记录原生socket编写服务端

原生socket编写服务端close后立即bind失败,原因socket会延迟关闭,解决方案--设置端口复用

   self.fd = socket(AF_INET,SOCK_STREAM,0);
    int opt = 1;
    setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(opt));
    self.server_addr = inet_addr("127.0.0.1");
    //set server addr info
    struct sockaddr_in server_addr;
    bzero(&server_addr, sizeof(struct sockaddr_in));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(port);
    if(bind(self.fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0){
        DTLogError(@"bind error\n");
        return -1;
    }
    if(listen(self.fd, 65535) < 0){
        DTLogError(@"listen error\n");
        return -2;
    }

关于kqueue

    //创建Kqueue结构体数组
    struct kevent change_event[1024],event[1024];
    //创建对端地址结构体
    struct sockaddr_in client_addr;
    size_t client_len  = sizeof(struct sockaddr_in);
    // Prepare the kqueue.
    int kq = kqueue();
    //Set listen fd
    int fd = self.fd;
    //添加服务端fd,以监听连接syn
    EV_SET(change_event, fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
    // 注册kqueue监听
    if (kevent(kq, change_event, 1, NULL, 0, NULL) == -1)
    {
        perror("kevent");
        return;
    }
    self.status = YES;
    while (self.status)
    {
        // 获取事件
        int new_events = kevent(kq, NULL, 0, event, 1, NULL);
        //时间数为-1则获取失败,退出循环
        if (new_events == -1)
        {
            perror("kevent");
            self.status = NO;
        }
        //遍历事件
        for (int i = 0; new_events > i; i++)
        {
            //获取事件的描述符
            int event_fd = (int)event[i].ident;
            
          //如果描述符和监听描述符一致,则为客户端连接请求
           if (event_fd == fd)
            {
                
                // Accept客户端,获取与该客户端连接的FD
                int socket_connection_fd = accept(event_fd, (struct sockaddr *)&client_addr, (socklen_t *)&client_len);
                if (socket_connection_fd == -1)
                {
                    perror("Accept socket error");
                }
               
                        //添加fd到kqueue监听
                        EV_SET(change_event, socket_connection_fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
                        if (kevent(kq, change_event, 1, NULL, 0, NULL) < 0)
                        {
                            perror("kevent error");
                        }
                
                
            }else{
            //连接终止
            if (event[i].flags & EV_EOF)
            {
                //关闭socket
                close(event_fd);
            
            }
            
            
            else if (event[i].filter & EVFILT_READ)
            {
                //此时您可以调用read()去读取数据,可以在循环的任意处写,但是不能异步调用,可以用一个专用socket与本监听通信间接写保证安全
       
  
            }
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值