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\n",recv_buf); 
        send(client_fd,&recv_buf,sizeof(recv_buf),0);
        memset(recv_buf,0,sizeof(recv_buf));        
    }
    printf("over \n");
}
 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.\n",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\n");
    //3.listen 設 置監聽
    ret = listen(sock_fd, BACKLOG);//BACKLOG為排隊處理
    if(-1 == ret)
    {
        perror("listen");
        return -1;
    }
    DEBUF("listen ok\n");
    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("新用戶加入\n");
         if(ret != 0)
        {
            printf("pthread_create error \n");
            return -1;
        } 
    }
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM