1 #include <stdio.h>
2 #include <sys/socket.h>
3 #include <arpa/inet.h>
4 #include <netinet/in.h>
5 #include <string.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <signal.h>
9 #include <pthread.h>
10 #include <semaphore.h>
11 #include <termios.h>
12 #include <sys/stat.h>
13 #include <fcntl.h>
14 //使用多线程解决并发
15 //pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
16 //为什么选择多线程解决并发问题,而不选择多进程
17 void serial_port_init(int fd);
18 void *pthread_fun(void *args)
19 {
20 int *cidp = (int *)args;
21 int cid = *cidp;
22 char buf[128] = "";
23 int count = -1;
24 //5.发送或接收数据:send(),write()/recv(),read();
25 while (strncmp(buf, "quit", 4))
26 {
27 read(cid, buf, sizeof(buf));
28 printf("接收到:%s\n", buf);
29 write(cid, buf, strlen(buf));
30 memset(buf, 0, sizeof(buf));
31 }
32 //6.关闭套接字:close();
33 shutdown(cid, SHUT_RDWR);
34 close(cid);
35 }
36
37 int main(int argc, char **argv)
38 {
39 if (argc < 3)
40 {
41 printf("usage : ./a.out ip port\n");
42 return -1;
43 }
44
45 int sid = socket(AF_INET, SOCK_STREAM, 0);
46 if (sid < 0)
47 {
48 perror("socket error");
49 return -1;
50 }
51
52 //2.绑定到本机ip和端口号bind();
53 struct sockaddr_in saddr = {0};
54 saddr.sin_family = AF_INET;
55 saddr.sin_port = htons(atoi(argv[2]));
56 saddr.sin_addr.s_addr = inet_addr(argv[1]);
57 int reuseaddr = 1;
58 if (setsockopt(sid, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)) < 0) //设置地址复用
59 {
60 perror("reuseaddr error");
61 close(sid);
62 return -1;
63 }
64
65 //端口复用
66 if (bind(sid, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
67 {
68 perror("bind error: port binded");
69 close(sid);
70 return -1;
71 }
72
73 //3.把套接字设置为监听状态listen();
74 if (listen(sid, 10) < 0)
75 {
76 perror("listen error");
77 close(sid);
78 return -1;
79 }
80
81 //4.等待客户端连接请求:accept();
82 int cid = -1;
83 pthread_t tid;
84
85 //设置线程分离
86 pthread_attr_t attr;
87 pthread_attr_init(&attr);
88 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
89
90 //当有客户端连接时,会有两个线程:主线程处理客户端连接请求,并创建一个子线程与网络客户端交互,子线程:负责与网络客户端交互
91 while (1)
92 {
93 cid = accept(sid, NULL, NULL);
94 if (cid < 0)
95 {
96 perror("accept error");
97 continue;
98 }
99
100 pthread_create(&tid, &attr, pthread_fun, &cid); //创建子线程
101 }
102 close(sid);
103 }