简体   繁体   English

为什么这个 Boost TCP 套接字以一种方法工作而不是另一种方法?

[英]Why does this Boost TCP socket work in one method and not in another?

I want to establish a socket connection in one method and use this connection in another method of a class.我想在一个方法中建立一个套接字连接,并在一个类的另一个方法中使用这个连接。 While in the first method (where I establish the connection) I can read and write from and to the socket as much as I want, in the second method I always get a Bad file descriptor error.虽然在第一种方法(我建立连接的地方)中,我可以根据需要从套接字读取和向套接字写入,但在第二种方法中,我总是收到Bad file descriptor错误。 Note that I use version 1.65.1 of Boost.请注意,我使用的是1.65.1版的 Boost。

I created a small reproducible example (I added some logs for clarification):我创建了一个小的可重现示例(我添加了一些日志以进行澄清):

code.h代码.h

#include <boost/asio.hpp>

using boost::asio::ip::tcp;

class SocketManager {
    tcp::socket *sock;
    boost::asio::io_service *io_service;
    tcp::acceptor *acceptor;

    public:
        virtual void initialize();  // works
        virtual void evaluate();  // fails
};

code.cc代码.cc

#include "code.h"
#include <iostream>
#include <boost/asio.hpp>

using boost::asio::ip::tcp;
using namespace std;


int main() {
    SocketManager sm;
    sm.initialize();
    sm.evaluate();
    return 0;
}

void SocketManager::initialize() {
    boost::asio::io_service _io_service;
    io_service = &_io_service;

    tcp::acceptor a(*io_service, tcp::endpoint(tcp::v4(), 1337));
    acceptor = &a;

    tcp::socket sock_(*io_service);
    sock = &sock_;

    a.accept(*sock);

    char data[1024];
    boost::system::error_code error;
    size_t length = sock->read_some(boost::asio::buffer(data), error);
    if (error)
        throw boost::system::system_error(error);  // No Error here!

    boost::asio::write(*sock, boost::asio::buffer(data, length));

    cout << io_service->stopped() << endl;  // prints 0
    cout << acceptor->is_open() << endl;  // prints 1
    cout << sock->is_open() << endl;  // prints 1
}

void SocketManager::evaluate() {
    cout << io_service->stopped() << endl;  // prints 0
    cout << acceptor->is_open() << endl;  // prints 1
    cout << sock->is_open() << endl;  // prints 1

    char data[1024];
    boost::system::error_code error;
    size_t length = sock->read_some(boost::asio::buffer(data), error);
    if (error)
        throw boost::system::system_error(error);  // Error: "Bad file descriptor"
}

Output of the code above when used with a client:与客户端一起使用时上述代码的输出:

root@5531547d4baf:/cpp# ./a.out 
0
1
1
0
1
1
terminate called after throwing an instance of 'boost::system::system_error'
  what():  Bad file descriptor
Aborted

Note that the code that throws the error is the exact same code in both methods (in the first one it works without any error and in the second one it throws a Bad file descriptor error).请注意,抛出错误的代码在两种方法中是完全相同的代码(在第一个方法中它没有任何错误,而在第二个方法中它抛出一个Bad file descriptor错误)。

I suspect that the io_service is no longer valid when switching to the new function, so I have already experimented with the associated poll and run functions without success.我怀疑切换到新函数时io_service不再有效,所以我已经尝试了相关的pollrun函数,但没有成功。

I also tried to replace the boost::asio::buffer with a boost::asio::mutable_buffer and a boost::asio::mutable_buffer .我也试图取代boost::asio::bufferboost::asio::mutable_bufferboost::asio::mutable_buffer However, the exact same code works in the first method, so I suspect that the function calls are alright!但是,完全相同的代码在第一种方法中有效,所以我怀疑函数调用没问题!

As per the comment sock , io_service and acceptor members of SocketManager are initialized to point to local variables within SocketManager::initialize .根据注释sockSocketManager io_serviceacceptor成员被初始化为指向SocketManager::initialize局部变量。 When that completes you then have dangling pointers.完成后,您将获得悬空指针。

I don't see any reason to use pointers at all here.我在这里根本看不到任何使用指针的理由。 Just make them non-pointer data members and initialize them in a constructor (untested)...只需使它们成为非指针数据成员并在构造函数中初始化它们(未经测试)...

class SocketManager {
    boost::asio::io_service io_service;
    tcp::acceptor           acceptor;
    tcp::socket             sock;
public:
    SocketManager ()
      : acceptor(io_service, tcp::endpoint(tcp::v4(), 1337))
      , sock(io_service)
      {}
      ...
};

Note that the io_service member is declared first as it must be initialized before sock and acceptor .请注意, io_service成员首先声明,因为它必须sockacceptor之前初始化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么 boost::asio::ip::tcp::basic_stream_socket::available 运行时间长? - Why does boost::asio::ip::tcp::basic_stream_socket::available have a long runtime? 为什么boost :: asio :: ip :: tcp :: socket&socket()不能为const - why boost::asio::ip::tcp::socket& socket() cannot be const 为什么可以重新使用boost :: asio :: tcp :: socket? - Why can this boost::asio::tcp::socket be re-used? 为什么tcp :: socket :: is_open()方法在连接不存在的地址时返回true? - Why does tcp::socket::is_open() method return true when connecting a non-existent address? boost::asio 扩展 TCP 套接字 - boost::asio extension TCP socket 什么会提升::: asio :: ssl :: stream <boost::asio::ip::tcp::socket> :: shutdown()吗? - What does boost::asio::ssl::stream<boost::asio::ip::tcp::socket>::shutdown() do? C ++ Boost.ASIO:使用Windows API将可接受的TCP连接从一个打开的套接字传递到另一个(与Linux API一起使用)吗? - C++ Boost.ASIO: passing accepted TCP connection from one opened socket to another using Windows APIs ( while works with Linux APIs)? boost_tcp受体和boost_tcp套接字的keep_alive选项 - keep_alive options for boost tcp acceptor and boost tcp socket boost :: combine()是否与方法的输出一起工作? - Does boost::combine() work with output of a method? 为什么boost :: geometry :: intersection不正确? - Why boost::geometry::intersection does not work correct?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM