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