select 优化socket回射服务器

来源:互联网 发布:中宣部知乎 编辑:程序博客网 时间:2024/06/04 22:46

注意:readset被每次需要重新set,所以用allset先保存下来,每次重新赋值给readset

server.c

#include <unistd.h>#include <sys/stat.h>#include <sys/wait.h>#include <sys/types.h>#include <fcntl.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <signal.h>#include <arpa/inet.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>/* int socket(int domain, int type, int protocol); *//* int bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen); //man 2 bind struct sockaddr { sa_family_t sa_family; char        sa_data[14]; } //man 7 ip struct sockaddr_in { sa_family_t    sin_family; // address family: AF_INET u_int16_t      sin_port;   // port in network byte order struct in_addr sin_addr;   // internet address }; //Internet address. struct in_addr { u_int32_t      s_addr;     //address in network byte order }; *///int listen(int sockfd, int backlog);//int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);/*        On success, accept() returns a non-negative integer that is a descriptor for the accepted socket.        On  error, -1 is returned, and errno is set appropriately. */int main(){        int sockfd = 0;        sockfd = socket(AF_INET, SOCK_STREAM, 0);        if (sockfd == -1)        {                perror("fun socket");                exit(0);        }        struct sockaddr_in srvaddr;        srvaddr.sin_family = AF_INET;        srvaddr.sin_port = htons(8001);        srvaddr.sin_addr.s_addr = (INADDR_ANY);        int on = 1;        //bind socket error: Address already in use        if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)        {                perror("setsockopt");                return -1;        }        if (bind(sockfd, (struct sockaddr *) &srvaddr, sizeof(srvaddr)) < 0)        {                perror("fun bind");                return -1;        }        if (listen(sockfd, SOMAXCONN) < 0)        {                perror("fun listen");                return -1;        }        int i;        int client[FD_SETSIZE];        int maxi = 0;        memset(client,-1,FD_SETSIZE);        fd_set read_set;        fd_set all_set;        FD_ZERO(&read_set);        FD_ZERO(&all_set);        int maxfd = sockfd;        FD_SET(sockfd,&all_set);        while(1)        {                read_set = all_set;//重新准备要被监听的文件描述符集合,这也是select的缺点之一                int nready = select(maxfd+1,&read_set,NULL,NULL,NULL);                if(nready == -1)                {                        if(errno == EINTR)                                continue;                        return -1;                }                else if(nready == 0)                {                                continue;//timeout                }                if(FD_ISSET(sockfd,&read_set))                {                        struct sockaddr_in peer_addr;                        //The  addrlen  argument is a value-result argument: the caller must initialize it to contain the size (in bytes) of the structure pointed to by addr;                        socklen_t peerlen = sizeof(peer_addr);                        int conn = accept(sockfd,(struct sockaddr*)&peer_addr,&peerlen);                        if(conn == -1)                        {                                perror("accept error");                                return -1;                        }                        printf("perradd:%s\n perrport:%d\n", inet_ntoa(peer_addr.sin_addr), ntohs(peer_addr.sin_port));                        for(i = 0; i < FD_SETSIZE; i++)                        {                                if(client[i] == -1)                                {                                        client[i] = conn;                                        if(i > maxi)                                                maxi = i;                                        break;                                }                        }                        FD_SET(conn,&all_set);                        if(conn > maxfd)                                maxfd = conn;                        if(--nready > 0)                                continue;                }                for(i = 0; i <= maxi; i++)                {                        int conn = client[i];                        if(conn == -1)                                continue;                        if(FD_ISSET(conn,&read_set))                        {                                char recvbuf[1204];                                memset(recvbuf,0x00,sizeof(recvbuf));                                int nread = read(conn,recvbuf,sizeof(recvbuf));                                if(nread == 0)                                {                                        printf("peer has closed\n");                                        FD_CLR(conn,&all_set);                                        client[i] = -1;                                        close(conn);                                }                                fputs(recvbuf,stdout);                                write(conn,recvbuf,nread);                                memset(recvbuf,0x00,sizeof(recvbuf));                        }                }        }        return 0;}



client.c

#include <unistd.h>#include <sys/stat.h>#include <sys/wait.h>#include <sys/types.h>#include <fcntl.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <signal.h>#include <arpa/inet.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/select.h>#include <sys/time.h>#include <unistd.h>/* int socket(int domain, int type, int protocol); *//* int bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen); //man 2 bind struct sockaddr { sa_family_t sa_family; char        sa_data[14]; } //man 7 ip struct sockaddr_in { sa_family_t    sin_family; // address family: AF_INET u_int16_t      sin_port;   // port in network byte order struct in_addr sin_addr;   // internet address }; //Internet address. struct in_addr { u_int32_t      s_addr;     //address in network byte order }; *///int listen(int sockfd, int backlog);//accept 接受一个新的连接 ,这个新的连接是一个主动套接字/*   int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); On success, accept() returns a non-negative integer that is a descriptor for the accepted socket.   On  error, -1 is returned, and errno is set appropriately. int conn = 0; */int main(int argc,char *argv[]){        if(argc != 2)        {                printf("./client IPAddress\n");                return -1;        }        int sockfd = 0;        sockfd = socket(AF_INET, SOCK_STREAM, 0);        if (sockfd == -1) {                perror("fun socket\n");                exit(0);        }        struct sockaddr_in srvaddr;        srvaddr.sin_family = AF_INET;        srvaddr.sin_port = htons(8001);        srvaddr.sin_addr.s_addr = inet_addr(argv[1]); //127.0.0.1        if (connect(sockfd, (struct sockaddr*) (&srvaddr), sizeof(srvaddr)) < 0) {                perror("fun socket\n");                exit(0);        }        printf("connect success\n");        char revbuf[1024] = { 0 };        char sendbuf[1024] = { 0 };        /*        while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL) {                //向服务写数据                write(sockfd, sendbuf, strlen(sendbuf));                //从服务器读数据                read(sockfd, revbuf, sizeof(revbuf));                //                fputs(revbuf, stdout); //从服务器收到数据,打印屏幕                memset(revbuf, 0, sizeof(revbuf));                memset(sendbuf, 0, sizeof(sendbuf));        }        */        fd_set read_set;        FD_ZERO(&read_set);        int stdin_fd = fileno(stdin);        int maxfd = (sockfd > stdin_fd ? sockfd : stdin_fd);        fd_set all_set;        FD_ZERO(&all_set);        FD_SET(stdin_fd,&all_set);        FD_SET(sockfd,&all_set);        while(1)        {                read_set = all_set;                int ret = select(maxfd+1,&read_set,NULL,NULL,NULL);                if(ret == -1)                {                        perror("select error");                        return -1;                }                else if(ret == 0)                {                        printf("timeout\n");                        return -1;                }                else if(ret == 1)                {                        if(FD_ISSET(stdin_fd,&read_set))                        {                                fgets(sendbuf,sizeof(sendbuf),stdin);                                write(sockfd, sendbuf, strlen(sendbuf));                                memset(sendbuf, 0, sizeof(sendbuf));                                printf("write sock\n");                        }                        if(FD_ISSET(sockfd,&read_set))                        {                                int nread = read(sockfd, revbuf, sizeof(revbuf));                                if(nread == 0)                                {                                        printf("peer closed\n");                                        break;                                }                                fputs(revbuf, stdout);                                memset(revbuf, 0, sizeof(revbuf));                                printf("read sock\n");                        }                }        }        close(sockfd);        return 0;}



0 0
原创粉丝点击