【TCP/IP】多进程服务器的实现(进阶) - 用I/O分割优化回声客户端

      之前实现的回声客户端按照先向服务器端发送数据,直到服务器端收到回声数据后,再传输下一批数据。很大程度会影响端与端之间的数据交换效率(存在一个等待周期)。那么有什么办法可以解决这个问题呢?

I/O分割

        之前的回声客户端,采用的是单进程模式。我们不妨采用一种新的设计思路——用客户端的父进程接收数据,创建出子进程来发送数据,这样就可以使得同一客户端下不同进程分别去完成输入和输出操作。这样,无论服务器是否收到数据,都可以让客户端持续进行I/O操作。我们把这种处理方式称之为I/O分割。

        通过I/O分割,可以一定程度上提高频繁交换数据的程序的性能。因为分割I/O之后,发送数据时无需再去考虑接收数据的情况,使得程序能够连续发送数据,进而提高数据的吞吐量。(在网速较慢的情况下,做了I/O分割的程序性能一般远高于未做分割的)

代码实现

        知道了I/O分割的意义所在,那么接下来,让我们用I/O分割思想去实现对之前回声客户端的优化。

echo_mclient.cpp

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define BUF_SIZE 1024

void Read_routine(int sock, char *buf);
void Write_routine(int sock, char *buf);
void Sender_message(char *message);

int main(int argc, char *argv[])
{
    int sock;
    int port;
    pid_t pid;
    std::string ipAddress;
    char buf[BUF_SIZE];
    struct sockaddr_in serv_adr;

    std::cout << "Please input IP and port that you want to connect:" << std::endl;
    std::cin >> ipAddress >> port;

    sock = socket(PF_INET, SOCK_STREAM, 0);
    if (sock == -1)
    {
        Sender_message((char *)"Socket creation error");
    }

    memset(&serv_adr, 0, sizeof(serv_adr));
    serv_adr.sin_family = AF_INET;
    serv_adr.sin_addr.s_addr = inet_addr(ipAddress.c_str());
    serv_adr.sin_port = htons(port);

    if (connect(sock, (struct sockaddr *)&serv_adr, sizeof(serv_adr)) == -1)
    {
        Sender_message((char *)"Connect error!");
    }
    // 创建子进程
    pid = fork();
    // 如果是子进程,那么进行写操作(发送数据);父进程则进行读操作(接收数据)
    pid == 0 ? Write_routine(sock, buf) : Read_routine(sock, buf);

    close(sock);
    return 0;
}

void Read_routine(int sock, char *buf)
{
    while (1)
    {
        int str_len = read(sock, buf, BUF_SIZE);
        if (str_len == 0)
        {
            return;
        }
        buf[str_len] = 0;
        printf("Message from server: %s", buf);
    }
}

void Write_routine(int sock, char *buf)
{
    while (1)
    {
        fgets(buf, BUF_SIZE, stdin);
        // 如果输入为q或Q,则关闭套接字写权限
        if (!strcmp(buf, "Q\n") || !strcmp(buf, "q\n"))
        {
            // 关闭套接字写权限
            shutdown(sock, SHUT_WR);
            return;
        }
        write(sock, buf, strlen(buf));
    }
}

void Sender_message(char *message)
{
    puts(message);
    exit(1);
}

你可能感兴趣的:(#,网络编程,服务器,tcp/ip,网络,网络协议,udp)