basic_echo_server
来源:互联网 发布:vs画图软件 编辑:程序博客网 时间:2024/05/01 22:56
basic echo server
client.c
#include <sys/socket.h>#include <string.h>#include <stdlib.h>#include <errno.h>#include <sys/types.h>#include <stdio.h>#include <arpa/inet.h>//htons#include <signal.h>#define MAX_SIZE 100 void send_echo_fun(int fd) { char buf_snd[MAX_SIZE]; char buf_rcv[MAX_SIZE]; int len; while(1) { char *s = fgets(buf_snd,MAX_SIZE,stdin);//fget \n\0 if( s == NULL) break; int n = strlen(buf_snd)-1; int len; if(n>0) { len = write(fd,buf_snd,strlen(buf_snd)-1); len = read(fd,buf_rcv,MAX_SIZE); buf_rcv[len]='\0'; printf("rcv %s\n",buf_rcv); if(len == 0) { printf("recv FIN from server\n"); return ; } } }}int main(){ int client_fd ; client_fd = socket(AF_INET,SOCK_STREAM,0); if(client_fd < 0) perror("socket error"); struct sockaddr_in server_sock; server_sock.sin_family = AF_INET; server_sock.sin_port = htons(12345); int err = inet_pton(AF_INET,"127.0.0.1",&server_sock.sin_addr); if(err != 1) perror("inet_pton error"); err = connect(client_fd,(struct sockaddr *)&server_sock,sizeof(server_sock)); if(err == 0) printf("connect ok\n"); send_echo_fun(client_fd); close(client_fd); return 0;}
server.c
#include <stdio.h>#include <unistd.h>//fork#include <sys/types.h>#include <sys/socket.h>#include <errno.h>//peeor#include <stdlib.h>//exit()#include <arpa/inet.h>//inet_pton#include <sys/wait.h>//waitpid#define MAX_SIZE 100/*当fork时,必须捕获SIGCHLD信号 * 捕获信号,必须处理被中断的系统调用 * SIGCHLD信号处理函数必须正确编写,不能留下僵尸进程 */void client_handle(int fd){ char buf[MAX_SIZE]; int len; while(1) { len = read(fd,buf,MAX_SIZE);//read会把\n放在末尾 buf[len]='\0'; printf("recv %s\n",buf); if(len > 0) write(fd,buf,len); else if (len < 0 && errno == EINTR) continue; else if (len == 0) //对于tcp len == 0即读到FIN { printf("recv FIN from client\n"); return ; } else perror("read error"); }}void child_handle(int sigo){ int status; while(1) { pid_t pid = waitpid(-1,&status,WNOHANG);//-1表示等待第一个终止的进程,WNOHANG代表在没有已终止子进程时不阻塞 if(pid > 0) printf("child %d terminal\n",pid); else return; }}int main(){ int listen_fd = socket(AF_INET,SOCK_STREAM,0); if(listen_fd < 0) perror("listen error"); struct sockaddr_in listen_sock; bzero(&listen_sock,sizeof(listen_sock)); listen_sock.sin_family = AF_INET; listen_sock.sin_port = htons(12345); int err = inet_pton(AF_INET,"127.0.0.1",(char *)&listen_sock.sin_addr); if(err < 0) perror("inet_pton error"); err = bind(listen_fd,(struct sockaddr *)&listen_sock,sizeof(listen_sock)); if(err < 0) perror("bind error"); err = listen(listen_fd,5);//note 5 if(err < 0) perror("listen error"); signal(SIGCHLD,child_handle); while(1) { struct sockaddr_in client_addr; int client_addr_len; int client_fd = accept(listen_fd,(struct sockaddr *)&client_addr,&client_addr_len); if(errno == EINTR)//accept 可能被SIGCHLD信号中断 continue; pid_t pid = fork(); if(pid > 0) { close(client_fd);//note the difference between close() and shutdown() } else { close(listen_fd); client_handle(client_fd); exit(1); } } return 0;}
建立一个信号处理函数并在其中调用wait并不足以防止出现僵死进程。本问题在于,若信号都在处理函数之前产生,那么信号处理函数只
执行一次,因为unix的信号一般是不排队的。
正确的解决办法是调用waitpid,在一个循环中调用waitpid,以获取所有已终止子进程的状态
0 0
- basic_echo_server
- basic_echo_server
- 排序算法——选择排序
- Hdu 4009 Transfer water【最小树形图】
- 第十一讲 项目3 买五赠一 买二十赠五 优惠计算
- Feature transformations with ensembles of trees
- 条件变量思路整理
- basic_echo_server
- WebView
- c++ string类函数总结
- next_permutation原理剖析
- C++第五次实验-项目2:数组选择
- poll_echo_server
- 我大一的线性代数学习
- 抽象代数——代数结构
- 2015.4.1 网络群体与市场 正关系与负关系