zoukankan      html  css  js  c++  java
  • socket利用多线程实现一对多通信

    1、服务器端:socket()建立套接字,绑定(bind)并监听(listen),用accept()等待客户端连接。将accept()写入死循环,每次连接一个客户端,开一个线程。

    2、一般情况下建立socket连接后服务器与客户端建立了一个管道,当关闭socket或关闭客户端的时候,会导致管道破裂信号。如果使用默认处理则会导致服务器程序退出。

    需要程序忽略管道破裂信号。

    signal(SIGPIPE, SIG_IGN);//忽略管道破裂信号

    3、线程处理完毕后,需要及时关闭线程,通过recv()函数的特性,在socket关闭的时候返回零。判断并结束线程。

    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <pthread.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <signal.h>  //处理信号问题 应忽略socket 信号
    
    #define MY_IP     "192.168.149.137"
    #define MY_PORT  5005
    #define BACKLOG  100
    
    #define DEBUF(X) printf(X)
    int fd = -1;
    char buf[100];    //最大连接数
    void *func(void *arg)
    {    char recv_buf[100];
        char send_buf[100];
        int client_fd = (int)arg;//传参
        int ret = 1;
        memset(recv_buf,0,sizeof(recv_buf));
        while(1)
        {
            ret = recv(client_fd,&recv_buf,sizeof(recv_buf),0);
            if(0 == ret) break;//阻塞等待过程中断开则会返回0
            printf("%s
    ",recv_buf); 
            send(client_fd,&recv_buf,sizeof(recv_buf),0);
            memset(recv_buf,0,sizeof(recv_buf));        
        }
        printf("over 
    ");
    }
     int main()
    {    
        struct sockaddr_in server_addr;
        struct sockaddr_in client_addr;//客户地址
        socklen_t len = 0;//接收长度
        char recv_buf[100];
        char send_buf[100];
        int sock_fd = -1;//监听描述符
        int client_fd = -1;//连接fd
    
        int ret = -1;
        pthread_t th =-1 ;
        
        signal(SIGPIPE, SIG_IGN);//忽略管道破裂信号
        sock_fd = socket(AF_INET,SOCK_STREAM,0);
        if(-1 == sock_fd)
        {
            perror("socket");
            return -1;
        }
        printf("sock_fd = %d.
    ",sock_fd);
        //2.bind绑定socket 和本机IP 端口
        server_addr.sin_family = AF_INET;//IPV4
        server_addr.sin_port = htons(MY_PORT);//设置端口模式
        server_addr.sin_addr.s_addr = inet_addr(MY_IP);//设置IP
        ret = bind(sock_fd,(struct  sockaddr  *)&server_addr,sizeof(server_addr));
        if(-1 == ret)
        {
            perror("bind");
            return -1;
        }
        DEBUF("bind ok
    ");
        //3.listen 设 置监听
        ret = listen(sock_fd, BACKLOG);//BACKLOG为排队处理
        if(-1 == ret)
        {
            perror("listen");
            return -1;
        }
        DEBUF("listen ok
    ");
        while(1)
        {
            client_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &len);
            if(-1 == client_fd)
            {
                perror("listen");
                return -1;
            }
            ret = pthread_create(&th ,NULL , func , (void*)client_fd);//创建线程
            DEBUF("新用户加入
    ");
             if(ret != 0)
            {
                printf("pthread_create error 
    ");
                return -1;
            } 
        }
        return 0;
    }
  • 相关阅读:
    2021.3.3
    2021.3.2
    2021.3.1
    2021.2.28(每周总结)
    2021.2.27
    2021.2.26
    2021.2.25
    2021.2.23
    Redis系统学习之五大基本数据类型(List(列表))
    Redis系统学习之五大基本数据类型(String(字符串))
  • 原文地址:https://www.cnblogs.com/PengfeiSong/p/6796338.html
Copyright © 2011-2022 走看看