socket经典IO多路复用,C实现

select

#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>

/*
FD_SETSIZE

fd_set
{
    FD_ISSET, FD_CLR, FD_SET, FD_ZERO
}
timeval

ready
1. SO_RCVLOWAT, >= TCP_UDP_socket --> default 1
2. FIN --> TCP, read down
3. listen_socket, connected count > 0

1. SO_SNDLOWAT, ~ 2048
2. ~ write down, produce SIGPIPE

*/

static char* IP_ADDR = "127.0.0.1";
static unsigned PORT = 8080;
static unsigned MAX_FD = 100;
static unsigned BS = 1024;

int main(void)
{
   
    int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    if(socket_fd == -1){
   
        printf("create socket fail = %d\n", errno);
        return -1;
    }
    int skopt = 1;
    if(setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,&skopt,sizeof(skopt)) < 0){
   
        printf("setsockopt fail = %d\n", errno);
        return -1;
    }
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));
    {
   
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_addr.s_addr = inet_addr(IP_ADDR);
        serv_addr.sin_port = htons(PORT);
    }
    if(bind(socket_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0){
   
        printf("bind ip_addr fail = %d\n", errno);
        return -1;
    }
    if(listen(socket_fd, 10) < 0){
   
        printf("listen socket fail = %d\n", errno);
        return -1;
    }
    fd_set all_fds;
    FD_ZERO(&all_fds);
    FD_SET(socket_fd, &all_fds);
    int maxfd_arg = socket_fd; 
    struct timeval tOut = {
   59,1000000};
    int client_fds[MAX_FD];
    for(int i = 0; i < MAX_FD; ++i){
   
        client_fds[i] = -1;
    }
    int max_cfd = -1;
    for(;;){
   
        fd_set rfds = all_fds;
        struct timeval tval = tOut;
        int sl_ret = select(maxfd_arg+1, &rfds, NULL, NULL, &tval);
        if(sl_ret == -1){
   
            printf("select fail = %d\n", errno);
            return -1;
        }
        else if(sl_ret == 0){
   
            printf("select timeout\n");
            //return 0;
        }
        if(FD_ISSET(socket_fd, &rfds)){
   
            int client_fd = accept(socket_fd, NULL, NULL);
            if(client_fd == -1){
   
                printf("accept client fail = %d\n", errno);
                return -1;
            }
            int i;
            for(i = 0; i < MAX_FD; ++i){
   
                if(client_fds[i] < 0){
   
                    client_fds[i] = client_fd;
                    FD_SET(client_fd, &all_fds);
                    max_cfd = max_cfd <= i ? i+1 : max_cfd;
                    maxfd_arg = maxfd_arg < client_fd ? client_fd : maxfd_arg;
                    break;
                }
            }
            if(i == MAX_FD){
   
                printf("too much client_fds\n");
                return -1;
            }
            char acc_str[BS];
            sprintf(acc_str, "hello world %d !",client_fd);
            write(client_fd, acc_str, strlen(acc_str));
            if(--sl_ret <= 0){
   
                continue;
            }
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值