• 网络阻塞IO实验


    阻塞IO的阻塞实验

    阻塞实验参考陈硕先生的视频。

    这里的阻塞并不是调用read之后没有写的阻塞,然而实际上也是,但这是发生在网络中的,形成了一个互锁。

    我们假设有一个阻塞实现的echo服务器和客户端,应用层面的发送和接受缓存都是4KB。服务器的代码逻辑是每收到4KB就回送,客户端的代码逻辑是完整的发送消息然后再完整地接受。

    服务器端代码:

    #include "../common_include.hpp"
    
    #include <thread>
    using namespace std;
    
    int main(int argc, char **argv)
    {
        int fd = socket(AF_INET, SOCK_STREAM, 0); //TCP
        assert(fd > 0);
        sockaddr_in servaddr;
        ::bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(55555);
        inet_aton("127.0.0.1", &servaddr.sin_addr);
        int err = bind(fd, SOCK_CAST(&servaddr), sizeof(servaddr));
        assert(err == 0);
        err = listen(fd, 5);
        assert(err == 0);
    
        while (1)
        {
            sockaddr_in client_addr;
            socklen_t client_addr_len;
            int connfd = accept(fd, SOCK_CAST(&client_addr), &client_addr_len);
            std::thread worker([&]()
                               {
                                   int myfd = connfd;
                                   while (1)
                                   {
                                       char buf[4096];
                                       int nread = read(myfd, buf, 4096);
                                       cout << "read " << nread << " bytes" << endl;
                                       if (nread <= 0)
                                       {
                                           break;
                                       }
                                       int nsend = write(myfd, buf, nread);
                                       cout << "send " << nsend << " bytes" << endl;
                                       if (nsend <= 0)
                                       {
                                           break;
                                       }
                                   }
                                   close(myfd);
                               });
            worker.detach();
        }
        return 0;
    }
    

    客户端代码:

    #include "../common_include.hpp"
    
    int main(int argc, char **argv)
    {
        ExitAssert(argc == 3, "usage: ./echo_client port msg_len");
        int fd = socket(AF_INET, SOCK_STREAM, 0); //TCP
        assert(fd > 0);
        sockaddr_in servaddr;
        ::bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(std::atoi(argv[1]));
        inet_aton("127.0.0.1", &servaddr.sin_addr);
    
        int err = connect(fd, SOCK_CAST(&servaddr), sizeof(servaddr));
        ExitAssert(err == 0, "connect");
    
        const size_t msgLen = std::atoi(argv[2]);
        size_t left = msgLen;
        char buf[4096];
        while (left)
        {
            int nwrite = 0;
            if (left > 4096)
            {
                nwrite = write(fd, buf, 4096);
            }
            else
            {
                nwrite = write(fd, buf, left);
            }
            ExitAssert(nwrite >= 0, "write");
            left -= nwrite;
        }
        left = msgLen;
        while (left)
        {
            int nread = 0;
            if (left > 4096)
            {
                nread = read(fd, buf, 4096);
            }
            else
            {
                nread = read(fd, buf, left);
            }
    
            if (nread <= 0)
            {
                break;
            }
            left -= nread;
        }
        std::cout << "read " << msgLen << " bytes" << std::endl;
        close(fd);
        return 0;
    }
    

    运行客户端:./client 55555 20240000

    运行服务端:./server

    发现阻塞现象。

    分析

    通过

    sysctl -A |grep mem
    netstat -anp|grep 55555
    

    知道tcp的发送缓冲最大约为4MB,接收缓冲为6MB,在阻塞实验中,可以看到服务端的接收缓冲已满,客户端的发送缓冲已满。这个过程是客户端以4KB为单位不停地发送,服务端在开始每接收4KB就回送4KB,但是客户端在发送完20MB前并不会调用read接收,这就导致了过一段时间后客户端的接收缓冲会满,从而进而阻塞服务端的send,进而逐渐阻塞服务端的read与客户端的write。

  • 相关阅读:
    就没有我遇不到的报错!java.lang.NoClassDefFoundError: org/apache/hadoop/hbase/filter/Filter
    【HBase】通过Bulkload批量加载数据到Hbase表中
    【HBase】HBase和Hue的整合
    【HBase】协处理器是什么?又能干什么?怎么用?
    【HBase】带你了解一哈HBase的各种预分区
    【HBase】快速了解上手rowKey的设计技巧
    【HBase】HBase和Sqoop整合
    【HBase】快速搞定HBase与Hive的对比、整合
    hive元数据报错?试了很多方法都没辙?也许你漏了这一步
    【HBase】HBase与MapReduce集成——从HDFS的文件读取数据到HBase
  • 原文地址:https://www.cnblogs.com/manch1n/p/15322147.html
Copyright © 2020-2023  润新知