1> 使用select完成TCP客户端程序
客户端:
#include
#define FPORT 9999
#define FIP "192.168.125.130"
#define KPORT 6666
#define KIP "192.168.125.130"
int main(int argc, const char *argv[])
{
//创建套接字文件描述符
int cfd = 0;
if((cfd = socket(AF_INET,SOCK_STREAM,0)) == -1)
{
perror("socket error");
return -1;
}
//允许重复引用
int reuse = 1;
if(setsockopt(cfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) == -1)
{
perror("setsockopt error");
return -1;
}
//绑定客服端
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(KPORT);
sin.sin_addr.s_addr = inet_addr(KIP);
if(bind(cfd,(struct sockaddr*)&sin,sizeof(sin)) == -1)
{
perror("bind error");
return -1;
}
//连接服务器
struct sockaddr_in cin;
cin.sin_family = AF_INET;
cin.sin_port = htons(FPORT);
cin.sin_addr.s_addr = inet_addr(FIP);
if(connect(cfd,(struct sockaddr*)&cin,sizeof(cin)) == -1)
{
perror("connect");
return -1;
}
//定义检测文件描述符的集合
fd_set readfd;
//清空集合
FD_ZERO(&readfd);
//将cfd和0加入集合
FD_SET(cfd,&readfd);
FD_SET(0,&readfd);
char buf[128] = "";
int res = -1;
fd_set tempfd;
while(1)
{
tempfd = readfd;
res = select(cfd+1,&tempfd,NULL,NULL,NULL);
if(res < 0)
{
perror("select error");
return -1;
}else if(res == 0)
{
printf("time out\n");
return -1;
}
//下面为处理的处理描述符
if(FD_ISSET(0,&tempfd))
{
bzero(buf,sizeof(buf));
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1]=0;
send(cfd,buf,sizeof(buf),0);
printf("客服端输入为%s\n",buf);
}
if(FD_ISSET(cfd,&tempfd))
{
bzero(buf,sizeof(buf));
int res = recv(cfd,buf,sizeof(buf),0);
if(res == 0)
{
printf("服务器下线\n");
break;
}
printf("服务器发来的消息为%s\n",buf);
}
}
close(cfd);
return 0;
}
服务器:
#include
#define PORT 9999
#define IP "192.168.125.130"
int main(int argc, const char *argv[])
{
int sfd = -1;
if((sfd = socket(AF_INET,SOCK_STREAM,0)) == -1)
{
perror("socket");
return -1;
}
int reuse = 1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) == -1)
{
perror("setsockopt error");
return -1;
}
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin)) == -1)
{
perror("bind error");
return -1;
}
if(listen(sfd,128) == -1)
{
perror("listen error");
return -1;
}
struct sockaddr_in cin;
socklen_t socklen = sizeof(cin);
int newfd = -1;
char buf[128] = "";
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(sfd,&readfds);
FD_SET(0,&readfds);
int res = 0;
fd_set tempfds;
int maxfd = sfd;
char rbuf[128]="";
struct sockaddr_in arr_cin[1024];
while(1)
{
tempfds = readfds;
res = select(maxfd+1,&tempfds,NULL,NULL,NULL);
if(res == -1)
{
perror("select error");
return -1;
}else if(res == 0)
{
printf("time out\n");
return -1;
}
for(int index=0;index<=maxfd;index++)
{
if(!FD_ISSET(index,&tempfds))
{
continue;
}
if(index == sfd)
{
if((newfd = accept(sfd,(struct sockaddr*)&cin,&socklen)) == -1)
{
perror("accept");
return -1;
}
arr_cin[newfd] =cin;
printf("[%s:%d]链接成功,newfd = %d\n\n",inet_ntoa(arr_cin[newfd].sin_addr),ntohs(arr_cin[newfd].sin_port),newfd);
FD_SET(newfd,&readfds);
if(newfd > maxfd)
{
maxfd = newfd;
}
}else if(index == 0)
{
scanf("%s",buf);
printf("%s\n",buf);
}else
{
bzero(rbuf,sizeof(rbuf));
int res = recv(index,rbuf,sizeof(rbuf),0);
if(res == 0)
{
printf("客户端下线\n");
close(index);
FD_CLR(index,&readfds);
for(int i =maxfd;i>0;i--)
{
if(FD_ISSET(i,&readfds))
{
maxfd = i;
break;
}
}
continue;
}
printf("[%s:%d] :%s\n",inet_ntoa(arr_cin[index].sin_addr),ntohs(arr_cin[index].sin_port),rbuf);
strcat(rbuf,"*_*");
send(index,rbuf,sizeof(rbuf),0);
}
}
}
close(sfd);
return 0;
}
效果图:

2> 使用poll完成TCP并发服务器
客户端:
#include
#define SERPORT 9999
#define SERIP "192.168.125.130"
#define CLIPORT 6666
#define CLIIP "192.168.125.130"
int main(int argc, const char *argv[])
{
int cfd = -1;
if((cfd = socket(AF_INET,SOCK_STREAM,0)) == -1)
{
perror("socket error");
return -1;
}
printf("cfd = %d\n",cfd);
int reuse = 1;
if(setsockopt(cfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) == -1)
{
perror("setsockopt error");
return -1;
}
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(CLIPORT);
sin.sin_addr.s_addr = inet_addr(CLIIP);
if(bind(cfd,(struct sockaddr*)&sin,sizeof(sin)) == -1)
{
perror("bind error");
return -1;
}
struct sockaddr_in cin;
cin.sin_family = AF_INET;
cin.sin_port = htons(SERPORT);
cin.sin_addr.s_addr = inet_addr(SERIP);
if(connect(cfd,(struct sockaddr*)&cin,sizeof(cin)) == -1)
{
perror("connect error");
return -1;
}
struct pollfd fds[2];
fds[0].fd = 0;
fds[0].events = POLLIN;
fds[1].fd = cfd;
fds[1].events = POLLIN;
int res = -1;
char wbuf[128] = "";
while(1)
{
res = poll(fds,2,-1);
if(res < 0)
{
perror("poll error");
return -1;
}else if(res == 0)
{
printf("time out \n");
return -1;
}
if(fds[0].revents == POLLIN)
{
bzero(wbuf,sizeof(wbuf));
fgets(wbuf,sizeof(wbuf),stdin);
wbuf[strlen(wbuf)-1]=0;
send(cfd,wbuf,sizeof(wbuf),0);
}
if(fds[1].revents == POLLIN)
{
bzero(wbuf,sizeof(wbuf));
int res = recv(cfd,wbuf,sizeof(wbuf),0);
if(res == 0)
{
printf("服务器已下线\n");
break;
}
printf("[%s:%d]:%s\n",SERIP,SERPORT,wbuf);
}
}
close(cfd);
return 0;
}
服务器:
效果图: