网络通信day5作业

1>    使用select完成TCP客户端程序

客户端:

#include<myhead.h>#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<myhead.h>
#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<myhead.h>
#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;
}

服务器:

#include<myhead.h>#define PORT 9999
#define IP "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;}//端口快速重用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(PORT);sin.sin_addr.s_addr = inet_addr(IP);if(bind(cfd,(struct sockaddr*)&sin,sizeof(sin)) == -1){perror("bind error");return -1;}//设置为监听状态if(listen(cfd,128) == -1){perror("listen error");return -1;}//要检测的文件描述符集合对应的数组struct pollfd fds[1024];//定义客户端信息struct sockaddr_in add_cin[1024];//标准0fds[0].fd = 0;fds[0].events = POLLIN;//标准cfdfds[cfd].fd = cfd;fds[cfd].events = POLLIN;struct sockaddr_in cin;socklen_t socklen = sizeof(cin);int newfd = -1;int res = -1;int size = 4;//初始成员个数char buf[128]="";while(1){res = poll(fds,size,-1);if(res == -1){perror("poll error");return -1;}else if(res == 0){printf("time out\n");return -1;}for(int index=0;index<1024;index++){if(fds[index].revents != POLLIN){continue;}if(fds[cfd].revents == POLLIN)//if((fds[index].revents == POLLIN)&&(fds[index].fd == cfd)){//到此下面为操作文件描述符//设置为等待连接状态if((newfd = accept(cfd,(struct sockaddr*)&cin,&socklen)) == -1){perror("accept error");return -1;}//客户端加入数组add_cin[newfd]=cin;fds[size].fd = newfd;fds[size].events = POLLIN;size++;//printf("连接成功\n");printf("[%s,%d]连接成功,newfd=%d\n",inet_ntoa(add_cin[newfd].\sin_addr),ntohs(add_cin[newfd].sin_port),newfd);}else if((fds[index].revents == POLLIN)&&fds[index].fd == 0){bzero(buf,sizeof(buf));//终端输入fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1] = 0;printf("服务器输入为%s\n",buf);}else {bzero(buf,sizeof(buf));int resa = recv(fds[index].fd,buf,sizeof(buf),0);if(resa == 0){printf("客户端下线\n");close(fds[index].fd);fds[index] = fds[size];size--;continue;}printf("[%s,%d]发送%s\n",inet_ntoa(add_cin[newfd].sin_addr),\ntohs(add_cin[newfd].sin_port),buf);strcat(buf,"*_*");send(fds[index].fd,buf,sizeof(buf),0);}}}return 0;
}

 服务器:

#include<myhead.h>#define PORT 9999
#define IP "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;}//端口快速重用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(PORT);sin.sin_addr.s_addr = inet_addr(IP);if(bind(cfd,(struct sockaddr*)&sin,sizeof(sin)) == -1){perror("bind error");return -1;}//设置为监听状态if(listen(cfd,128) == -1){perror("listen error");return -1;}//要检测的文件描述符集合对应的数组struct pollfd fds[1024];//定义客户端信息struct sockaddr_in add_cin[1024];//标准0fds[0].fd = 0;fds[0].events = POLLIN;//标准cfdfds[cfd].fd = cfd;fds[cfd].events = POLLIN;struct sockaddr_in cin;socklen_t socklen = sizeof(cin);int newfd = -1;int res = -1;int size = 4;//初始成员个数char buf[128]="";while(1){res = poll(fds,size,-1);if(res == -1){perror("poll error");return -1;}else if(res == 0){printf("time out\n");return -1;}for(int index=0;index<1024;index++){if(fds[index].revents != POLLIN){continue;}if(fds[cfd].revents == POLLIN){//到此下面为操作文件描述符//设置为等待连接状态if((newfd = accept(cfd,(struct sockaddr*)&cin,&socklen)) == -1){perror("accept error");return -1;}//客户端加入数组add_cin[newfd]=cin;fds[newfd].fd = newfd;fds[newfd].events = POLLIN;size++;//printf("连接成功\n");printf("[%s,%d]连接成功,newfd=%d\n",inet_ntoa(add_cin[newfd].\sin_addr),ntohs(add_cin[newfd].sin_port),newfd);}else if((fds[index].revents == POLLIN)&&fds[index].fd == 0){bzero(buf,sizeof(buf));//终端输入fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1] = 0;printf("服务器输入为%s\n",buf);}else {bzero(buf,sizeof(buf));int resa = recv(fds[index].fd,buf,sizeof(buf),0);if(resa == 0){printf("客户端下线\n");close(fds[index].fd);//fds[index] = fds[size];//size--;continue;}printf("[%s,%d]发送%s\n",inet_ntoa(add_cin[newfd].sin_addr),\ntohs(add_cin[newfd].sin_port),buf);strcat(buf,"*_*");send(fds[index].fd,buf,sizeof(buf),0);}}}return 0;
}

效果图: