Select服务器

select

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>

int array_fds[1024];

static void Usage(const char *proc)
{
    printf("Usage: %s [local_ip] [local_port]\n",proc);
}

int startup(char *_ip, int _port)
{
    int sock = socket(AF_INET,SOCK_STREAM,0);
    if(sock < 0)
    {
        perror("sock");
        exit(2);
    }

    int flag = 1;
    setsockopt(sock, SOL_SOCKET,SO_REUSEADDR,&flag,sizeof(flag));

    struct sockaddr_in local;
    local.sin_family = AF_INET;
    local.sin_port = htons(_port);
    local.sin_addr.s_addr = inet_addr(_ip);

    if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)
    {
        perror("bind");
        exit(3);
    }

    if(listen(sock,10)<0)
    {
        perror("listen");
        exit(4);
    }

    return sock;
}
int main(int argc,char* argv[])
{
    if(argc != 3)
    {
        Usage(argv[0]);
        return 0;
    }

    int listenSock = startup(argv[1],atoi(argv[2]));
    int maxfd = 0;

    fd_set rfds;

    int array_size = sizeof(array_fds)/sizeof(array_fds[0]);
    array_fds[0] = listenSock;
    int i = 1;
    for(;i < array_size;i++)
    {
        array_fds[i] = -1;
    }

    while(1){
        struct timeval _timeout = {0,0};
        FD_ZERO(&rfds);
        maxfd = -1;
        for(i = 0;i<array_size;i++){
            if(array_fds[i] > 0){
                FD_SET(array_fds[i],&rfds);
                if(array_fds[i] > maxfd){
                    maxfd = array_fds[i];
                }
            }
        }

        switch(select(maxfd+1,&rfds,NULL,NULL,NULL/*&_timeout*/)){
            case 0:
                printf("timeout...\n");
                break;
            case -1:
                perror("select");
                break;
            default:
                {
                    int j = 0;
                    for(;j < array_size;j++){
                        if(array_fds[j]<0){
                            continue;
                        }
                        if(j == 0&&FD_ISSET(array_fds[j],&rfds)){
                            struct sockaddr_in client;
                            socklen_t len = sizeof(client);
                            int new_fd = accept(array_fds[j],\
                                    (struct sockaddr*)&client,&len);
                            if(new_fd < 0){
                                perror("accept");
                                continue;
                            }
                            else{
                                printf("get a new client: (%s:%d)\n",\
                                        inet_ntoa(client.sin_addr),\
                                        ntohs(client.sin_port));
                                int k = 1;
                                for(;k < array_size;k++){
                                    if(array_fds[k] < 0){
                                        array_fds[k] = new_fd;
                                        break;
                                    }
                                }
                                if(k == array_size){
                                    close(new_fd);
                                }
                            }
                        }
                        else if(j != 0&&\
                                FD_ISSET(array_fds[j],&rfds))
                        {
                            char buf[10240];
                            ssize_t s = read(array_fds[j],buf,sizeof(buf)-1);
                            if(s>0)
                            {
                                buf[s] = 0;
                                printf("client say: %s\n",buf);
                            }
                            else if(s == 0)
                            {
                                printf("client quit!\n");
                                close(array_fds[j]);
                                array_fds[j] = -1;
                            }
                            else
                            {
                                perror("read");
                                close(array_fds[j]);
                                array_fds[j] = -1;
                            }
                        }
                        else
                        {

                        }
                    }
                }
                break;
        }
    }
    return 0;
}

client

#include<stdio.h>  
#include<sys/types.h>  
#include<netinet/in.h>  
#include<arpa/inet.h>  
#include<sys/socket.h>  
#include<stdlib.h>  
#include<string.h>  
#include<strings.h>  
#include<sys/stat.h>  
#include<unistd.h>  
static void Usage(char * proc)  
{  
    printf("Usage : %s [ip] [port]\n");  
}  

int main(int argc, char* argv[])  
{  
    if(argc != 3)  
    {  
        Usage(argv[0]);  
        return 1;  
    }  

    int sock = socket(AF_INET, SOCK_STREAM, 0);  
    struct sockaddr_in peer;  
    peer.sin_family = AF_INET;  
    peer.sin_port = htons(atoi(argv[2]));  
    peer.sin_addr.s_addr = inet_addr(argv[1]);  

    if(connect(sock, (struct sockaddr*)&peer, sizeof(peer)) < 0)  
    {  
        perror("connect");  
        return 2;  
    }  

    char buf[10240];  
    //int sfd = dup(STDOUT_FILENO);  
    while(1)  
    {  
        printf("Please Enter : ");  
        fflush(stdout);  
        ssize_t s = read(0, buf, sizeof(buf)-1);  
        int sfd = dup(STDOUT_FILENO);  
        if(s > 0)  
        {  
            buf[s-1] = 0;  
            //write(sock, buf, strlen(buf));  
            //输出重定向  
            //close(1);  
           // int new_fd = dup(sock);  
           int new_fd = dup2(sock, 1);  
            if(new_fd == -1)  
            {  
               perror("dup()");  
               return -1;  
            }  
            printf("%s",buf);  
            fflush(stdout);  
            //恢复stdout  
            dup2(sfd, STDOUT_FILENO);  

            ssize_t _s = read(sock, buf, sizeof(buf)-1);  
            if(_s > 0)  
            {  
               buf[_s] = 0;  
               printf("sever # %s \n", buf);  
            }  
        }  
    }  
    close(sock);  
    return 0;  
}  

总结select服务器优缺点,与多进程/多线程服务器进行对比:
使用select注意事项:
1.要将sock_fd加入到maxfd+1中,要不就无法检测到网络连接,会一直阻塞在select语句
2.通过存储每次连接的描述符,设置FD_SET函数,在遍历的去判断FD_ISSET处理。
3.我们可以看到select每次有数据到来时,需要遍历的去寻找所有可用的描述符,来判断其是否满足处理的条件。
4.select的通知机制,轮询的去查看是否在maxfd+1内有满足条件的描述符
select优缺点:
与多进程/多线程服务器进行对比 它的优点在于:
1、不需要建立多个线程、进程就可以实现一对多的通信。
2、可以同时等待多个文件描述符,效率比起多进程多线程来说要高很多。
3、select()的可移植性更好,在某些Unix系统上不支持poll()
4、select() 对于超时值提供了更好的精度:微秒,而poll是毫秒

与多进程/多线程服务器进行对比 它的缺点在于:
1、每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大 ,循环次数有点多;
2、同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大 。
3、select支持的文件描述符数量太小了,默认是1024;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值