【网络编程】学习笔记--04 server端和client代码
Server端:
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<errno.h> #include<pthread.h> #include<ctype.h> #include<sys/socket.h> #include<arpa/inet.h> #define SERV_PORT 9527 void sys_err(const char *str) { perror(str); exit(1); } int main(int argc,char *argv[]) { int lfd = 0,cfd = 0; int ret,i; char buf[BUFSIZ],client_IP[BUFSIZ]; struct sockaddr_in serv_addr,clit_addr; socklen_t clit_addr_len; serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(SERV_PORT); serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); lfd = socket(AF_INET,SOCK_STREAM,0); if(lfd==-1){ sys_err("socket error"); } bind(lfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)); listen(lfd,128); clit_addr_len = sizeof(clit_addr); cfd = accept(lfd,(struct sockaddr *)&clit_addr,&clit_addr_len); if(cfd==-1){ sys_err("accept error"); } printf("client ip:%s port:%d\n", inet_ntop(AF_INET, &clit_addr.sin_addr.s_addr,client_IP,sizeof(client_IP)), ntohs(clit_addr.sin_port)); while(1){ ret = read(cfd,buf,sizeof(buf)); for(i=0;i<ret;i++) buf[i]=toupper(buf[i]); write(STDOUT_FILENO,buf,ret); } close(lfd); close(cfd); return 0; }
Client端:
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<arpa/inet.h> #include<sys/socket.h> #define SERV_PORT 9527 void sys_err(const char *str) { perror(str); exit(1); } int main(int argc,char *argv[]) { int cfd; int conter=10; char buf[BUFSIZ]; struct sockaddr_in serv_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(SERV_PORT); inet_pton(AF_INET,"127.0.0.1",&serv_addr.sin_addr.s_addr); cfd = socket(AF_INET,SOCK_STREAM,0); if(cfd==-1) sys_err("socket error"); int ret = connect(cfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)); if(ret!=0) sys_err("connect error"); while(conter--) { ret = read(STDIN,buf,sizeof(buf)); write(cfd,buf,ret) write(STDOUT_FILENO,buf,ret); sleep(1); } close(cfd); return 0; }
运行的时候,开2个窗口,一个窗口跑server端,./server即可,另一个跑client端,./client即可。注意要先编译。
多进程+回收子进程(信号捕捉杀僵尸进程)版server:
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<errno.h> #include<signal.h> #include<pthread.h> #include<sys/socket.h> #include<arpa/inet.h> #include<ctype.h> #include<sys/wait.h> #include<sys/types.h> #define SRV_PORT 9999 void catch_child(int signum) { while(waitpid(0,NULL,WNOHANG)>0); return ; } int main(int argc,char *argv[]) { int lfd,cfd; pid_t pid; struct sockaddr_in srv_addr,clt_addr; socklen_t clt_addr_len; char buf[BUFSIZ]; int ret,i; memset(&srv_addr,0,sizeof(srv_addr)); srv_addr.sin_family = AF_INET; srv_addr.sin_port = htons(SRV_PORT); srv_addr.sin_addr.s_addr = htonl(INADDR_ANY); lfd = socket(AF_INET,SOCK_STREAM,0); bind(lfd,(struct sockaddr *)&srv_addr,sizeof(srv_addr)); listen(lfd,128); clt_addr_len = sizeof(clt_addr); while(1){ cfd = accept(lfd,(struct sockaddr *)&clt_addr ,&clt_addr_len); pid = fork(); if(pid == 0){ close(lfd); break; } else if(pid > 0){ struct sigaction act; act.sa_handler = catch_child; sigemptyset(&act.sa_mask); act.sa_flags = 0; ret = sigaction(SIGCHLD,&act,NULL); close(cfd); } } if(pid == 0){ for(;;){ ret = read(cfd, buf ,sizeof(buf)); if(ret == 0){ close(cfd); exit(1); } for(i=0;i<ret;i++) buf[i]=toupper(buf[i]); write(cfd,buf,ret); write(STDOUT_FILENO,buf,ret); } } return 0; }
多进程+回收子进程+端口复用版server:
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<errno.h> #include<signal.h> #include<pthread.h> #include<sys/socket.h> #include<arpa/inet.h> #include<ctype.h> #include<sys/wait.h> #include<sys/types.h> #define SRV_PORT 9999 void catch_child(int signum) { while(waitpid(0,NULL,WNOHANG)>0); return ; } int main(int argc,char *argv[]) { int lfd,cfd; pid_t pid; struct sockaddr_in srv_addr,clt_addr; socklen_t clt_addr_len; char buf[BUFSIZ]; int ret,i; memset(&srv_addr,0,sizeof(srv_addr)); srv_addr.sin_family = AF_INET; srv_addr.sin_port = htons(SRV_PORT); srv_addr.sin_addr.s_addr = htonl(INADDR_ANY); lfd = socket(AF_INET,SOCK_STREAM,0); int opt=1; setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,(void*)&opt,sizeof(opt)) bind(lfd,(struct sockaddr *)&srv_addr,sizeof(srv_addr)); listen(lfd,128); clt_addr_len = sizeof(clt_addr); while(1){ cfd = accept(lfd,(struct sockaddr *)&clt_addr ,&clt_addr_len); pid = fork(); if(pid == 0){ close(lfd); break; } else if(pid > 0){ struct sigaction act; act.sa_handler = catch_child; sigemptyset(&act.sa_mask); act.sa_flags = 0; ret = sigaction(SIGCHLD,&act,NULL); close(cfd); } } if(pid == 0){ for(;;){ ret = read(cfd, buf ,sizeof(buf)); if(ret == 0){ close(cfd); exit(1); } for(i=0;i<ret;i++) buf[i]=toupper(buf[i]); write(cfd,buf,ret); write(STDOUT_FILENO,buf,ret); } } return 0; }
运用select的(可以不用写多进程)的server:
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<errno.h> #include<pthread.h> #include<ctype.h> #include<sys/socket.h> #include<arpa/inet.h> #define SERV_PORT 9527 void sys_err(const char *str) { perror(str); exit(1); } int main(int argc,char *argv[]) { int listenfd = 0,connfd = 0; char buf[BUFSIZ]; struct sockaddr_in serv_addr,clie_addr; socklen_t clie_addr_len; listenfd = socket(AF_INET,SOCK_STREAM,0); int opt = 1; setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); memset(&serv_addr,0,sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(SERV_PORT); serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); bind(listenfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)); listen(listenfd,128); fd_set rset,allset; //定义读集合rset,备份集合allset int ret,maxfd = 0,n,i,j; maxfd = listenfd; //最大文件描述符 FD_ZERO(&allset); //清空监听集合 FD_SET(listenfd,&allset); //将待监听fd添加到监听集合中 while(1){ rset = allset; //备份 ret = select(maxfd+1, &rset, NULL, NULL,NULL); //使用select监听 if(FD_ISSET(listenfd,&rset)){ //listenfd满足监听读事件 clie_addr_len = sizeof(clie_addr); connfd = accept(listenfd, (struct sockaddr *)&clie_addr, &clie_addr_len); //与客户端建立连接,不会阻塞 FD_SET(connfd, &allset); //将新产生的fd添加到监听集合中,监听数据读事件 if(maxfd < connfd) //修改maxfd maxfd = connfd; if(ret == 1) //说明select返回值只有1个,并且是listenfd,后续无需执行 continue; } for(i = listenfd+1; i<=maxfd; i++){ //处理满足读事件的fd if(FD_ISSET(i,&rset)){ //找到满足读事件的fd n = read(i,buf,sizeof(buf)); if(n == 0){ //检测到客户端已经关闭连接 close(i); FD_CLR(i,&allset); //将关闭的fd移除出监听集合 } for(j = 0; j < n;j++) buf[j] = toupper(buf[j]); write(i,buf,n); write(STDOUT_FILENO,buf,n); } } } close(listenfd); return 0; }
前ICPC算法竞赛退役选手|现摸鱼ing