Python套接字未从C+;接收所有数据+;助推asio 简而言之

Python套接字未从C+;接收所有数据+;助推asio 简而言之,python,c++,sockets,boost,boost-asio,Python,C++,Sockets,Boost,Boost Asio,我试图从boost::asio服务器(嵌入式系统)发送编码和压缩的图像数据(~300kB),并通过python套接字客户端(笔记本电脑)接收。客户端每次似乎只接收65532字节,而客户端发送大约350000字节 我的想法是,可能有什么东西限制了TCP数据包的大小(boost::asio或pythonsocket或其他)在65535字节左右 协议 客户端向服务器发送长度为5的字符串READY 服务器从客户端接收READY 服务器将消息的长度,一个4字节的uint,传输到客户端(长度仅为消息的长度;

我试图从boost::asio服务器(嵌入式系统)发送编码和压缩的图像数据(~300kB),并通过python套接字客户端(笔记本电脑)接收。客户端每次似乎只接收65532字节,而客户端发送大约350000字节

我的想法是,可能有什么东西限制了TCP数据包的大小(boost::asio或pythonsocket或其他)在65535字节左右

协议
  • 客户端向服务器发送长度为5的字符串
    READY
  • 服务器从客户端接收
    READY
  • 服务器将消息的
    长度
    ,一个4字节的
    uint
    ,传输到客户端(长度仅为消息的长度;即不包括
    长度
    本身)
  • 服务器将消息传输到客户端
  • 客户端从服务器接收
    长度和消息
  • 描述 当建立新连接时,服务器将创建一个新的
    img_session
    对象。发生读取事件时,将调用
    handle\u read()
    函数
    img_流
    是zlib压缩和base64编码的
    std::string
    ,通过
    img_锁
    进行“同步”

    客户端在线程中调用一次
    run\u image()
    。该方法将首先发送一个
    READY
    信号,然后等待服务器响应。服务器的第一个响应将是消息其余部分的长度。然后它将持续接收消息的其余部分,并将其保存在变量
    message
    中。同时,并发线程将对消息进行解码和解压缩,并将图像保存在变量
    帧中

    代码 服务器代码(img\u session.h

    客户端代码(controller.py

    客户日志

    ...
    
    connection from 127.0.0.1:61616
    img_session waiting for READY signal...
    [DEBUG] server.h: instance of img_session found
    [INFO ] IMG READ
    [INFO ] READY signal received...
    [INFO ] img_stream.length() = 349544
    len = 349544
    img_session.cpp: bytes[] = 0 5 85 104
    img_session.cpp: message.length() = 349548
    img_session.cpp: HEAD:  UheJy0vYGZpLgSrIsJMkEmyARMwASZIBNkAiZgQpnQJowJY8Ix4ZUyI
    jITqnrPnnvv62V7KBBCUP3xKyJTYtvKdv8p6Td+2u1jeR5gP/W5oaSVtVRuKh8FvhyTV7095VkDz1u+V
    ZVrbR8nq79cxfbtFI/Pv5/stmcvpbDJVc0sreC8a1fZarPf7722mddXuBeNLPZTsRfFCiusqrzVdw3vO
    1wqjl2rONf6VO0O1Lq1dSCqKmulbLbwp64jqhVchzaUuS3r8Lax2rLpRJWfV2MKm6fL8SuIC6z2x5CLq
    VX5o58xrhTNbjjpvu4edjWW8Yt6X8Yqs5ZNK9iCu7eXWm1LteW9/X0D/ZCKG871OByLGmC3ay3vjU3F3
    rsaitmdbFar3dL1VduS7nBlDWt7LXu1b8m3V9SwVvZW2/7+3Nr+/r+uXY01vy9lLVZmLdu7YFsre92Hr
    b+XrRylHK0eRz1aO+p7qX2vx96wvNd7q/1o63fVeqmjvbfYxrbKj2NtGdV+71qOtKy9+9jXmUdpo+/js
    OW9sar8e1dL6+O92Mpuh7dbnR1lViVt/Y6Tro39vYy9t/1drOvjKvn+2HdbWh+rGdj7bsYqbCddB2L7f
    vTdVt4fsfKuoR8dy7vCVc8x5rGaus57jHasSxv9XWx9fP9+r8+DW+b7nH28D+32+73MPrE+bOO0LcOW9
    8f35mOtzPf2MdZGlZ/Vtmt5l8PhOHDiqLXBtpza+F7KmPvgRhRGtUOHHKp2tyYNtootPHBdOOMx38t5j
    HqM4te789rfy/sGHrxXuF3vjb2tjbh16+69b/tm6/sqj9u4bjWL2eGo7X2WceC8645V+43t3bbbxzn89
    rK221XUdRPsRg0rOXiXum3B3XivzHHyhhxz1dPfV3mui8WucU5bxvsujmvYlvf6NVeBc66P/b1MFFjHv
    rfs65avwnNOHD77+yzn+irnuXcWu/p52oroVjLmHjR5bKm3YjcA/bKdp/hCKVX4laoJrL9C7yuUP8vc1
    1lz/Ydj
    img_session.cpp: TAIL: sC5fp569IQ/fnp9NsY4EfMdjx8cR77ftC8426c2vPM27KFV/q+Crrf1tH
    /fnYt+KoafkL+S9PaSs96I4qAmH7fHK/p2qcY6IFrOdR14uAs87ssSvGTw+rx/ib0ci+kXMpRGd2D2Sx
    cHWl4rCb42a3MHfFyUzlPUTwhm5rA+DWF1Z6JPUtpwUqX90KiWpYMzOer1mRRv5K1yOUPHB36F/H6PjY
    Hw4NkqwQb0WHrJn2ws85PB3owhbaZ4iECNkp2D0aylzFBMLVOK4USwzpKFWQZpFXd2lOm8eicRyLAuKL
    y3Gou2FvyGELfezceNR8I31QOXroJiuOOH9OMhSpxVgmPGlQ4XMXw5by49xfWOSrSIlVVOoBlUxAnp9u
    xwSTPras50W+LMZAE6iSe26qbDbAPcyfeyQpIQ+91BTfkKdYbcaJBWH35RQ8qVLKKuoMaAvQlnIBms4l
    XNeiFJesperkO000isv5NQ48FkQZ1Ua/w7AqRI6M1EEGuc4sSw7GdFmibbpNMGUnyjCxtkGQzjnaouUr
    2o+ajPq3JSM2pt03zroAyzDs1axEu05eHWd5WDo5ZC0rvEd8RR496IsuxuzWCyeNszWWM9lQOGMAmtI4
    Dm1I/egQrD6knzxq3sY2oXHNbJk1i5At0YpbLrOntb1AgHKcuyxZ/pXBvIAMpDac/LVXtNhXvA6Hel2Z
    PvwOBj2GaXgpt7Evaj/Vm6WeePzRrQ+nQfzYDPUHkr5/B0rGvgQKrgi/Hz+ehT4zLPgu9GCHvmNIYStZ
    fC7L7luR1NVhtBwKmSuQNip9DjfAe9/0a0k2fkx0Vko4HKijDkh62YmXF5YTBgG3jSgmRv/qvbeIZwP/
    NsG+HIdYWGoqmxX0C5PamF936VxCd0bYz8rtjnf1v35pj8soTpHasDdfTFsvGuuRdMtFLycccHIVgK3I
    gX9UnpZIjQnaeD2HpK2vubAyVc8CrIXAzdemYjOXHTo3EeI3/7RCR3yDA7qDsZIkNWj7vKl84XsQeH/A
    X1TLNQ=
    
    ...
    
    Sent READY signal
    num: 349544
    Receiving... ( 0 of 342 )
    #### HEAD ####
    b'eJy0vYGZpLgSrIsJMkEmyARMwASZIBNkAiZgQpnQJowJY8Ix4ZUyIjITqnrPnnvv62V7KBBCUP3xKyJTYtvKdv8p6Td+2u1jeR5gP/W5oaSVtVRuKh8FvhyTV7095VkDz1u+VZVrbR8nq79cxfbtFI/Pv5/stmcvpbDJVc0sreC8a1fZarPf7722mddXuBeNLPZTsRfFCiusqrzVdw3vO1wqjl2rONf6VO0O1Lq1dSCqKmulbLbwp64jqhVchzaUuS3r8Lax2rLpRJWfV2MKm6fL8SuIC6z2x5CLqVX5o58xrhTNbjjpvu4edjWW8Yt6X8Yqs5ZNK9iCu7eXWm1LteW9/X0D/ZCKG871OByLGmC3ay3vjU3F3rsaitmdbFar3dL1VduS7nBlDWt7LXu1b8m3V9SwVvZW2/7+3Nr+/r+uXY01vy9lLVZmLdu7YFsre92Hrb+XrRylHK0eRz1aO+p7qX2vx96wvNd7q/1o63fVeqmjvbfYxrbKj2NtGdV+71qOtKy9+9jXmUdpo+/jsOW9sar8e1dL6+O92Mpuh7dbnR1lViVt/Y6Tro39vYy9t/1drOvjKvn+2HdbWh+rGdj7bsYqbCddB2L7fvTdVt4fsfKuoR8dy7vCVc8x5rGaus57jHasSxv9XWx9fP9+r8+DW+b7nH28D+32+73MPrE+bOO0LcOW98f35mOtzPf2MdZGlZ/Vtmt5l8PhOHDiqLXBtpza+F7KmPvgRhRGtUOHHKp2tyYNtootPHBdOOMx38t5jHqM4te789rfy/sGHrxXuF3vjb2tjbh16+69b/tm6/sqj9u4bjWL2eGo7X2WceC8645V+43t3bbbxzn89rK221XUdRPsRg0rOXiXum3B3XivzHHyhhxz1dPfV3mui8WucU5bxvsujmvYlvf6NVeBc66P/b1MFFjHvrfs65avwnNOHD77+yzn+irnuXcWu/p52oroVjLmHjR5bKm3YjcA/bKdp/hCKVX4laoJrL9C7yuUP8vc11lz/Ydjfr/M'
    
    ... 
    
    Receiving... ( 63 of 342 )
    b'JGPgXARwxzUdiKKMzTRc4OaHzidOcNJrBQHbD+M6nZ6PKBrUlsRiq9KhIQY/JTOVqSd5ufKNbatfImARAtARU6pbAa2mh0YHVQrR04zzmEVA5Pnrc4Gt4kUiaWzVqu/Nv7tWw63102hqqZHgKyrXxsBq8emZeBQCriWU18xHfJZ4Fwq6+8cs0rMdIeCKitrmHTO6gFcZ1W3Q1zTDLQ6rbpMNOhSTBjIQrOwv+7xLiykV3pxd4SpDFC+JxcWaX5mUXWVBI7PLjG5EkKM0GAHgkfm8ynnGLITQs97JCiW/KwLEc+ZVW0IOrwJxiw3ZDnr4z7kRtOnjoX9ZiDSCvgwHP6mCn09UB+9AsCVnhSlt/TpQo0T+ShQnmXDwNpXLPSAQFCxT+6CDTYROLxKRWI6eCQlz57ipCo7OrIuZYFLQdzaATzI62KStlL8tv/CWbwmLUdsnul0T5hyyB/h7nFeiodJy7E5rStiJfCJXxwLl7zv2y/cDI0Apa37CfmjK4SO9ns7qcPgeoYt9zZcGLbeMULcaNMAYL3653y4Wy3ZO2dHKiPv6v8vg/Z+j7yDSy8IWHuC4bYB35eHfEei08vZDUpexFVfB8HEsyDJSIN4/7/uINS/0ptkjI+vi8DJiyijSO/xHfvInih/DS9aEvBv99pLhk7+RV/5GFD0pgcQPBYm0nwmLgE0PG9b/h8LQ+FvlPwf7Sp346Adq5nN6/nNXrhSN2RmpNfDXeUvX3mqRz/3DA6TnvZ16VGOCEgrag9DZHG7hZAZwE3brJ+Wl+BLRRMzvGpNq2mHqGU0cmeSdfJyAvciWWd1XQ2J2/JlGMu4AN7VfjqRiE9ctjQ2kp1sl2npXPKIqbhsDJ30cM4E7yOjIjjNs8yOOIZfb859t/y5sk2GueLHypprjHk2nlfzcKbQrQ95qdVVVOIyuGqz89XqiCqAui8K+CBP3pgjyhGwo9MXSqyCZrf8zrWtMaTQhGPJ5EWcfaf5BK/hlEZJiwTEX0oNuNFUw/Ge50BvJ'
    Receiving... ( 64 of 342 )
    b''
    Receiving... ( 65 of 342 )
    b''
    
    ...
    
    Receiving... ( 340 of 342 )
    b''
    Receiving... ( 341 of 342 )
    b''
    #### TAIL ####
    b''
    ###########################################
    ##### Received! message (len= 65532 ) #####
    ###########################################
    Message length     : 65532
    Decoded length     : 49149
    
    Exception in thread Thread-4:
    Traceback (most recent call last):
      File "C:\Python35\lib\threading.py", line 914, in _bootstrap_inner
        self.run()
      File "C:\Python35\lib\threading.py", line 862, in run
        self._target(*self._args, **self._kwargs)
      File "C:\Python35\controller.py", line 204, in decodeImg
        raw = decompress(raw)
    zlib.error: Error -5 while decompressing data: incomplete or truncated stream
    

    您正在从局部变量发送,但在编写完成之前,它已超出范围

    消息
    设为成员变量

    注意
    img\u锁
    不是线程安全的

    这是一个有效的演示:

    #ifndef _IMG_SESSION_H_
    #define _IMG_SESSION_H_
    
    #include <boost/bind.hpp>
    #include <boost/asio.hpp>
    #include <iostream>
    #include <boost/thread.hpp>
    
    struct session {
        session(boost::asio::io_service& svc) : svc(svc) {
        }
    
        void clean() {}
        boost::asio::io_service& svc;
        boost::asio::ip::tcp::socket _socket{svc};
        int max_length = 1024;
        //std::array<char, 1024> _data;
        char _data[1024];
    };
    
    class img_session : public session
    {
    public:
        img_session(boost::asio::io_service& io_service, std::string * img_stream, int*  img_lock);
        ~img_session();
    
        /* Starts the session. This is called in the constructor.*/
        void start();
    
    private:
        void handle_read(const boost::system::error_code& error, size_t bytes_transferred);
        void handle_write(const boost::system::error_code& error, size_t bytes_transferred);
    
        std::string * img_stream;
        int * img_lock;
        std::string message;
    };
    
    #endif /* _IMG_SESSION_H */
    
    /* Public Methods */
    img_session:: img_session(boost::asio::io_service& io_service, std::string * img_stream, int * img_lock) : session(io_service), img_stream(img_stream), img_lock(img_lock){
    }
    
    img_session::~img_session() { }
    
    void img_session::start()
    {
        std::cout << "connection from " << _socket.remote_endpoint() << "\n";
        std::cout << "img_session waiting for READY signal..." << std::endl;
        _socket.async_read_some(boost::asio::buffer(_data, max_length),
            boost::bind(&img_session::handle_read, this,
                boost::asio::placeholders::error,
                boost::asio::placeholders::bytes_transferred));
    }
    
    /* Private Methods */
    
    void img_session::handle_read(const boost::system::error_code& error, size_t /*bytes_transferred*/)
    {
        if (!error)
        {
            //char otherString[6];
            std::cout << "[INFO ] IMG READ" << std::endl;
            if (strncmp(_data, "READY", 5) == 0) {
                std::cout << "[INFO ] READY signal received..." << std::endl;
                while (*img_lock == 1) boost::this_thread::yield();
                *img_lock = 1;
                message = "0000" + *img_stream;
                size_t len = message.length();
    
                std::cout << "len = " << len << std::endl;
    
                message[0] = (len >> 24) & 0xFF;
                message[1] = (len >> 16) & 0xFF;
                message[2] = (len >> 8) & 0xFF;
                message[3] = len & 0xFF;
                std::cout << "img_session.cpp: bytes[] = " << (int) message[0] << " " << (int)message[1] << " " << (int)message[2] << " " << (int)message[3] << std::endl;
                std::cout << "img_session.cpp: message.length() = " << message.length() << std::endl;
                std::cout << "img_session.cpp: HEAD: " << message.substr(4, 1024) << std::endl;
                std::cout << "img_session.cpp: TAIL: " << message.substr(message.length() - 1024, message.length() - 1);
    
    
                boost::asio::async_write(_socket,
                    boost::asio::buffer(message), 
                    boost::bind(&img_session::handle_write, this,
                        boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
    
                *img_lock = 0;
            }
            else {
                std::cout << "[INFO ] READY signal not received..." << std::endl;
                /*
                 *boost::asio::async_write(_socket,
                 *    boost::asio::buffer("", 1),
                 *    boost::bind(&img_session::handle_write, this,
                 *        boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
                 */
            }
            clean();
        }
        else
        {
            delete this;
        }
    }
    
    void img_session::handle_write(const boost::system::error_code& error, size_t bytes_transferred)
    {
        if (!error)
        {
            std::cout << "img_session waiting for READY signal..." << std::endl;
            _socket.async_read_some(boost::asio::buffer(_data, max_length),
                boost::bind(&img_session::handle_read, this,
                    boost::asio::placeholders::error,
                    boost::asio::placeholders::bytes_transferred));
        }
        else
        {
            std::cout << __FUNCTION__ << ":" << error.message() << "\n";
            delete this;
        }
    }
    
    int main() {
        boost::asio::io_service svc;
        std::string img_stream(300<<10, '*');
        int img_lock = 0;
        auto s = new img_session(svc, &img_stream, &img_lock);
    
        using boost::asio::ip::tcp;
    
        tcp::acceptor a(svc);
        a.open(tcp::v4());
        a.set_option(tcp::acceptor::reuse_address(true));
        a.bind({{}, 6767});
        a.listen(1);
        a.accept(s->_socket);
    
        s->start();
    
        svc.run();
    }
    
    印刷品

      0       1  307204
    

    您正在从局部变量发送,但在编写完成之前,它已超出范围

    消息
    设为成员变量

    注意
    img\u锁
    不是线程安全的

    这是一个有效的演示:

    #ifndef _IMG_SESSION_H_
    #define _IMG_SESSION_H_
    
    #include <boost/bind.hpp>
    #include <boost/asio.hpp>
    #include <iostream>
    #include <boost/thread.hpp>
    
    struct session {
        session(boost::asio::io_service& svc) : svc(svc) {
        }
    
        void clean() {}
        boost::asio::io_service& svc;
        boost::asio::ip::tcp::socket _socket{svc};
        int max_length = 1024;
        //std::array<char, 1024> _data;
        char _data[1024];
    };
    
    class img_session : public session
    {
    public:
        img_session(boost::asio::io_service& io_service, std::string * img_stream, int*  img_lock);
        ~img_session();
    
        /* Starts the session. This is called in the constructor.*/
        void start();
    
    private:
        void handle_read(const boost::system::error_code& error, size_t bytes_transferred);
        void handle_write(const boost::system::error_code& error, size_t bytes_transferred);
    
        std::string * img_stream;
        int * img_lock;
        std::string message;
    };
    
    #endif /* _IMG_SESSION_H */
    
    /* Public Methods */
    img_session:: img_session(boost::asio::io_service& io_service, std::string * img_stream, int * img_lock) : session(io_service), img_stream(img_stream), img_lock(img_lock){
    }
    
    img_session::~img_session() { }
    
    void img_session::start()
    {
        std::cout << "connection from " << _socket.remote_endpoint() << "\n";
        std::cout << "img_session waiting for READY signal..." << std::endl;
        _socket.async_read_some(boost::asio::buffer(_data, max_length),
            boost::bind(&img_session::handle_read, this,
                boost::asio::placeholders::error,
                boost::asio::placeholders::bytes_transferred));
    }
    
    /* Private Methods */
    
    void img_session::handle_read(const boost::system::error_code& error, size_t /*bytes_transferred*/)
    {
        if (!error)
        {
            //char otherString[6];
            std::cout << "[INFO ] IMG READ" << std::endl;
            if (strncmp(_data, "READY", 5) == 0) {
                std::cout << "[INFO ] READY signal received..." << std::endl;
                while (*img_lock == 1) boost::this_thread::yield();
                *img_lock = 1;
                message = "0000" + *img_stream;
                size_t len = message.length();
    
                std::cout << "len = " << len << std::endl;
    
                message[0] = (len >> 24) & 0xFF;
                message[1] = (len >> 16) & 0xFF;
                message[2] = (len >> 8) & 0xFF;
                message[3] = len & 0xFF;
                std::cout << "img_session.cpp: bytes[] = " << (int) message[0] << " " << (int)message[1] << " " << (int)message[2] << " " << (int)message[3] << std::endl;
                std::cout << "img_session.cpp: message.length() = " << message.length() << std::endl;
                std::cout << "img_session.cpp: HEAD: " << message.substr(4, 1024) << std::endl;
                std::cout << "img_session.cpp: TAIL: " << message.substr(message.length() - 1024, message.length() - 1);
    
    
                boost::asio::async_write(_socket,
                    boost::asio::buffer(message), 
                    boost::bind(&img_session::handle_write, this,
                        boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
    
                *img_lock = 0;
            }
            else {
                std::cout << "[INFO ] READY signal not received..." << std::endl;
                /*
                 *boost::asio::async_write(_socket,
                 *    boost::asio::buffer("", 1),
                 *    boost::bind(&img_session::handle_write, this,
                 *        boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
                 */
            }
            clean();
        }
        else
        {
            delete this;
        }
    }
    
    void img_session::handle_write(const boost::system::error_code& error, size_t bytes_transferred)
    {
        if (!error)
        {
            std::cout << "img_session waiting for READY signal..." << std::endl;
            _socket.async_read_some(boost::asio::buffer(_data, max_length),
                boost::bind(&img_session::handle_read, this,
                    boost::asio::placeholders::error,
                    boost::asio::placeholders::bytes_transferred));
        }
        else
        {
            std::cout << __FUNCTION__ << ":" << error.message() << "\n";
            delete this;
        }
    }
    
    int main() {
        boost::asio::io_service svc;
        std::string img_stream(300<<10, '*');
        int img_lock = 0;
        auto s = new img_session(svc, &img_stream, &img_lock);
    
        using boost::asio::ip::tcp;
    
        tcp::acceptor a(svc);
        a.open(tcp::v4());
        a.set_option(tcp::acceptor::reuse_address(true));
        a.bind({{}, 6767});
        a.listen(1);
        a.accept(s->_socket);
    
        s->start();
    
        svc.run();
    }
    
    印刷品

      0       1  307204
    

    如果您使用的是TCP,您不能对调用
    recv
    返回的数据量做任何假设,除非它不会超过参数所说的值。因此,我不能重复调用
    recv
    来接收真正大的数据?您可以,但您需要跟踪收到的信息量,而不是调用它的次数。您应该继续调用
    recv
    ,直到读取所需的字节数或流关闭为止(返回值为0)。如果要读取的剩余字节数小于1024,则还应将参数调整为
    recv
    ,以反映这一点。(注意:1024不是最佳的
    recv
    缓冲区大小)。如果您使用TCP,您不能对调用
    recv
    返回的数据量进行任何假设,除非它不会超过参数所说的值。因此,我不能重复调用
    recv
    来接收真正大的数据。您可以,但您需要跟踪收到的信息量,而不是调用它的次数。您应该继续调用
    recv
    ,直到读取所需的字节数或流关闭为止(返回值为0)。如果要读取的剩余字节数小于1024,则还应将参数调整为
    recv
    ,以反映这一点。(注意:1024不是最佳的
    recv
    缓冲区大小)。
    netcat localhost 6767 | wc 
    READY
    
      0       1  307204