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;
}
原文地址:https://www.cnblogs.com/418ks/p/11726693.html