使用select实现TCP客户端的并发
1 #include<head.h>
2 #define SER_PORT 8888 //服务器端口号
3 #define SER_IP "192.168.122.155" //服务器ip地址
4 #define CLI_PORT 6666 //客户端的端口号
5 #define CLI_IP "192.168.122.155" //客户端ip地址
6 int main(int argc, const char *argv[])
7 {
8 //1、创建用于通信的套接字文件描述符
9 int cfd = -1;
10 cfd = socket(AF_INET, SOCK_STREAM, 0);
11 if(cfd == -1)
12 {
13 perror("socket error");
14 return -1;
15 }
16 printf("cfd = %d\n", cfd); //3
17 /*//2、绑定(可选)
18 //2.1 填充地址信息结构体
19 struct sockaddr_in cin;
20 cin.sin_family = AF_INET;
21 cin.sin_port = htons(CLI_PORT);
22 cin.sin_addr.s_addr = inet_addr(CLI_IP);
23 //2.2绑定
24 if(bind(cfd, (struct sockaddr*)&cin, sizeof(cin)) == -1)
25 {
26 perror("bind error");
27 return -1;
28 }
29 printf("bind success\n");*/
30 //3、连接服务器
31 //3.1 填充服务器地址信息结构体
32 struct sockaddr_in sin;
33 sin.sin_family = AF_INET;
34 sin.sin_port = htons(SER_PORT);
35 sin.sin_addr.s_addr = inet_addr(SER_IP);
36 //3.2 连接
37 if(connect(cfd, (struct sockaddr*)&sin, sizeof(sin)) == -1)
38 {
39 perror("connect error");
40 return -1;
41 }
42 printf("connect success\n");
43 fd_set readfds;
44 FD_ZERO(&readfds);
45 FD_SET(0,&readfds);
46 FD_SET(cfd,&readfds);
47 //4、收发数据
48 char buf[128] = "";
49 while(1)
50 {
51 int res=select(cfd+1,&readfds,NULL,NULL,NULL);
52 if(res==-1)
53 {
54 perror("select error");
55 return -1;
56 }
57 else if(res==0)
58 {
59 perror("timeout\n");
60 return -1;
61 }
62 if(FD_ISSET(0,&readfds))
63 {
64 //清空数组
65 bzero(buf, sizeof(buf));
66 printf("请输入>>>");
67 fgets(buf, sizeof(buf), stdin); //从终端输入数据
68 buf[strlen(buf)-1] = 0; //将换行改为'\0'
69 //发送给服务器
70 send(cfd, buf, sizeof(buf), 0);
71 printf("发送成功\n");
72 if(strcmp(buf, "quit") == 0)
73 {
74 break;
75 }
76 }
77 if(FD_ISSET(cfd,&readfds))
78 {
79 //接收服务器发来的消息
80 recv(cfd, buf, sizeof(buf), 0);
81 printf("[%s:%d]:%s\n", SER_IP, SER_PORT, buf);
82 }
83 }
84 //5、关闭套接字
85 close(cfd);
86 return 0;
87 }
使用poll实现TCP服务器的并发
1 #include<head.h>
2 #define SER_PORT 8888
3 #define SER_IP "192.168.122.155"
4 int main(int argc, const char *argv[])
5 {
6 //1、创建用于连接的套接字
7 int sfd = socket(AF_INET, SOCK_STREAM, 0);
8 //参数1:通信域,表明使用的是ipv4协议
9 //参数2:通信方式,使用TCP通信
10 //参数3:0表示之前已经指定协议 IPPROTO_TCP
11 if(sfd == -1)
12 {
13 perror("socket error");
14 return -1;
15 }
16 printf("sfd = %d\n", sfd); //3
17 //将端口号快速重用函数
18 int reuse = 1;
19 if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1)
20 {
21 perror("setsockopt error");
22 return -1;
23 }
24 printf("端口号快速重用成功\n");
25 //2、给当前套接字绑定IP地址和端口号
26 //2.1填充要绑定的地址信息结构体
27 struct sockaddr_in sin;
28 sin.sin_family = AF_INET; //通信域
29 sin.sin_port = htons(SER_PORT); //端口号
30 sin.sin_addr.s_addr = inet_addr(SER_IP); //ip地址
31 //2.2 绑定
32 if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) == -1)
33 {
34 perror("bind error");
35 return -1;
36 }
37 printf("bind success %s %s %d\n", __FILE__, __func__, __LINE__);
38 //3、将套接字设置成监听状态
39 if(listen(sfd, 128) == -1)
40 {
41 perror("listen error");
42 return -1;
43 }
44 printf("listen success %s %s %d\n", __FILE__, __func__, __LINE__);
45 //4、阻塞等待客户端的链接请求
46 //4.1定义容器接收客户端的地址信息
47 struct sockaddr_in cin; //用于接收地址信息
48 socklen_t socklen = sizeof(cin); //用于接收地址信息的大小
49 int newfd = -1;
50 struct pollfd pfd[3];
51 pfd[0].fd=0;
52 pfd[0].events=POLLIN;
53 pfd[1].fd=sfd;
54 pfd[1].events=POLLIN;
55 while(1)
56 {
57 int res = poll(pfd,3,-1);
58 if(res == -1)
59 {
60 perror("poll error");
61 return -1;
62 }else if(res == 0)
63 {
64 printf("timeout\n");
65 return -1;
66 }
67 if(pfd[1].revents==POLLIN)
68 {
69
70 //4.2 接收客户端的链接
71 newfd = accept(sfd, (struct sockaddr*)&cin, &socklen);
72 if(newfd == -1)
73 {
74 perror("accept error");
75 return -1;
76 }
77 printf("[%s:%d]发来链接请求 %s %s %d\n", \
78 inet_ntoa(cin.sin_addr), ntohs(cin.sin_port),__FILE__, __func__, __LINE__);
79 pfd[2].fd=newfd;
80 pfd[2].events=POLLIN;
81 }
82 //判断0号文件描述符是否在集合中
83 if(pfd[0].revents==POLLOUT)
84 {
85 //终端输入
86 char wbuf[128] = "";
87 scanf("%s", wbuf);
88 printf("触发了终端输入事件。。。\n");
89 }
90 if(pfd[1].revents==POLLIN||pfd[2].revents==POLLIN)
91 {
92 //5、跟客户端进行消息通信
93 char buf[128] = "";
94 while(1)
95 {
96 //将数组清空
97 bzero(buf, sizeof(buf));
98 //读取客户端发来的消息
99 //int res = read(newfd, buf, sizeof(buf));
100 int res = recv(newfd, buf, sizeof(buf), 0);
101 if(res == 0)
102 {
103 printf("客户端已经下线\n");
104 break;
105 }
106 printf("[%s:%d] : %s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), buf);
107 //给客户端发消息
108 strcat(buf, "*_*");
109 //write(newfd, buf, sizeof(buf));
110 send(newfd, buf, sizeof(buf), 0);
111 printf("发送成功\n");
112 }
113 }
114 //关闭当前通信的套接字
115 close(newfd);
116 }
117 //6、关闭套接字
118 close(sfd);
119 return 0;
120 }
使用poll实现TCP服务器的并发