socket编程之select多路复用

/*************************************************************************
 *  Copyright (C): 1540999272@qq.com
 *  Filename:      server.c
 *  Author:        Lu Zengmeng
 *  Description:   
 *  Creat Time:    2016-07-19 12:08
 ************************************************************************/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>

#define PORT             8003
#define BUF_LEN          128
#define BACKLOG          5

int main(int argc, char *argv[])
{
        int                    sock_fd;
        int                    conn_fd;
        int                    yes = 1;
        struct sockaddr_in     my_addr;

    bzero(&my_addr,sizeof(my_addr));
    my_addr.sin_family        = AF_INET;
    my_addr.sin_port          = htons(PORT);
    my_addr.sin_addr.s_addr   = INADDR_ANY;


    if (-1 == (sock_fd = socket(AF_INET, SOCK_STREAM, 0)))
    {
        perror("socket");
        exit(1);
    }
    
    if (-1 == setsockopt(sock_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)))
    {
        perror("setsockopt");
        exit(1);
    }

    if (-1 == bind(sock_fd, (struct sockaddr *)&my_addr, sizeof(my_addr)))
    {
        perror("bind");
        exit(1);
    }

    if (-1 == listen(sock_fd, BACKLOG))
    {
        perror("listen");
        exit(1);
    }

    printf("listenning...\n");

    fd_set         fds; //创建select所要检查的集合fds
    int            max_fd;
    int            ret;
    int            i;
    int            conn_amount = 0;
    int            fd_all[BACKLOG]= {0,}; //用来存放需要通信的多个socket描述符
    struct timeval tv;
    char           recv_buf[BUF_LEN];

    max_fd = sock_fd;

    while(1)
    {
        FD_ZERO(&fds); //初始化关注列表
        FD_SET(sock_fd,&fds); //将listen的sock_fd加入关注

        tv.tv_sec  = 5;
        tv.tv_usec = 0;

        for(i=0;i<BACKLOG;i++) //将所有需要通信的socket描述符存入fd_all数组
        {
            if(fd_all[i] != 0)
                FD_SET(fd_all[i],&fds);
        }

        ret = select(max_fd+1,&fds,NULL,NULL,&tv);
        if(ret < 0)
        {
            perror("select");
            break;
        }

        else if(0 == ret)
        {
            printf("timeout\n");
            continue;
        }

        for(i=0;i<conn_amount;i++)
        {
            if(FD_ISSET(fd_all[i],&fds)) //检查已建立的连接是否有数据请求
            {
                ret = recv(fd_all[i],recv_buf,BUF_LEN,0);
                if(ret <= 0)
                {
                   printf("client[%d] closed \n",fd_all[i]);
                   close(fd_all[i]);
                   FD_CLR(fd_all[i],&fds);  //清除已关闭的socket描述符
                   fd_all[i] = 0;
                   //conn_amount--;
                }
                else
                {
                    recv_buf[ret] = '\0';
                    fflush(stdout);
                    printf("%s from client[%d]\n",recv_buf,fd_all[i]);
                }    
            }
        }

        if(FD_ISSET(sock_fd,&fds))  //检查是否有连接请求
        {
            conn_fd = accept(sock_fd,NULL,NULL);
            if( conn_fd < 0)
            {
                perror("accept");
                continue;
            }

            if(conn_amount < BACKLOG)
            {
                fd_all[conn_amount++] = conn_fd;  //将新建立的连接加入关注
                printf("new connection client[%d] \n",conn_fd);

                if(conn_fd > max_fd)  //重新设置max_fd
                    max_fd = conn_fd;
            }

            else
            {
                printf("max connections arrive,exit\n");
                close(conn_fd);
                break;
            }
        }

        printf("Client amount: %d\n",conn_amount);
        for(i=0;i<BACKLOG;i++)
        {
            if(fd_all[i]!=0)
                printf("client[%d] \n",fd_all[i]);
        }
        printf("\n");

    }

    for(i=0;i<BACKLOG;i++)
    {
        if(fd_all[i] != 0)
            close(fd_all[i]); //关闭所有fd
    }

        return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值