zoukankan      html  css  js  c++  java
  • 网络阻塞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。

  • 相关阅读:
    Mvc+三层(批量添加、删除、修改)
    js中判断复选款是否选中
    EF的优缺点
    Git tricks: Unstaging files
    Using Git Submodules
    English Learning
    wix xslt for adding node
    The breakpoint will not currently be hit. No symbols have been loaded for this document."
    Use XSLT in wix
    mfc110ud.dll not found
  • 原文地址:https://www.cnblogs.com/manch1n/p/15322147.html
Copyright © 2011-2022 走看看