select 服务器 客户端 缩水版
tcpserver.c
int main(int argc, char**argv) { int listenfd = socket(AF_INET,SOCK_STREAM,0); struct sockaddr_in serv_addr, client_addr; socklen_t client_len = sizeof(client_addr); memset(&serv_addr,0,sizeof(serv_addr)); memset(&client_addr,0,sizeof(client_addr)); serv_addr.sin_addr.s_addr = INADDR_ANY; //绑定所有ip serv_addr.sin_family=AF_INET; serv_addr.sin_port = htons(PORT); int opt = 1; socklen_t optlen = sizeof(opt); //设置复用ip if(setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,(void*)&opt,optlen) < 0){ perror("setsockopt"); return 0; } //设置ip port if(bind(listenfd,(SA*)&serv_addr,sizeof(serv_addr)) < 0){ perror("bind"); return 0; } //BACKLOG = 10 if(listen(listenfd,BACKLOG) < 0){ perror("listen"); return 0; } //一些变量,下面会用到 int nready = 0,client[FD_SETSIZE] , maxfd = listenfd , connfd = 0,maxi = -1; // client 用于存储 客户描述符 for(int i = 0; i < FD_SETSIZE ; ++i) client[i] = -1; fd_set rset ,allset; FD_ZERO(&allset); //把监听套接字先置位 FD_SET(listenfd,&allset); int clientfd = -1 , n = 0 , i = 0; char buf[BUFSIZ]; while(1){ //select 每次将修改rset,需要重置 rset = allset; nready = select(maxfd+1,&rset,NULL,NULL,NULL); printf("nread : %d \n" , nready); //可能被信号打断 if(nready < 0){ perror("select"); continue; } //客户链接 进来 if(FD_ISSET(listenfd,&rset)){ client_len = sizeof(client_addr); connfd = accept(listenfd,(SA*)&client_addr,&client_len); printf("a client : %d\n" , connfd); //找个位置放进去 for(i = 0; i < FD_SETSIZE; ++i){ if(client[i] < 0) { client[i] = connfd; break; } } //服务器已满 if(FD_SETSIZE == i){ close(connfd); puts("server is full"); } else { //把客户fd 放入监听集合中 FD_SET(connfd,&allset); if(connfd > maxfd) maxfd = connfd; //client 索引 if( i > maxi) maxi = i; //如果数量为0 则不需要往下继续了 if(--nready == 0) continue; } } for(int i = 0 ; i <= maxi;++i){ if((clientfd = client[i]) <0 ) continue; //直到找到一个可读的fd if(FD_ISSET(clientfd,&rset)){ printf("clientfd : %d is ready\n", clientfd); //如果对断关闭了 if((n = read(clientfd,buf,BUFSIZ)) <= 0){ printf("clientfd : %d closed\n",clientfd); //清空当前fd 所存在的地方 close(clientfd); FD_CLR(clientfd,&allset); client[i] = -1; } else{ write(clientfd,buf,n); } if(--nready == 0) break; } } } return 0; }
tcpclient.c
void str_echo(int sockfd); int max(int a, int b){ return a > b ? a : b; } int main(int argc, char**argv) { if(argc != 2){ puts("ip addr"); return 0; } int sockfd = socket(AF_INET,SOCK_STREAM,0); struct sockaddr_in sin; memset(&sin,0,sizeof(sin)); sin.sin_port = htons(PORT); sin.sin_family = AF_INET; //把字符串转成网络字节序 inet_pton(AF_INET,argv[1],&sin.sin_addr); connect(sockfd,(SA*)&sin,sizeof(sin)); str_echo(sockfd); return 0; } void str_echo(int sockfd){ int maxfd = sockfd; int eof = 0 , readn = 0 , fd_num = 0, n= 0; char buf[BUFSIZ]; fd_set rset; FD_ZERO(&rset); while(1) { //EOF ==》 CTRL+D if(0 == eof){ FD_SET(0,&rset); } //select 将修改rset ,每次重置 FD_SET(sockfd,&rset); maxfd = max(0,sockfd); fd_num = select(maxfd+1,&rset,NULL,NULL,NULL); printf("fd_num : %d\n" , fd_num); //如果是套接字可读 if(FD_ISSET(sockfd,&rset)){ //服务器关闭 if((n=read(sockfd,buf,BUFSIZ)) <= 0){ if(eof == 1){ puts("server closed"); break; } else { puts("server ter"); break; } } buf[n] = 0; printf("recv from serv:%s\n" , buf); } //如果是输入端可读 if(FD_ISSET(0,&rset)){ //如果ctrl + d if((n = read(0,buf,BUFSIZ)) <= 0){ printf("client closing\n"); //先发送Fin , 等服务端close shutdown(sockfd,SHUT_WR); eof = 1; FD_CLR(0,&rset); continue; } write(sockfd,buf,n); } } }
相关推荐
专注前端开发 2020-10-21
苏康申 2020-11-13
vitasfly 2020-11-12
oraclemch 2020-11-06
liuyang000 2020-09-25
FellowYourHeart 2020-10-05
赵继业 2020-08-17
whyname 2020-08-16
Seandba 2020-08-16
dbasunny 2020-08-16
拼命工作好好玩 2020-08-15
langyue 2020-08-15
写程序的赵童鞋 2020-08-03
Accpcjg 2020-08-02
tydldd 2020-07-30
好记忆也需烂 2020-07-28
jianghero 2020-07-28