Boost Asio открыть более одной розетки - PullRequest
0 голосов
/ 06 июля 2018

Я новичок в boost :: asio. У меня есть клиент и сервер, которые используют boost::asio::ip::tcp::socket. Когда я использую один разъем, все работает нормально. Но теперь мне нужно создать еще один. Иногда это работает, но обычно я получаю исключение во время второго сокета connect.

Вот упрощенный код на стороне клиента:

boost::asio::io_service ios;
std::cout << "Connecting 1950\n";
mp_SocketReader = new SerializationSocket(host, "1950", ios);
std::cout << "Connecting 1960\n";
mp_SocketWriter = new SerializationSocket(host, "1960", ios);

на стороне сервера:

boost::asio::io_service ios;
SerializationSocket socketReader(1950, ios);
SerializationSocket socketWriter(1960, ios);

И часть SerializationSocket кода:

class SerializationSocket {
    boost::asio::ip::tcp::socket *mp_Socket;

public:
    /* As client */
    SerializationSocket(std::string host, std::string port, boost::asio::io_service& ios) {
        mp_Socket = new boost::asio::ip::tcp::socket(ios);
        boost::asio::ip::tcp::resolver resolver(ios);
        boost::asio::ip::tcp::resolver::query query(host, port);
        boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
        std::cout << "Before connect\n";
        connect(*mp_Socket, iterator);
        std::cout << "After connect\n";
    }

    /* As server */
    SerializationSocket(int port, boost::asio::io_service& ios) {
        mp_Socket = new boost::asio::ip::tcp::socket(ios);
        boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port);
        boost::asio::ip::tcp::acceptor acceptor(ios, endpoint);
        acceptor.accept(*mp_Socket);
    }
};

Вывод при возникновении проблемы (на стороне клиента):

Connecting 1950
Before connect
After connect
Connecting 1960
Before connect
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >'
  what():  connect: Connection refused
Aborted (core dumped)

В чем может быть причина такого поведения?

обновление: небольшие sleep() между сокетами помогают избежать проблем.

1 Ответ

0 голосов
/ 06 июля 2018

Вы используете блокирующие розетки. Это означает, что ваш сервер не начинает прослушивать порт 1960, пока клиент не подключится к порту 1950. Теперь у вас есть состояние гонки, иногда клиент работает быстрее сервера и пытается подключиться, когда сервер еще не прослушивает.

Возможные решения:

  1. используйте асинхронные (неблокирующие) сокеты, по крайней мере, на стороне сервера, так что вы может начать слушать / принимать на них обоих.
  2. блокирует сокеты, но принимает соединения на двух потоках
  3. создайте акцептор в конструкторе сокетов сервера, но переместите вызов на accept в другой метод, теперь создайте два сокета сервера и затем вызовите accept для обоих из них. Я не уверен в этом, не помню, как реализован Asio , но стоит попробовать, так как это было бы самым простым решением.
...