Linux C利用Socket套接字进行服务器与多个客户端进行通讯

服务器端

#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <signal.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
//服务器端

void *fun_thrReceiveHandler(void *socketInfo);
void *fun_thrAcceptHandler(void *socketListen);
//1:是 0:否
int checkThrIsKill(pthread_t thr);

typedef struct MySocketInfo{
    int socketCon;
    char *ipaddr;
    uint16_t port;
}_MySocketInfo;

// 客户端数组
struct MySocketInfo arrConSocket[10];
int conClientCount = 0;

// 接受客户端线程列表
pthread_t arrThrReceiveClient[10];
int thrReceiveClientCount = 0;

int main()
{
    //初始化全局变量
    //memset(arrConSocket,0,sizeof(struct MySocketInfo)*10);

    printf("开始socket\n");
    /* 创建TCP连接的Socket套接字 */
    int socketListen = socket(AF_INET, SOCK_STREAM, 0);
    if(socketListen < 0){
        printf("创建TCP套接字失败\n");
        exit(-1);
    }else{
        printf("创建套接字成功\n");
    }
    /* 填充服务器端口地址信息,以便下面使用此地址和端口监听 */
    struct sockaddr_in server_addr;
    bzero(&server_addr,sizeof(struct sockaddr_in));
    server_addr.sin_family=AF_INET;
    server_addr.sin_addr.s_addr=htonl(INADDR_ANY); /* 这里地址使用全0,即所有 */
    server_addr.sin_port=htons(2000);
    if(bind(socketListen, (struct sockaddr *)&server_addr,sizeof(struct sockaddr)) != 0){
        perror("绑定ip地址、端口号失败\n");
        exit(-1);
    }else{
        printf("绑定ip地址,端口号\n");
    }
    /* 开始监听相应的端口 */
    if(listen(socketListen, 10) != 0){
        printf("开启监听失败\n");
        exit(-1);
    }else{
        printf("开启监听成功\n");
    }
    /* 接受连接套接字 */
    pthread_t thrAccept;
    pthread_create(&thrAccept,NULL,fun_thrAcceptHandler,&socketListen);

    /* 实时发送数据 */
    while(1){
        //判断线程存活多少
        int i;
        for(i=0;i<thrReceiveClientCount;i++){
            if(checkThrIsKill(arrThrReceiveClient[i]) == 1){
                printf("有个线程被杀了\n");
                thrReceiveClientCount--;
            }
        }
        printf("当前有接受数据线程多少个:%d\n",thrReceiveClientCount);

        // 可以录入用户操作选项,并进行相应操作
        char userStr[30] = {'0'};
        scanf("%s",userStr);
        if(strcmp(userStr,"q") == 0){
            printf("用户选择退出!\n");
            break;
        }
        // 发送消息
        if(conClientCount <= 0){
            printf("没有客户端连接\n");
        }else{
            int i;
            for(i=0; i<conClientCount; i++){
                //int sendMsg_len = send(arrConSocket[i].socketCon, userStr, 30, 0);
                int sendMsg_len = write(arrConSocket[i].socketCon,userStr,30);
                if(sendMsg_len > 0){
                    printf("向%s:%d发送成功\n",arrConSocket[i].ipaddr,arrConSocket[i].port);
                }else{
                    printf("向%s:%d发送失败\n",arrConSocket[i].ipaddr,arrConSocket[i].port);
                }
            }
        }

        sleep(0.5);
    }

    // 等待子进程退出
    printf("等待子线程退出,即将退出!\n");
    char *message;
    pthread_join(thrAccept,(void *)&message);
    printf("%s\n",message);

    return 0;
}

void *fun_thrReceiveHandler(void *socketCon){
    char buffer[30];
    int buffer_length;
    int _socketCon;
    while(1){
        //添加对buffer清零
        bzero(&buffer,sizeof(buffer));
        _socketCon = *((int *)socketCon);
        sleep(0.1);
        printf("接受数据线程中,连接套接字为%d\n",_socketCon);

        buffer_length = read(_socketCon,buffer,30);
        if(buffer_length == 0){
            printf("%d 客户端关闭\n",_socketCon);
            conClientCount--;
            break;
        }else if(buffer_length < 0){
            printf("接受客户端数据失败\n");
            break;
        }
        buffer[buffer_length] = '\0';
        printf("%d 说:%s\n",_socketCon,buffer);

        //获取当前线程id
        //printf("当前线程id:%ld",pthread_self());

        sleep(0.2);
    }
    printf("接受数据线程结束了\n");
    return NULL;
}

void *fun_thrAcceptHandler(void *socketListen){
    while(1){
        int sockaddr_in_size = sizeof(struct sockaddr_in);
        struct sockaddr_in client_addr;
        int _socketListen = *((int *)socketListen);
        int socketCon = accept(_socketListen, (struct sockaddr *)(&client_addr), (socklen_t *)(&sockaddr_in_size));
        if(socketCon < 0){
            printf("连接失败\n");
        }else{
            printf("连接成功 ip: %s:%d\r\n",inet_ntoa(client_addr.sin_addr),client_addr.sin_port);
        }
        printf("连接套接字为:%d\n",socketCon);
        //开启新的通讯线程,负责同连接上来的客户端进行通讯
        _MySocketInfo socketInfo;
        socketInfo.socketCon = socketCon;
        socketInfo.ipaddr = inet_ntoa(client_addr.sin_addr);
        socketInfo.port = client_addr.sin_port;
        arrConSocket[conClientCount] = socketInfo;
        conClientCount++;
        printf("连接了%d个用户\n",conClientCount);

        pthread_t thrReceive = 0;
        pthread_create(&thrReceive,NULL,fun_thrReceiveHandler,&socketCon);
        arrThrReceiveClient[thrReceiveClientCount] = thrReceive;
        thrReceiveClientCount++;

        //让进程休息1秒
        sleep(0.5);
    }

    char *s = "安全退出接受进程";
    pthread_exit(s);
}

int checkThrIsKill(pthread_t thr){
    int res = 1;
    int res_kill = pthread_kill(thr,0);
    if(res_kill == 0){
        res = 0;
    }
    return res;
}

客户端

#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>

typedef struct MySocketInfo{
    int socketCon;
    unsigned long ipaddr;
    unsigned short port;
}_MySocketInfo;

void *fun_thrReceiveHandler(void *socketCon);

int main()
{
    printf("开始socket\n");
    /* 创建TCP连接的Socket套接字 */
    int socketCon = socket(AF_INET, SOCK_STREAM, 0);
    if(socketCon < 0){
        printf("创建TCP连接套接字失败\n");
        exit(-1);
    }
    /* 填充客户端端口地址信息,以便下面使用此地址和端口监听 */
    struct sockaddr_in server_addr;
    bzero(&server_addr,sizeof(struct sockaddr_in));
    server_addr.sin_family=AF_INET;
    server_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
    server_addr.sin_port=htons(2000);
    printf("连接之前的socketCon:%d",socketCon);
    /* 连接服务器 */
    int res_con = connect(socketCon,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr));
    if(res_con != 0){
        printf("连接失败\n");
        exit(-1);
    }
    printf("连接成功\n");
    //开启新的实时接受数据线程
    pthread_t thrReceive;
    pthread_create(&thrReceive,NULL,fun_thrReceiveHandler,&socketCon);

    /* 实时发送数据 */
    while(1){
        //char userStr[30] = {'\0'};
        char *userStr = "woaini";
        // 可以录入用户操作选项,并进行相应操作
        //scanf("%s",userStr);
        //if(strcmp(userStr,"q") == 0){
            //printf("用户选择退出!\n");
            //break;
        //}
        // 发送消息
        //int sendMsg_len = send(socketCon, userStr, 30, 0);
        printf("-发送之前-\n");
        int sendMsg_len = write(socketCon,userStr,30);
        if(sendMsg_len > 0){
            printf("发送成功,客户端套接字:%d\n",socketCon);
        }else{
            printf("发送失败\n");
        }

        sleep(2);
    }

    // 关闭套接字
    close(socketCon);
    return 0;
}

void *fun_thrReceiveHandler(void *socketCon){
    while(1){
        char buffer[30];
        int _socketCon = *((int *)socketCon);
        //int buffer_length = recv(_socketCon,buffer,30,0);
        int buffer_length = read(_socketCon,buffer,30);
        buffer[buffer_length] = '\0';
        printf("服务器说:%s\n",buffer);
    }
    return NULL;
}

代码思路:服务器端:首先创建监听的套接字,然后创建用于(循环检测客户端连接)的新线程,当检测到有客户端连接,则创建一个新的线程负责同这个套接字通讯,即接受这个套接字发送过来的消息。

现象:单个客户端同服务器可以进行通讯,当连接上多个客户端过后,服务器端能够群发消息,最后连接的客户端向服务器发送的消息能够接受到,但之前的所有的客户端向服务器发送消息均不能收到。

解决思路:先使用排除法,首先找到了一份正确的客户端代码,连接上我自己写的服务器,也出现了同样的错误,所以可以排除我自己写的客户端。最终到了服务器端。服务器中,因为单个客户端可以与服务器通讯,所以检测连接的线程没有问题,那么最终归结到了循环接受客户端数据的线程。那着正确的服务器接受客户端数据的代码同自己写的对照,哈哈,发现了问题,是_socketCon值的问题,_socketCon的赋值是通过指针,然后打印这个值,发现这个值在不断变化,并且在检测连接的线程中定义的
int socketCon 值正是这个,而这个值是在 while死循环中不停的创建,不停的销毁!哇咔咔,真相终于大白与天下,功夫不负有心人啊,查了一天半的bug终于被我查出来了!

总结:

1、在死循环中切记不要定义变量,最好是在死循环之外定义变量,在死循环中使用!

2、在函数有死循环时,值只有一个的局部变量,就在死循环之上定义并初始化!就不要在死循环中赋值,只是去使用它就好了!

3、在创建多线程给多线程处理函数传参数中,切记不要传入生命周期较短的指针变量,传入值类型都好!

服务器与多个客户端通讯的正确代码如下:

服务器端

#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <signal.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
//服务器端

void *fun_thrReceiveHandler(void *socketInfo);
void *fun_thrAcceptHandler(void *socketListen);
//1:是 0:否
int checkThrIsKill(pthread_t thr);

typedef struct MySocketInfo{
    int socketCon;
    char *ipaddr;
    uint16_t port;
}_MySocketInfo;

// 客户端数组
struct MySocketInfo arrConSocket[10];
int conClientCount = 0;

// 接受客户端线程列表
pthread_t arrThrReceiveClient[10];
int thrReceiveClientCount = 0;

int main()
{
    //初始化全局变量
    //memset(arrConSocket,0,sizeof(struct MySocketInfo)*10);

    printf("开始socket\n");
    /* 创建TCP连接的Socket套接字 */
    int socketListen = socket(AF_INET, SOCK_STREAM, 0);
    if(socketListen < 0){
        printf("创建TCP套接字失败\n");
        exit(-1);
    }else{
        printf("创建套接字成功\n");
    }
    /* 填充服务器端口地址信息,以便下面使用此地址和端口监听 */
    struct sockaddr_in server_addr;
    bzero(&server_addr,sizeof(struct sockaddr_in));
    server_addr.sin_family=AF_INET;
    server_addr.sin_addr.s_addr=htonl(INADDR_ANY); /* 这里地址使用全0,即所有 */
    server_addr.sin_port=htons(2000);
    if(bind(socketListen, (struct sockaddr *)&server_addr,sizeof(struct sockaddr)) != 0){
        perror("绑定ip地址、端口号失败\n");
        exit(-1);
    }else{
        printf("绑定ip地址,端口号\n");
    }
    /* 开始监听相应的端口 */
    if(listen(socketListen, 10) != 0){
        printf("开启监听失败\n");
        exit(-1);
    }else{
        printf("开启监听成功\n");
    }
    /* 接受连接套接字 */
    pthread_t thrAccept;
    pthread_create(&thrAccept,NULL,fun_thrAcceptHandler,&socketListen);

    /* 实时发送数据 */
    while(1){
        //判断线程存活多少
        int i;
        for(i=0;i<thrReceiveClientCount;i++){
            if(checkThrIsKill(arrThrReceiveClient[i]) == 1){
                printf("有个线程被杀了\n");
                thrReceiveClientCount--;
            }
        }
        printf("当前有接受数据线程多少个:%d\n",thrReceiveClientCount);

        // 可以录入用户操作选项,并进行相应操作
        char userStr[30] = {'0'};
        scanf("%s",userStr);
        if(strcmp(userStr,"q") == 0){
            printf("用户选择退出!\n");
            break;
        }
        // 发送消息
        if(conClientCount <= 0){
            printf("没有客户端连接\n");
        }else{
            int i;
            for(i=0; i<conClientCount; i++){
                //int sendMsg_len = send(arrConSocket[i].socketCon, userStr, 30, 0);
                int sendMsg_len = write(arrConSocket[i].socketCon,userStr,30);
                if(sendMsg_len > 0){
                    printf("向%s:%d发送成功\n",arrConSocket[i].ipaddr,arrConSocket[i].port);
                }else{
                    printf("向%s:%d发送失败\n",arrConSocket[i].ipaddr,arrConSocket[i].port);
                }
            }
        }

        sleep(0.5);
    }

    // 等待子进程退出
    printf("等待子线程退出,即将退出!\n");
    char *message;
    pthread_join(thrAccept,(void *)&message);
    printf("%s\n",message);

    return 0;
}

void *fun_thrAcceptHandler(void *socketListen){
    while(1){
        int sockaddr_in_size = sizeof(struct sockaddr_in);
        struct sockaddr_in client_addr;
        int _socketListen = *((int *)socketListen);
        int socketCon = accept(_socketListen, (struct sockaddr *)(&client_addr), (socklen_t *)(&sockaddr_in_size));
        if(socketCon < 0){
            printf("连接失败\n");
        }else{
            printf("连接成功 ip: %s:%d\r\n",inet_ntoa(client_addr.sin_addr),client_addr.sin_port);
        }
        printf("连接套接字为:%d\n",socketCon);
        //开启新的通讯线程,负责同连接上来的客户端进行通讯
        _MySocketInfo socketInfo;
        socketInfo.socketCon = socketCon;
        socketInfo.ipaddr = inet_ntoa(client_addr.sin_addr);
        socketInfo.port = client_addr.sin_port;
        arrConSocket[conClientCount] = socketInfo;
        conClientCount++;
        printf("连接了%d个用户\n",conClientCount);

        pthread_t thrReceive = 0;
        pthread_create(&thrReceive,NULL,fun_thrReceiveHandler,&socketInfo);
        arrThrReceiveClient[thrReceiveClientCount] = thrReceive;
        thrReceiveClientCount++;

        //让进程休息1秒
        sleep(0.5);
    }

    char *s = "安全退出接受进程";
    pthread_exit(s);
}

void *fun_thrReceiveHandler(void *socketInfo){
	char buffer[30];
	int buffer_length;
	_MySocketInfo _socketInfo = *((_MySocketInfo *)socketInfo);
    while(1){
    	//添加对buffer清零
    	bzero(&buffer,sizeof(buffer));

        buffer_length = read(_socketInfo.socketCon,buffer,30);
        if(buffer_length == 0){
            printf("%s:%d 客户端关闭\n",_socketInfo.ipaddr,_socketInfo.port);
            conClientCount--;
            break;
        }else if(buffer_length < 0){
            printf("接受客户端数据失败\n");
            break;
        }
        buffer[buffer_length] = '\0';
        printf("%s:%d 说:%s\n",_socketInfo.ipaddr,_socketInfo.port,buffer);

        sleep(0.2);
    }
    printf("接受数据线程结束了\n");
    return NULL;
}

int checkThrIsKill(pthread_t thr){
    int res = 1;
    int res_kill = pthread_kill(thr,0);
    if(res_kill == 0){
        res = 0;
    }
    return res;
}
#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <signal.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
//服务器端

void *fun_thrReceiveHandler(void *socketInfo);
void *fun_thrAcceptHandler(void *socketListen);
//1:是 0:否
int checkThrIsKill(pthread_t thr);

typedef struct MySocketInfo{
    int socketCon;
    char *ipaddr;
    uint16_t port;
}_MySocketInfo;

// 客户端数组
struct MySocketInfo arrConSocket[10];
int conClientCount = 0;

// 接受客户端线程列表
pthread_t arrThrReceiveClient[10];
int thrReceiveClientCount = 0;

int main()
{
    //初始化全局变量
    //memset(arrConSocket,0,sizeof(struct MySocketInfo)*10);

    printf("开始socket\n");
    /* 创建TCP连接的Socket套接字 */
    int socketListen = socket(AF_INET, SOCK_STREAM, 0);
    if(socketListen < 0){
        printf("创建TCP套接字失败\n");
        exit(-1);
    }else{
        printf("创建套接字成功\n");
    }
    /* 填充服务器端口地址信息,以便下面使用此地址和端口监听 */
    struct sockaddr_in server_addr;
    bzero(&server_addr,sizeof(struct sockaddr_in));
    server_addr.sin_family=AF_INET;
    server_addr.sin_addr.s_addr=htonl(INADDR_ANY); /* 这里地址使用全0,即所有 */
    server_addr.sin_port=htons(2000);
    if(bind(socketListen, (struct sockaddr *)&server_addr,sizeof(struct sockaddr)) != 0){
        perror("绑定ip地址、端口号失败\n");
        exit(-1);
    }else{
        printf("绑定ip地址,端口号\n");
    }
    /* 开始监听相应的端口 */
    if(listen(socketListen, 10) != 0){
        printf("开启监听失败\n");
        exit(-1);
    }else{
        printf("开启监听成功\n");
    }
    /* 接受连接套接字 */
    pthread_t thrAccept;
    pthread_create(&thrAccept,NULL,fun_thrAcceptHandler,&socketListen);

    /* 实时发送数据 */
    while(1){
        //判断线程存活多少
        int i;
        for(i=0;i<thrReceiveClientCount;i++){
            if(checkThrIsKill(arrThrReceiveClient[i]) == 1){
                printf("有个线程被杀了\n");
                thrReceiveClientCount--;
            }
        }
        printf("当前有接受数据线程多少个:%d\n",thrReceiveClientCount);

        // 可以录入用户操作选项,并进行相应操作
        char userStr[30] = {'0'};
        scanf("%s",userStr);
        if(strcmp(userStr,"q") == 0){
            printf("用户选择退出!\n");
            break;
        }
        // 发送消息
        if(conClientCount <= 0){
            printf("没有客户端连接\n");
        }else{
            int i;
            for(i=0; i<conClientCount; i++){
                //int sendMsg_len = send(arrConSocket[i].socketCon, userStr, 30, 0);
                int sendMsg_len = write(arrConSocket[i].socketCon,userStr,30);
                if(sendMsg_len > 0){
                    printf("向%s:%d发送成功\n",arrConSocket[i].ipaddr,arrConSocket[i].port);
                }else{
                    printf("向%s:%d发送失败\n",arrConSocket[i].ipaddr,arrConSocket[i].port);
                }
            }
        }

        sleep(0.5);
    }

    // 等待子进程退出
    printf("等待子线程退出,即将退出!\n");
    char *message;
    pthread_join(thrAccept,(void *)&message);
    printf("%s\n",message);

    return 0;
}

void *fun_thrAcceptHandler(void *socketListen){
    while(1){
        int sockaddr_in_size = sizeof(struct sockaddr_in);
        struct sockaddr_in client_addr;
        int _socketListen = *((int *)socketListen);
        int socketCon = accept(_socketListen, (struct sockaddr *)(&client_addr), (socklen_t *)(&sockaddr_in_size));
        if(socketCon < 0){
            printf("连接失败\n");
        }else{
            printf("连接成功 ip: %s:%d\r\n",inet_ntoa(client_addr.sin_addr),client_addr.sin_port);
        }
        printf("连接套接字为:%d\n",socketCon);
        //开启新的通讯线程,负责同连接上来的客户端进行通讯
        _MySocketInfo socketInfo;
        socketInfo.socketCon = socketCon;
        socketInfo.ipaddr = inet_ntoa(client_addr.sin_addr);
        socketInfo.port = client_addr.sin_port;
        arrConSocket[conClientCount] = socketInfo;
        conClientCount++;
        printf("连接了%d个用户\n",conClientCount);

        pthread_t thrReceive = 0;
        pthread_create(&thrReceive,NULL,fun_thrReceiveHandler,&socketInfo);
        arrThrReceiveClient[thrReceiveClientCount] = thrReceive;
        thrReceiveClientCount++;

        //让进程休息1秒
        sleep(0.5);
    }

    char *s = "安全退出接受进程";
    pthread_exit(s);
}

void *fun_thrReceiveHandler(void *socketInfo){
	char buffer[30];
	int buffer_length;
	_MySocketInfo _socketInfo = *((_MySocketInfo *)socketInfo);
    while(1){
    	//添加对buffer清零
    	bzero(&buffer,sizeof(buffer));

        buffer_length = read(_socketInfo.socketCon,buffer,30);
        if(buffer_length == 0){
            printf("%s:%d 客户端关闭\n",_socketInfo.ipaddr,_socketInfo.port);
            conClientCount--;
            break;
        }else if(buffer_length < 0){
            printf("接受客户端数据失败\n");
            break;
        }
        buffer[buffer_length] = '\0';
        printf("%s:%d 说:%s\n",_socketInfo.ipaddr,_socketInfo.port,buffer);

        sleep(0.2);
    }
    printf("接受数据线程结束了\n");
    return NULL;
}

int checkThrIsKill(pthread_t thr){
    int res = 1;
    int res_kill = pthread_kill(thr,0);
    if(res_kill == 0){
        res = 0;
    }
    return res;
}

客户端

#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>

typedef struct MySocketInfo{
    int socketCon;
    unsigned long ipaddr;
    unsigned short port;
}_MySocketInfo;

void *fun_thrReceiveHandler(void *socketCon);
int checkThrIsKill(pthread_t thr);

int main()
{
    printf("开始socket\n");
    /* 创建TCP连接的Socket套接字 */
    int socketCon = socket(AF_INET, SOCK_STREAM, 0);
    if(socketCon < 0){
        printf("创建TCP连接套接字失败\n");
        exit(-1);
    }
    /* 填充客户端端口地址信息,以便下面使用此地址和端口监听 */
    struct sockaddr_in server_addr;
    bzero(&server_addr,sizeof(struct sockaddr_in));
    server_addr.sin_family=AF_INET;
    server_addr.sin_addr.s_addr=inet_addr("127.0.0.1"); /* 这里地址使用全0,即所有 */
    server_addr.sin_port=htons(2000);
    /* 连接服务器 */
    int res_con = connect(socketCon,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr));
    if(res_con != 0){
        printf("连接失败\n");
        exit(-1);
    }
    printf("连接成功,连接结果为:%d\n",res_con);
    //开启新的实时接受数据线程
    pthread_t thrReceive;
    pthread_create(&thrReceive,NULL,fun_thrReceiveHandler,&socketCon);

    /* 实时发送数据 */
    while(1){
        //检测接受服务器数据线程是否被杀死

        char userStr[30] = {'0'};
        // 可以录入用户操作选项,并进行相应操作
        scanf("%s",userStr);
        if(strcmp(userStr,"q") == 0){
            printf("用户选择退出!\n");
            break;
        }
        // 发送消息
        //int sendMsg_len = send(socketCon, userStr, 30, 0);
        int sendMsg_len = write(socketCon,userStr,30);
        if(sendMsg_len > 0){
            printf("发送成功,服务端套接字句柄:%d\n",socketCon);
        }else{
            printf("发送失败\n");
        }

        //if(checkThrIsKill(thrReceive) == 1){
            //printf("接受服务器数据的线程已被关闭,退出程序\n");
            //break;
        //}
    }
    // 关闭套接字
    close(socketCon);
    return 0;
}

void *fun_thrReceiveHandler(void *socketCon){
    while(1){
        char buffer[30];
        int _socketCon = *((int *)socketCon);
        //int buffer_length = recv(_socketCon,buffer,30,0);
        int buffer_length = read(_socketCon,buffer,30);
        if(buffer_length == 0){
            printf("服务器端异常关闭\n");
            exit(-1);
        }else if(buffer_length < 0){
            printf("接受客户端数据失败\n");
            break;
        }
        buffer[buffer_length] = '\0';
        printf("服务器说:%s\n",buffer);
    }
    printf("退出接受服务器数据线程\n");
    return NULL;
}

int checkThrIsKill(pthread_t thr){
    int res = 1;
    int res_kill = pthread_kill(thr,0);
    if(res_kill == 0){
        res = 0;
    }
    return res;
}
时间: 2024-12-21 13:36:49

Linux C利用Socket套接字进行服务器与多个客户端进行通讯的相关文章

19、网络编程 (Socket套接字编程)

网络模型 *A:网络模型 TCP/IP协议中的四层分别是应用层.传输层.网络层和链路层,每层分别负责不同的通信功能,接下来针对这四层进行详细地讲解. 链路层:链路层是用于定义物理传输通道,通常是对某些网络连接设备的驱动协议,例如针对光纤.网线提供的驱动. 网络层:网络层是整个TCP/IP协议的核心,它主要用于将传输的数据进行分组,将分组数据发送到目标计算机或者网络. 传输层:主要使网络程序进行通信,在进行网络通信时,可以采用TCP协议,也可以采用UDP协议. 应用层:主要负责应用程序的协议,例如

linux网络环境下socket套接字编程(UDP文件传输)

今天我们来介绍一下在linux网络环境下使用socket套接字实现两个进程下文件的上传,下载,和退出操作! 在socket套接字编程中,我们当然可以基于TCP的传输协议来进行传输,但是在文件的传输中,如果我们使用TCP传输,会造成传输速度较慢的情况,所以我们在进行文件传输的过程中,最好要使用UDP传输. 在其中,我们需要写两个程序,一个客户端,一个服务端,在一个终端中,先运行服务端,在运行客户端,在服务端和客户端都输入IP地址和端口号,注意服务端和客户端的端口号要相同,然后选择功能,在linux

linux网络编程-(socket套接字编程UDP传输)

今天我们来介绍一下在linux网络环境下使用socket套接字实现两个进程下文件的上传,下载,和退出操作! 在socket套接字编程中,我们当然可以基于TCP的传输协议来进行传输,但是在文件的传输中,如果我们使用TCP传输,会造成传输速度较慢的情况,所以我们在进行文件传输的过程中,最好要使用UDP传输. 在其中,我们需要写两个程序,一个客户端,一个服务端,在一个终端中,先运行服务端,在运行客户端,在服务端和客户端都输入IP地址和端口号,注意服务端和客户端的端口号要相同,然后选择功能,在linux

利用原始套接字实现一个简单的采集网络数据包

//利用原始套接字实现一个简单的采集网络数据包,并进行反向解析IP,MAC地址#include <stdio.h>#include <sys/socket.h>#include <unistd.h>#include <sys/types.h>#include <linux/if_ether.h>#include <linux/in.h> #define BUFFER_MAX 2048 int main(int argc, char *

Python开发基础-Day23try异常处理、socket套接字基础1

异常处理 错误 程序里的错误一般分为两种: 1.语法错误,这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正 2.逻辑错误,人为造成的错误,如数据类型错误.调用方法错误等,这些解释器是不会进行检测的,只有在执行的过程中才能抛出的错误 异常 异常是python解释器在运行程序的过程中遇到错误所抛出的信息,如: Python异常种类: 常用异常: 1 AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x 2 IOError 输入/输出异

Linux网络编程——原始套接字实例:简单版网络数据分析器

通过<Linux网络编程--原始套接字编程>得知,我们可以通过原始套接字以及 recvfrom( ) 可以获取链路层的数据包,那我们接收的链路层数据包到底长什么样的呢? 链路层封包格式 MAC 头部(有线局域网) 注意:CRC.PAD 在组包时可以忽略 链路层数据包的其中一种情况: unsigned char msg[1024] = { //--------------组MAC--------14------ 0xb8, 0x88, 0xe3, 0xe1, 0x10, 0xe6, // dst

Linux网络编程和套接字

1.套接字概述 套接字的本意是插座,在网络中用来描述计算机中不同程序与其他计算机程序的通信方式. 常用的套接字类型有3种: 1)流套接字(SOCK--STREAM):使用了面向连接的可靠的数据通信方式,即TCP套接字: 2)数据报套接字(Raw Sockets):使用了不面向连接的数据传输方式,即UDP套接字: 3)原始套接字(SOCK--RAW):没有经过处理的IP数据包,可以根据自己程序的要求进行封装. 2.常用函数 1.创建套接字函数:成功时返回文件描述符,失败时返回-1 int sock

Python开发基础----异常处理、socket套接字基础1

异常处理 错误 程序里的错误一般分为两种: 1.语法错误,这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正 2.逻辑错误,人为造成的错误,如数据类型错误.调用方法错误等,这些解释器是不会进行检测的,只有在执行的过程中才能抛出的错误 异常 异常是python解释器在运行程序的过程中遇到错误所抛出的信息,如: Python异常种类: 常用异常: 1 AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x 2 IOError 输入/输出异

python基础之try异常处理、socket套接字基础part1

异常处理 错误 程序里的错误一般分为两种: 1.语法错误,这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正 2.逻辑错误,人为造成的错误,如数据类型错误.调用方法错误等,这些解释器是不会进行检测的,只有在执行的过程中才能抛出的错误 异常 异常是python解释器在运行程序的过程中遇到错误所抛出的信息,如: Python异常种类: 常用异常: 1 AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x 2 IOError 输入/输出异