select 优化socket回射服务器

注意: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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值