思维导图:
?使用selsect实现TCP客户端的并发
代码
#include<a.h>
#define SER_PORT 8888 //服务器端口号
#define SER_IP "192.168.125.50" //服务器ip地址
#define CLI_PORT 6666 //客户端的端口号
#define CLI_IP "192.168.125.50" //客户端ip地址
int main(int argc, const char *argv[])
{
//1、创建用于通信的套接字文件描述符
int cfd = -1;
cfd = socket(AF_INET, SOCK_STREAM, 0);
if(cfd == -1)
{
perror("socket error");
return -1;
}
printf("cfd = %d\n", cfd); //3
//2、绑定(可选)
//2.1 填充地址信息结构体
struct sockaddr_in cin;
cin.sin_family = AF_INET;
cin.sin_port = htons(CLI_PORT);
cin.sin_addr.s_addr = inet_addr(CLI_IP);
//2.2绑定
if(bind(cfd, (struct sockaddr*)&cin, sizeof(cin)) == -1)
{
perror("bind error");
return -1;
}
printf("bind success\n");
//3、连接服务器
//3.1 填充服务器地址信息结构体
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(SER_PORT);
sin.sin_addr.s_addr = inet_addr(SER_IP);
//3.2 连接
if(connect(cfd, (struct sockaddr*)&sin, sizeof(sin)) == -1)
{
perror("connect error");
return -1;
}
printf("连接成功\n");
//准备一个文件描述器
fd_set readfds,tempfds;//临时集合
//清空容器
FD_ZERO(&readfds);
//将要检测的文件放入集合中
FD_SET(0,&readfds);
FD_SET(cfd,&readfds);
int res=-1; //接收select函数对容器的中文件描述符号检测的返回值
//4、收发数据
char wbuf[128]=""; //终端
char rbuf[128]=""; //接收服务器发来的消息
while(1)
{
tempfds=readfds; //存储一份数据
//使用select函数对容器中的文件描述符进行检测
res=select(cfd+1,&tempfds,NULL,NULL,NULL);
if(res==-1)
{
perror("select error");
return -1;
}else if(res==0)
{
printf("timeout\n");
return -1;
}
//判断终端是否发生事件
if(FD_ISSET(0,&tempfds))
{
//清空数组
bzero(wbuf, sizeof(wbuf));
printf("请输入>>>");
fgets(wbuf, sizeof(wbuf), stdin); //从终端输入数据
wbuf[strlen(wbuf)-1] = 0; //将换行改为'\0'
//发送给服务器
send(cfd, wbuf, sizeof(wbuf), 0);
printf("发送成功\n");
if(strcmp(wbuf, "quit") == 0)
{
break;
}
}
//判断是否是服务器发来的消息触发
if(FD_ISSET(cfd,&tempfds))
{
//清空数组
bzero(rbuf,sizeof(rbuf));
//接收服务器发来的消息
recv(cfd, rbuf, sizeof(rbuf), 0);
printf("[%s:%d]:%s\n", SER_IP, SER_PORT, rbuf);
}
}
//5、关闭套接字
close(cfd);
return 0;
}