C语言实现Linux网络套接字多线程通信

986 阅读1分钟

应用到的知识点

pthread
socket

运行环境

:~$ cat /proc/version
Linux version 4.15.0-109-generic (buildd@lgw01-amd64-010) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)) #110-Ubuntu SMP Tue Jun 23 02:39:32 UTC 2020

服务端

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

#define SERVER_PORT 9999

int cur_sockets = 0;

struct new_socket_args
{
    int server_socket_fd;
    socklen_t sin_size;
};

void *client_read(void* args){
    struct new_socket_args _new_socket_args = *((struct new_socket_args*)args);
    char* buffer = (char*)malloc(sizeof(char)*200);
        while (1)
        {
            memset(buffer,0,sizeof(char)*200);
            int len = recv(_new_socket_args.server_socket_fd,buffer,sizeof(char)*200,0);
            if(len >0){
                printf("recv %s\n",buffer);
                if(strncmp("bye",buffer,3) == 0){
                    printf("to close this socket \n");
                    break;
                }
            }
        }
        free(buffer);
        shutdown(_new_socket_args.server_socket_fd,SHUT_RDWR);
    return NULL;
}

void *newConnection(void *args){
    struct new_socket_args _new_socket_args = *((struct new_socket_args*)args);
    while (1)
    {
        struct sockaddr_in client_sockaddr_in;
        int client_socket_fd = accept(_new_socket_args.server_socket_fd,(struct sockaddr*)&client_sockaddr_in,&_new_socket_args.sin_size);
        printf("current conects ,%d\n",cur_sockets);
        //setsockopt
        if(client_socket_fd < 0){
            printf("new client connected failure\n");
             shutdown(_new_socket_args.server_socket_fd,SHUT_RDWR);
            return NULL;
        }
        cur_sockets++;
        printf("new client connected success,%d\n",cur_sockets);

        pthread_t tid;
        struct new_socket_args _new_socket_args = {client_socket_fd,sizeof(struct sockaddr_in)};
        pthread_create(&tid,NULL,client_read,&_new_socket_args);
        printf("enter client recv thread\n");
    }
    return NULL;
}

int main(){
    int server_socket_fd;
    struct sockaddr_in server_addr;
    memset(&server_addr,0,sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(SERVER_PORT);
    server_socket_fd = socket(PF_INET,SOCK_STREAM,0);
    if(server_socket_fd < 0){
        printf("server socket create failure\n");
        return -1;
    }
    printf("server socket create success\n");

    int reuse = 1;
    setsockopt(server_socket_fd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(int));//这个设置很重要
    bind(server_socket_fd,(struct sockaddr*)&server_addr,sizeof(server_addr));
    int retListen;
    retListen = listen(server_socket_fd,6);
    if(retListen<0){
        shutdown(server_socket_fd,SHUT_RDWR);
        //close(server_socket_fd);
        return -1;
    }

    pthread_t tid;
    struct new_socket_args _new_socket_args = {server_socket_fd,sizeof(struct sockaddr_in)};
    pthread_create(&tid,NULL,newConnection,&_new_socket_args);
    pthread_join(tid,NULL);
    shutdown(server_socket_fd,SHUT_RDWR);
    return 0;
}

客户端

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>

#define SERVER_PORT 9999

int main(){
    int client_socket_fd;
    struct sockaddr_in  server_addr;        
    memset(&server_addr,0,sizeof(server_addr ));      
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(SERVER_PORT);
    client_socket_fd = socket(PF_INET,SOCK_STREAM,0);
    if(client_socket_fd < 0){
        printf("create client socket failure\n");
        return -1;
    }

    int con_result = connect(client_socket_fd,(struct sockaddr*)&server_addr,sizeof(server_addr));
    if(con_result<0){
        printf("connect failure\n");
        return -1;
    }
    printf("client connect success\n ");

    char* buffer = (char*)malloc(sizeof(char) * 200);
    while (1)
    {
        memset(buffer,0,sizeof(char) * 200);
        scanf("%s",buffer);
        if(strncmp("bye",buffer,3) == 0){
            printf("%s\n","to shutdown");
            send(client_socket_fd,buffer,strlen(buffer),0);
            break;
        }
        send(client_socket_fd,buffer,strlen(buffer),0);
    }
    free(buffer);
    shutdown(client_socket_fd,SHUT_RDWR);
    printf("client shutdown \n");
    return 0; 
}

编译与运行

:~/c# gcc -o socket_server linux_server_socket.c -lpthread
:~/c# ./socket_server
:~/c# gcc -o socket_client linux_client_socket.c -lpthread
:~/c# ./socket_client

测试结果