Linux下socket通信和多线程

时间:2021-04-02 16:14:10

服务端socket流程:socket() –> bind() –> listen() –> accept() –> 读取、发送信息(recv,send等)

客户端socket流程:socket() –> connect() –> 发送、读取信息(send,recv等)

参考:Socket基本操作

本文包含基本实现,多线程版本

基本实现

服务端监听某个端口,客户端连接之后发送数据——>客户端断开连接后,服务端也关闭了

服务端:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <sys/socket.h>
 4 #include <netinet/in.h>
 5 #include <string.h>
 6 
 7 const int Port = 8888;
 8 
 9 int main(void){
10     int sock_fd;
11     struct sockaddr_in mysock;
12     struct sockaddr_in client_addr;
13     int new_fd;
14     socklen_t sin_size
15     char buf[1024];
16     char sedbuf[1024] = "recv successfully.\n";
17 
18     //初始化socket
19     sock_fd = socket(AF_INET,SOCK_STREAM,0);
20 
21     //编辑地址信息
22     memset(&mysock,0,sizeof(mysock));
23     mysock.sin_family = AF_INET;
24     mysock.sin_port = htons(Port);
25     mysock.sin_addr.s_addr = INADDR_ANY;
26 
27     //绑定地址,然后监听
28     bind(sock_fd,(struct sockaddr *)&mysock,sizeof(struct sockaddr));
29     if(listen(sock_fd,10) < -1){
30         printf("listen error.\n");
31     }
32 
33     sin_size = sizeof(struct sockaddr_in);
34     
35     printf("listening...\n");
36     new_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size);//accpet
37     while(1){
38         int len = recv(new_fd,buf,sizeof(buf),0);
39         fputs(buf,stdout);
40         send(new_fd, sedbuf, sizeof(sedbuf), 0);
41         if(strcmp(buf,"exit\n") == 0){
42             break;
43         }
44         memset(buf,0,sizeof(buf));
45     }
46     close(new_fd);
47     close(sock_fd);
48     return 0;

 

 

客户端:

 1 #include<stdio.h>
 2 #include<unistd.h>
 3 #include<stdlib.h>
 4 #include<sys/types.h>
 5 #include<sys/socket.h>
 6 #include<netinet/in.h>
 7 #include<netdb.h>
 8 #include<string.h>
 9 #include<errno.h>
10 
11 const int Port = 8888;
12 
13 int main(void){
14     int sock_fd;
15     char buf[1024], sendbuf[1024], recvbuf[1024];
16     struct sockaddr_in server_addr;
17     sock_fd = socket(AF_INET, SOCK_STREAM, 0);//初始化socket
18     if(sock_fd == -1){
19         printf("%s\n",strerror(errno));
20         return 0;
21     }
22 
23     bzero(&server_addr, sizeof(server_addr));//编辑服务端地址信息
24     server_addr.sin_family = AF_INET;
25     server_addr.sin_port = htons(Port);
26     server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
27 
28     int tmp = connect(sock_fd, (struct sockaddr *)(&server_addr), 
29         sizeof(struct sockaddr));//连接服务端socket
30     if(tmp == -1){
31         printf("%s\n",strerror(errno));
32         return 0;
33     }
34 
35     while(1){
36         fgets(sendbuf, sizeof(sendbuf), stdin);
37         send(sock_fd, sendbuf, strlen(sendbuf), 0);
38         if(strcmp(sendbuf, "exit\n") == 0)
39             break;
40         recv(sock_fd, recvbuf, sizeof(recvbuf), 0);
41         fputs(recvbuf, stdout);
42         memset(sendbuf, 0, sizeof(sendbuf));
43         memset(recvbuf, 0, sizeof(recvbuf));
44     }
45     close(sock_fd);
46     return;
47 }

 

多客户端与服务端通信(多线程)

只需在服务端修改,增加多线程,就可以同时接收多个客户端发送的信息了。

服务端:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <sys/socket.h>
 4 #include <netinet/in.h>
 5 #include <string.h>
 6 #include <pthread.h>
 7 #include <unistd.h>
 8 
 9 const int Port = 8888;
10 pthread_mutex_t g_mutext;
11 
12 struct pthread_data{
13     struct sockaddr_in client_addr;
14     int sock_fd;
15 };
16 
17 void *serveForClient(void * arg);
18 
19 int main(void){
20     int sock_fd;
21     struct sockaddr_in mysock;
22     struct pthread_data pdata;
23     pthread_t pt;
24     socklen_t sin_size = sizeof(struct sockaddr_in);
25     struct sockaddr_in client_addr;
26     int new_fd;
27 
28     //初始化socket
29     sock_fd = socket(AF_INET,SOCK_STREAM,0);
30 
31     //编辑地址信息
32     memset(&mysock, 0, sizeof(mysock));
33     mysock.sin_family = AF_INET;
34     mysock.sin_port = htons(Port);
35     mysock.sin_addr.s_addr = INADDR_ANY;
36 
37     //绑定地址,然后监听
38     bind(sock_fd,(struct sockaddr *)&mysock,sizeof(struct sockaddr));
39     if(listen(sock_fd,10) < -1){
40         printf("listen error.\n");
41     }
42 
43     printf("listening...\n");
44     while(1){
45         //accpet
46         new_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size);
47         pdata.client_addr = client_addr;
48         pdata.sock_fd = new_fd;
49         pthread_create(&pt, NULL, serveForClient, (void *)&pdata);
50     }
51     close(new_fd);
52     close(sock_fd);
53     return 0;
54 }
55 
56 void *serveForClient(void *arg){
57     struct pthread_data *pdata = (struct pthread_data*)arg;
58     int new_fd = pdata->sock_fd;
59     char recvbuf[1024];
60     char sendbuf[1024] = "recv successfully.\n";
61     while(1){
62         recv(new_fd, recvbuf, sizeof(recvbuf), 0);
63         fputs(recvbuf,stdout);
64         strcpy(sendbuf, recvbuf);
65         if(strcmp(recvbuf,"exit\n") == 0){
66             send(new_fd, "connection close.\n", sizeof("connection close.\n"), 0);
67             break;
68         }
69         send(new_fd, sendbuf, sizeof(sendbuf), 0);
70         memset(recvbuf,0,sizeof(recvbuf));
71     }
72     close(new_fd);
73     pthread_exit(0);
74 }