基于windows的使用select的I/O复用回显服务器端

使用过select函数可以将多个文件描述符集中到一起监视,集中时也要按照监视项(接收、传输、异常)区分。

服务器端:

#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h>

#define BUF_SIZE 1024

void ErrorHandling(char* message);

int main()
{
    WSADATA wsa_data;
    SOCKET server_sock, client_sock;
    SOCKADDR_IN server_addr, client_addr;
    TIMEVAL time_out;
    fd_set reads, temp_reads;

    int addr_size;
    int str_len, fd_num;
    char buf[BUF_SIZE];

    if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0)
        ErrorHandling("WSAStartup() error.");

    server_sock = socket(PF_INET, SOCK_STREAM, 0);
    if (server_sock == INVALID_SOCKET)
        ErrorHandling("socket() error.");

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(8000);

    if (bind(server_sock, (SOCKADDR*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR)
        ErrorHandling("bind() error.");
    if (listen(server_sock, 5) == SOCKET_ERROR)
        ErrorHandling("listen() error.");

    FD_ZERO(&reads);
    FD_SET(server_sock, &reads);
    while (true)
    {
        temp_reads = reads;
        time_out.tv_sec = 5;
        time_out.tv_usec = 5000;
        if ((fd_num = select(0, &temp_reads, 0, 0, &time_out)) == SOCKET_ERROR)
            break;
        if (fd_num == 0)
            continue;
        for (int i = 0; i < reads.fd_count; ++i)
        {
            if (FD_ISSET(reads.fd_array[i], &temp_reads))
            {
                if (reads.fd_array[i] == server_sock) // connection request
                {
                    addr_size = sizeof(client_addr);
                    client_sock = accept(server_sock, (SOCKADDR*)&client_addr, &addr_size);
                    if (client_sock == INVALID_SOCKET)
                        ErrorHandling("accept() error.");
                    FD_SET(client_sock, &reads);
                    printf("connected client: %d\n", client_sock);
                }
                else // read message
                {
                    str_len = recv(reads.fd_array[i], buf, BUF_SIZE - 1, 0);
                    if (str_len == 0)
                    {
                        FD_CLR(reads.fd_array[i], &reads);
                        closesocket(temp_reads.fd_array[i]);
                        printf("close client: %d\n", temp_reads.fd_array[i]);
                    } 
                    else
                    {
                        send(reads.fd_array[i], buf, str_len, 0); // echo
                    }
                }
            }
        }
    }
    closesocket(server_sock);
    WSACleanup();
    return 0;
}

void ErrorHandling(char* message)
{
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

客户端:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <WinSock2.h>

#define BUF_SIZE 1024

void ErrorHandling(char* message);

int main()
{
    WSADATA wsa_data;
    SOCKET h_socket;
    SOCKADDR_IN server_addr;
    char message[BUF_SIZE];
    int str_len;

    if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0)
        ErrorHandling("WSAStartup() error.");

    h_socket = socket(PF_INET, SOCK_STREAM, 0);
    if (h_socket == INVALID_SOCKET)
        ErrorHandling("socket() error.");

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    server_addr.sin_port = htons(8000);

    if (connect(h_socket, (SOCKADDR*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR)
        ErrorHandling("connect() error.");
    else
        puts("Connect......");

    while (true)
    {
        fputs("Insert message(q to quit): ", stdout);
        fgets(message, sizeof(message), stdin);
        if (!strcmp(message, "q\n") || !strcmp(message, "Q\n"))
            break;
        send(h_socket, message, strlen(message), 0);
        str_len = recv(h_socket, message, sizeof(message) - 1, 0);
        message[str_len] = 0;
        printf("Message from server: %s", message);
    }
    closesocket(h_socket);
    WSACleanup();
    return 0;
}

void ErrorHandling(char* message)
{
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

猜你喜欢

转载自www.cnblogs.com/ACGame/p/9914732.html