作业
1> 使用select完成TCP客户端程序
//client
#include<myhead.h>
#define CLINET_IP "192.168.125.79"
#define CLINET_PORT 9999
#define SERVE_IP "192.168.125.79"
#define SERVE_PORT 8888
int main(int argc, const char *argv[])
{//socket()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;}//(bind())struct sockaddr_in cin;cin.sin_family=AF_INET;cin.sin_port=htons(CLINET_PORT);cin.sin_addr.s_addr=inet_addr(CLINET_IP);if(bind(cfd,(struct sockaddr*)&cin,sizeof(cin))==-1){perror("bind error");return -1;}printf("[%s:%d]->绑定成功\n",CLINET_IP,CLINET_PORT);//connect()struct sockaddr_in sin;sin.sin_family=AF_INET;sin.sin_port=htons(SERVE_PORT);sin.sin_addr.s_addr=inet_addr(SERVE_IP);if(connect(cfd,(struct sockaddr*)&sin,sizeof(sin))==-1){perror("connect error");return -1;}printf("[%s:%d]->连接成功\n",SERVE_IP,SERVE_PORT);//recv()/send()char buf[128]="";fd_set readfds;//定义文件描述符集合FD_ZERO(&readfds);//清空集合FD_SET(0,&readfds);//放入集合FD_SET(cfd,&readfds);//放入集合int res1=-1;//接收select返回int res2=-1;//接收recv返回fd_set tempfds;//定义一个临时文件描述符集合while(1) {tempfds=readfds;res1=select(cfd+1,&tempfds,NULL,NULL,NULL);if(res1==-1){perror("select error");return -1;}else if(res1==0){printf("time out\n");return -1;}if(FD_ISSET(0,&tempfds)){bzero(buf,sizeof(buf));fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1]=0;send(cfd,buf,sizeof(buf),0);}if(FD_ISSET(cfd,&tempfds)){bzero(buf,sizeof(buf));res2=recv(cfd,buf,sizeof(buf),0);if(res2==0||strcmp(buf,"quit")==0){printf("服务器下线\n");break;}printf("[%s:%d]->%s\n",SERVE_IP,SERVE_PORT,buf);}}//close()close(cfd);return 0;
}
//serve
#include<myhead.h>
#define PORT 8888
#define IP "192.168.125.79"
int main(int argc, const char *argv[])
{int sfd=-1;if((sfd=socket(AF_INET,SOCK_STREAM,0))==-1){perror("socket error");return -1;}printf("sfd=%d\n",sfd);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;}printf("bind success _%d_%s_%s\n",__LINE__,__FILE__,__func__);if(listen(sfd,128)==-1){perror("listen error");return -1;}printf("listen success _%d_%s_%s\n",__LINE__,__FILE__,__func__);struct sockaddr_in cin;socklen_t socklen=sizeof(cin);fd_set readfds; //定义阻塞的文件描述符集合FD_ZERO(&readfds); //清空FD_SET(sfd,&readfds); //将文件描述符放入FD_SET(0,&readfds);int res=0;//select返回值int maxfd=sfd;int newfd=-1;char buf[128]="";char rbuf[128]="";//服务器客户端通信struct sockaddr_in arr_cin[1024];fd_set tempfds;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;}else{ for(int index=0;index<=maxfd;index++){if(!FD_ISSET(index,&tempfds))//所有文件描述符没有事件发生 {continue;}else if( index==sfd ){if((newfd=accept(sfd,(struct sockaddr*)&cin,&socklen))==-1){perror("accept error");return -1;}arr_cin[newfd]=cin;printf("[%s:%d]:连接成功,newfd=%d\n",inet_ntoa(arr_cin[index].sin_addr),ntohs(arr_cin[index].sin_port),newfd);FD_SET(newfd,&readfds);//新的newfd应当加入原本的readfdsif(newfd>maxfd){maxfd=newfd;}}else if( index==0 ){scanf("%s",buf);printf("将发送所有连接的用户->%s\n",buf);for(int j=4;j<=maxfd;j++){send(j,buf,sizeof(buf),0);}}else{bzero(rbuf,sizeof(rbuf));if(recv(index,rbuf,sizeof(rbuf),0)==0){printf("客户端下线\n");close(index);//关闭套接字文件FD_CLR(index,&tempfds);//移除select数组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并发服务器