poll_echo_server
来源:互联网 发布:vs画图软件 编辑:程序博客网 时间:2024/05/01 22:48
poll
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#include <poll.h>#include <limits.h>#include <signal.h>#define MAX_SIZE 100#define OPEN_MAX 1024#define ENOSPACE 1#define INFTIM -1 //linux 没有找到头文件struct pollfd client[OPEN_MAX];/*当fork时,必须捕获SIGCHLD信号 * 捕获信号,必须处理被中断的系统调用 * SIGCHLD信号处理函数必须正确编写,不能留下僵尸进程 *//*void client_handle(int fd){ char buf[MAX_SIZE]; int len; while(1) { len = read(fd,buf,MAX_SIZE); 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) { 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); if(pid > 0) printf("child %d terminal\n",pid); else return; }}*/void init_pollfd(int listen_fd){ int i; client[0].fd = listen_fd; client[0].events = POLLRDNORM; for(i=1;i<OPEN_MAX;i++) client[i].fd = -1; }int add_client(int fd,int *max){ int i; for(i=0;i<OPEN_MAX;i++) { if(client[i].fd < 0) { client[i].fd = fd; client[i].events = POLLRDNORM; if(i > *max ) *max = i; return 0; } } if(i == OPEN_MAX) return ENOSPACE;}int main(){ int listen_fd = socket(AF_INET,SOCK_STREAM,0); if(listen_fd < 0) perror("listen error"); init_pollfd(listen_fd); int max_index = 0; 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); if(err < 0) perror("listen error"); while(1) { int nready = poll(client,max_index+1,INFTIM); if(client[0].revents & POLLRDNORM) { 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) continue; add_client(client_fd,&max_index); nready--; if(nready<=0) continue; } int i; for(i=0;i<OPEN_MAX;i++) { char rcv[MAX_SIZE]; if(client[i].fd < 0) continue; if(client[i].revents & (POLLRDNORM | POLLERR)) { int n = read(client[i].fd,rcv,MAX_SIZE); if(n<0) { if(errno == ECONNRESET) { close(client[i].fd); client[i].fd = -1; } } else if(n==0) { close(client[i].fd); client[i].fd = -1; printf("rcv fin from peer\n"); } else { rcv[n] = '\0'; printf("%s\n",rcv); write(client[i].fd,rcv,n); } nready--; if(nready <=0) break; } } } /* 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) continue; pid_t pid = fork(); if(pid > 0) { close(client_fd); } else { close(listen_fd); client_handle(client_fd); exit(1); } } */ return 0;}
client.c
#include <sys/socket.h>#include <string.h>#include <stdlib.h>#include <errno.h>#include <sys/types.h>#include <stdio.h>//fileno#include <arpa/inet.h>//htons#include <signal.h>#include <sys/time.h>//select#include <sys/select.h>//select/* * 缺点:stdio是有缓冲的,select不知道stdio使用了缓冲区,他只是从read系统调用的角度指出是否有数据可读 * 可能发送的速率远大于接收,当发送结束后仍就有数据要接收,所以当发送结束时shutdown(fd,SHUT_WR),FD_CLR(fileno(stdio),&rset) */int max(int a, int b){ return a>b?a:b;}#define MAX_SIZE 100 void send_echo_fun(int fd) { char buf_snd[MAX_SIZE]; char buf_rcv[MAX_SIZE]; int len; fd_set rset; FD_ZERO(&rset); while(1) { FD_SET(fileno(stdin),&rset); FD_SET(fd,&rset); int maxfd = max(fileno(stdin),fd) + 1; select(maxfd,&rset,NULL,NULL,NULL); if(FD_ISSET(fd,&rset)) { int len = read(fd,buf_rcv,MAX_SIZE); if(len == 0) { printf("rcv fin from peer\n"); printf("tag\n"); return; } buf_rcv[len]='\0'; printf("%s\n",buf_rcv); } if(FD_ISSET(fileno(stdin),&rset)) { char *s = fgets(buf_snd,MAX_SIZE,stdin); if(s == NULL) break; int n = strlen(buf_snd)-1; if(n>0) { write(fd,buf_snd,n); } } }}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;}
0 0