• C/C++网络编程10——I/O复用服务器端实现select方式


     

    #include <iostream>
    #include <cstdlib>
    #include <string>
    #include <cstring>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    #include <sys/time.h>
    #include <sys/select.h>
    
    using namespace std;
    
    #define BUF_SIZE 100
    
    void deal_error(string error_msg)
    {
        cout << error_msg << endl;
        exit(1);
    }
    
    int before_socket_accept()
    {
        int ser_sock = 0;
        ser_sock = socket(PF_INET, SOCK_STREAM, 0);
        if (ser_sock == -1) {
            deal_error("socket() failed");
            return ser_sock;
        }
    
        sockaddr_in ser_addr;
        ser_addr.sin_family = AF_INET;
        ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        ser_addr.sin_port = htons(33333);
        if (bind(ser_sock, (sockaddr *)&ser_addr, sizeof(ser_addr)) == -1) {
            close(ser_sock);
            deal_error("bind() failed");
            return -1;
        }
    
        if (listen(ser_sock, 5) == -1) {
            close(ser_sock);
            deal_error("listen() failed");
            return -1;
        }
    
        return ser_sock;
    }
    
    void accept_connect(int ser_sock)
    {
        fd_set reads;
        FD_ZERO(&reads);
        FD_SET(ser_sock, &reads);
        int fd_max = ser_sock;
        char message[BUF_SIZE];
    
        while(true) {
            fd_set cpy_reads = reads;
            timeval timeout;
            timeout.tv_sec = 5;
            timeout.tv_usec = 500;
            int fd_num = select(fd_max + 1, &cpy_reads, 0, 0, &timeout);
            if (fd_num == -1) {
                break;
            } else if (fd_num == 0) {      // select超时返回
                continue;
            } else {    // select监测到有变化
                for (int i = 0; i < fd_max + 1; i++) {
                    if (FD_ISSET(i, &cpy_reads)) {
                        if (i == ser_sock) {    // 如果是服务器端的套接字描述符发生变化,说明是客户端连接请求(SYN报文)
                            // 接受客户端的连接请求
                            sockaddr_in clnt_addr;
                            socklen_t addr_length = sizeof(clnt_addr);
                            int clnt_sock = accept(ser_sock, (sockaddr *)&clnt_addr, &addr_length);
                            FD_SET(clnt_sock, &reads);
                            if (fd_max < clnt_sock) {
                                fd_max = clnt_sock;
                            }
                        } else {    //  接收客户端的数据,并回传给客户端
                            int str_len = read(i, message, BUF_SIZE);
                            if (str_len == 0) {
                                FD_CLR(i, &reads);
                                close(i);
                            } else {
                                write(i, message, str_len);
                            }
                        }
                    }
                }
            }
        }
    }
    
    int main()
    {
        int ser_sock = before_socket_accept();
        if (ser_sock == -1) {
            return 0;
        }
    
        accept_connect(ser_sock);
    
        close(ser_sock);
        return 0;
    }
  • 相关阅读:
    C# IP地址字符串和数值转换
    Xstream序列化实体
    异步线程及同步控制
    XML序列化与反序列化(转)
    C# Webserice 代理生成工具(WSDL)
    ASP.NET(C#)图片加文字、图片水印(转)
    异步导致UI句柄增加的解决办法
    终于找到WinForm自定义控件不能拖到IDE设计器容器的办法
    C# PropertyGrid控件应用心得(转载)
    GDI_图片半透明效果示例
  • 原文地址:https://www.cnblogs.com/418ks/p/11726693.html
Copyright © 2020-2023  润新知