当前位置: 首页 > article >正文

重头开始嵌入式第三十二天(TCP多客户端模型)

1.多路IO

1.select

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
/* According to POSIX.1-2001, POSIX.1-2008 */
#include <sys/select.h>

/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
typedef struct sockaddr* (SA);
int main(int argc, char *argv[])
{
    //监听套接字
    int listfd = socket(AF_INET,SOCK_STREAM,0 );
    if(-1 ==listfd)
    {
        perror("socket");
        exit(1);
    }
    struct sockaddr_in ser,cli;
    bzero(&ser,sizeof(ser));
    bzero(&cli,sizeof(cli));
    ser.sin_family = AF_INET;
    ser.sin_port = htons(50000);
    ser.sin_addr.s_addr =inet_addr("127.0.0.1");

    //man 7 socket 
    int on = 1;
    setsockopt(listfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
    setsockopt(listfd,SOL_SOCKET,SO_REUSEPORT,&on,sizeof(on));
    int ret = bind(listfd,(SA)&ser,sizeof(ser));
    if(-1 ==ret)
    {
        perror("bind");
        exit(1);
    }
    //建立连接的排队数
    listen(listfd,3);
    socklen_t len = sizeof(cli);
    //1 create set 
    fd_set rd_set,tmp_set;
    FD_ZERO(&rd_set);
    FD_ZERO(&tmp_set);
    //2.add fd  
    FD_SET(listfd,&tmp_set);
    int maxfd = listfd;
    while(1)
    {   
        rd_set = tmp_set;
        select(maxfd+1,&rd_set,NULL,NULL,NULL);
        int i = 0 ;
        //通讯套接字
        for(i = 0 ;i<maxfd+1;i++)
        {
            if(FD_ISSET(i,&rd_set) && i ==listfd)
            {
                int conn = accept(listfd,(SA)&cli,&len);
                if(-1 == conn)
                {
                    perror("accept");
                    // exit(1);
                    continue;
                }

                FD_SET(conn,&tmp_set);
                if(conn>maxfd)
                    maxfd = conn;
            }
            if(FD_ISSET(i,&rd_set) && i!=listfd)
            {
                int conn = i ;
                char buf[512]={0};
                int rd_ret = recv(conn,buf,sizeof(buf),0);
                if(rd_ret<=0)
                {
                    FD_CLR(conn,&tmp_set);
                    close(conn);
                    printf("cli offline\n");
                    break;
                }
                //printf("cli:%s\n",buf);
                time_t tm;
                time(&tm);
                sprintf(buf,"%s %s",buf,ctime(&tm));
                send(conn,buf,strlen(buf),0);
            }
        }
    }
    close(listfd);
    return 0;
}

2.epoll

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
 #include <sys/epoll.h>
typedef struct sockaddr* (SA);
int add_fd(int epfd,int fd)
{
    struct epoll_event ev;
    ev.events = EPOLLIN;
    ev.data.fd = fd;
    int ret = epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&ev);
    if(-1 == ret)
    {
        perror("add fd");
    }
    return ret;
}
int del_fd(int epfd,int fd)
{
    struct epoll_event ev;
    ev.events = EPOLLIN;
    ev.data.fd = fd;
    int ret = epoll_ctl(epfd,EPOLL_CTL_DEL,fd,&ev);
    if(-1 == ret)
    {
        perror("add fd");
    }
    return ret;
}

int main(int argc, char *argv[])
{
    //监听套接字
    int listfd = socket(AF_INET,SOCK_STREAM,0 );
    if(-1 ==listfd)
    {
        perror("socket");
        exit(1);
    }
    struct sockaddr_in ser,cli;
    bzero(&ser,sizeof(ser));
    bzero(&cli,sizeof(cli));
    ser.sin_family = AF_INET;
    ser.sin_port = htons(50000);
    ser.sin_addr.s_addr =inet_addr("127.0.0.1");

    //man 7 socket 
    int on = 1;
    setsockopt(listfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
    setsockopt(listfd,SOL_SOCKET,SO_REUSEPORT,&on,sizeof(on));
    int ret = bind(listfd,(SA)&ser,sizeof(ser));
    if(-1 ==ret)
    {
        perror("bind");
        exit(1);
    }
    //建立连接的排队数
    listen(listfd,3);
    socklen_t len = sizeof(cli);

    struct epoll_event rev[10]={0};
    //1 create set 
    int epfd = epoll_create(10);
    if(-1 == epfd)
    {
        perror("epoll_create");
        return 1;
    }
    // 2 .add fd  
    
    add_fd(epfd,listfd);
    while(1)
    {    
        //3 wait event 
        int ep_ret = epoll_wait(epfd,rev,10,-1);
        int i = 0 ;
        //4 find fd handle
        for(i = 0 ;i<ep_ret;i++)
        {

            if(rev[i].data.fd == listfd)
            {    //通讯套接字
                int conn = accept(listfd,(SA)&cli,&len);
                if(-1 == conn)
                {
                    perror("accept");
                    continue;
                }
                add_fd(epfd,conn);
            }
            else 
            {
                int conn = rev[i].data.fd;
                char buf[512]={0};
                int rd_ret = recv(conn,buf,sizeof(buf),0);
                if(rd_ret<=0)
                {
                    del_fd(epfd,conn);
                    close(conn);
                    break;
                }
                time_t tm;
                time(&tm);
                sprintf(buf,"%s %s",buf,ctime(&tm));
                send(conn,buf,strlen(buf),0);
            }
        }
    }
    close(listfd);
    return 0;
}

2.并发模型

1.进程

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
#include <signal.h>
#include <sys/wait.h>
typedef struct sockaddr* (SA);
void handle(int num)
{
    wait(NULL);
}
int main(int argc, char *argv[])
{
    signal(SIGCHLD,handle);
    //监听套接字
    int listfd = socket(AF_INET,SOCK_STREAM,0 );
    if(-1 ==listfd)
    {
        perror("socket");
        exit(1);
    }
    struct sockaddr_in ser,cli;
    bzero(&ser,sizeof(ser));
    bzero(&cli,sizeof(cli));
    ser.sin_family = AF_INET;
    ser.sin_port = htons(50000);
    ser.sin_addr.s_addr =inet_addr("127.0.0.1");

    //man 7 socket 
    int on = 1;
    setsockopt(listfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
    setsockopt(listfd,SOL_SOCKET,SO_REUSEPORT,&on,sizeof(on));
    int ret = bind(listfd,(SA)&ser,sizeof(ser));
    if(-1 ==ret)
    {
        perror("bind");
        exit(1);
    }
    //建立连接的排队数
    listen(listfd,3);
    socklen_t len = sizeof(cli);
    while(1)
    {

        //通讯套接字
        int conn = accept(listfd,(SA)&cli,&len);
        if(-1 == conn)
        {
            perror("accept");
            //exit(1);
            continue;
        }
        pid_t pid = fork();
        if(0 == pid)
        {
                close(listfd);
            while(1)
            {
                char buf[512]={0};
                int rd_ret = recv(conn,buf,sizeof(buf),0);
                if(rd_ret<=0)
                {
                    printf("cli off line\n");
                    close(conn);
                    //break;
                    exit(1);
                }
                printf("cli:%s\n",buf);
                time_t tm;
                time(&tm);
                sprintf(buf,"%s %s",buf,ctime(&tm));
                send(conn,buf,strlen(buf),0);
            }
        }
        else if (pid>0)
        {
            close(conn);
        }
        else
        {
            printf("fork");
            continue;
        }
    }
    close(listfd);
    return 0;
}

2.线程

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
#include <signal.h>
#include <sys/wait.h>
#include <pthread.h>
typedef struct sockaddr* (SA);

void* th(void* arg)
{
    pthread_detach(pthread_self());
    int conn =* (int*)arg;
    //sem_post();
    while(1)
    {
        char buf[512]={0};
        int rd_ret = recv(conn,buf,sizeof(buf),0);
        if(rd_ret<=0)
        {
            printf("cli off line\n");
            close(conn);
            break;
        }
        printf("cli:%s\n",buf);
        time_t tm;
        time(&tm);
        sprintf(buf,"%s %s",buf,ctime(&tm));
        send(conn,buf,strlen(buf),0);
    }

    return NULL;
}
int main(int argc, char *argv[])
{
    //监听套接字
    int listfd = socket(AF_INET,SOCK_STREAM,0 );
    if(-1 ==listfd)
    {
        perror("socket");
        exit(1);
    }
    struct sockaddr_in ser,cli;
    bzero(&ser,sizeof(ser));
    bzero(&cli,sizeof(cli));
    ser.sin_family = AF_INET;
    ser.sin_port = htons(50000);
    ser.sin_addr.s_addr =inet_addr("127.0.0.1");

    //man 7 socket 
    int on = 1;
    setsockopt(listfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
    setsockopt(listfd,SOL_SOCKET,SO_REUSEPORT,&on,sizeof(on));
    int ret = bind(listfd,(SA)&ser,sizeof(ser));
    if(-1 ==ret)
    {
        perror("bind");
        exit(1);
    }
    //建立连接的排队数
    listen(listfd,3);
    socklen_t len = sizeof(cli);
    while(1)
    {
        //通讯套接字
        int conn = accept(listfd,(SA)&cli,&len);
        if(-1 == conn)
        {
            perror("accept");
            //exit(1);
            continue;
        }

        pthread_t tid;
        pthread_create(&tid,NULL,th,&conn);
        //sem_wait();
       // join();
       // 确保th中,把conn保存到局部变量中
       usleep(1000*5);
    }
    close(listfd);
    return 0;
}

3.循环

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <sys/socket.h>

#include <netinet/in.h>



#define PORT 8888

#define BUFFER_SIZE 1024



int main() {

    int server_fd, new_socket;

    struct sockaddr_in address;

    int addrlen = sizeof(address);

    char buffer[BUFFER_SIZE] = {0};



    // 创建服务器套接字

    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {

        perror("socket failed");

        exit(EXIT_FAILURE);

    }



    address.sin_family = AF_INET;

    address.sin_addr.s_addr = INADDR_ANY;

    address.sin_port = htons(PORT);



    // 绑定套接字到指定端口

    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {

        perror("bind failed");

        exit(EXIT_FAILURE);

    }



    // 监听连接

    if (listen(server_fd, 3) < 0) {

        perror("listen failed");

        exit(EXIT_FAILURE);

    }



    while (1) {

        // 接受新的连接

        if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {

            perror("accept failed");

            exit(EXIT_FAILURE);

        }



        while (1) {

            int valread = read(new_socket, buffer, BUFFER_SIZE);

            if (valread <= 0) {

                break;

            }

            printf("Received from client: %s\n", buffer);

            send(new_socket, buffer, strlen(buffer), 0);

            memset(buffer, 0, BUFFER_SIZE);

        }



        close(new_socket);

    }



    return 0;

}

 

 

 

 


http://www.kler.cn/a/289649.html

相关文章:

  • 【C++】类与对象的基础概念
  • Linux探秘坊-------1.系统核心的低语:基础指令的奥秘解析(1)
  • 腾讯云nginx SSL证书配置
  • Springboot整合Prometheus+grafana实现系统监控
  • 重新认识HTTPS
  • 将大型语言模型(如GPT-4)微调用于文本续写任务
  • 文件包含PHP伪协议利用方法
  • SEO外链自动发布外链工具网站源码
  • 深度学习应用 - 语音识别篇
  • 基于web知识库管理系统设计与实现
  • 通过EasyExcel设置自定义表头及设置特定单元格样式、颜色
  • C++:关于反向迭代器的学习分享
  • 缓存类型以及读写策略
  • RocketMQ高级特性三-消费者分类
  • java 常用并发队列- ArrayBlockingQueue
  • malab 将数据导入到excell文件代码的几种方法
  • LeetCode hot100刷题记录
  • LACP链路聚合
  • Android 9.0 SystemUI状态栏/快捷设置介绍
  • 【网络原理】Udp 的报文结构,保姆式教学,快速入门
  • 计算机网络 第2章 物理层
  • 多个Node.js版本之间切换
  • css spacing设置间距
  • redis缓存和数据库通过延迟双删除实现数据一致性
  • Ghidra逆向工具之旅与二进制代码分析【4】
  • 通过设置JVM参数来启用GC(垃圾回收)日志