Почему этот код Boost ASIO не работает с этим клиентом python?

Этот код идентичен исходному асинхронному эхо-серверу udp, но с другим сокетом.

Ответ передается и отображается в wirehark, но затем ошибка ICMP Port Unreachable отправляется обратно на сервер. Я пытаюсь понять, почему, потому что все выглядит правильно.

Вы можете скопировать этот код непосредственно в исходный файл, например server.cpp. и затем скомпилировать

gcc server.cpp -lboost_system

Запустите его командой: ./a.out 35200

 #include <cstdlib> #include <iostream> #include <boost/bind.hpp> #include <boost/asio.hpp> using boost::asio::ip::udp; class server { public: server(boost::asio::io_service& io_service, short port) : io_service_(io_service), socket_(io_service, udp::endpoint(udp::v4(), port)), socket2_(io_service, udp::endpoint(udp::v4(),0)) { socket_.async_receive_from( boost::asio::buffer(data_, max_length), sender_endpoint_, boost::bind(&server::handle_receive_from, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } void handle_receive_from(const boost::system::error_code& error, size_t bytes_recvd) { if (!error && bytes_recvd > 0) { // use a different socket... random source port. socket2_.async_send_to( boost::asio::buffer(data_, bytes_recvd), sender_endpoint_, boost::bind(&server::handle_send_to, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } else { socket_.async_receive_from( boost::asio::buffer(data_, max_length), sender_endpoint_, boost::bind(&server::handle_receive_from, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } } void handle_send_to(const boost::system::error_code& /*error*/, size_t /*bytes_sent*/) { // error_code shows success when checked here. But wireshark shows // an ICMP response with destination unreachable, port unreachable when run on // localhost. Haven't tried it across a network. socket_.async_receive_from( boost::asio::buffer(data_, max_length), sender_endpoint_, boost::bind(&server::handle_receive_from, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } private: boost::asio::io_service& io_service_; udp::socket socket_; udp::socket socket2_; udp::endpoint sender_endpoint_; enum { max_length = 1024 }; char data_[max_length]; }; int main(int argc, char* argv[]) { try { if (argc != 2) { std::cerr << "Usage: async_udp_echo_server <port>\n"; return 1; } boost::asio::io_service io_service; using namespace std; // For atoi. server s(io_service, atoi(argv[1])); io_service.run(); } catch (std::exception& e) { std::cerr << "Exception: " << e.what() << "\n"; } return 0; } 

Причина, по которой я нуждаюсь в этом, заключается в том, что у меня есть несколько потоков, получающих данные из входной очереди, которая подается с UDP-сервером. Теперь я хочу, чтобы эти потоки могли отправлять ответы напрямую, но я не могу заставить их работать.

Если я использую оригинальный сокет (т. Е. Socket_) в вызове async_send_to, он работает.

Хорошо … вот тестовый клиент, который не работает с приведенным выше кодом (но работает с исходной версией из примеров asio).

 #!/usr/bin/python import socket, sys, time, struct textport = "35200" host = "localhost" if len(sys.argv) > 1: host = sys.argv[1] print "Sending Data" s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) port = int(textport) s.connect((host, port)) s.sendall("Hello World") #s.shutdown(1) print "Looking for replies; press Ctrl-C or Ctrl-Break to stop." while 1: buf = s.recv(1200) if not len(buf): break print "Received: %s" % buf 

Меня это озадачило. Но, по крайней мере, я могу использовать клиент UDP C ++, и он работает.

4 Solutions collect form web for “Почему этот код Boost ASIO не работает с этим клиентом python?”

Вы не должны откладывать асинхронную отправку и затем закрывать сокет. Деструктор для сокета запускается в конце блока, закрывая сокет, что предотвращает появление сообщения.

Хорошо, совершенно другая возможность.

Вы используете netfilter? У вас есть правило conntrack?

Ответ от того же порта будет соответствовать CONNECTED в модуле conntrack, в то время как ответ от нового порта будет новым соединением. Если входящие UDP-пакеты, которые не соответствуют CONNECTED, имеют действие REJECT, это объясняет поведение, а также почему тот же самый код может работать для Сэма.

Вот так. Я снова отвечаю на свой вопрос. Проблема связана с моим кодом python, который был образцом, который я схватил у кого-то другого.

Эта версия работает целая куча и правильно читает результат. И, используется правильный API sendto recvfrom, который вы обычно используете с udp-пакетами.

 #!/usr/bin/python import socket, sys, time, struct textport = "35200" host = "localhost" if len(sys.argv) > 1: host = sys.argv[1] print "Sending Data" port = int(textport) addr = (host, port) buf = 1024 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.sendto("hello World", addr) print "Looking for replies; press Ctrl-C or Ctrl-Break to stop." while 1: data,addr = s.recvfrom(buf) if not data: print "Client has exited!" break else: print "\nReceived: '", data,"'" # Close socket s.close() 

Другое дело, что, как Бен указал в своем ответе, что в какой-то момент я создал сокет, который позже был удален, поскольку функция вышла из сферы действия, и у нее все еще были ожидающие ввода-вывода. Я решил, что в моем случае мало пользы для использования асинхронного ввода-вывода, поскольку он излишне усложняет код и не будет сильно влиять на производительность.

редактировать

Ваш код клиента python выглядит подозрительно, я не думаю, что вы должны делать connect или send с помощью UDP-сокета. Попробуй это:

 #!/usr/bin/python import socket, sys, time, struct port = 10000 host = "localhost" addr = (host,port) if len(sys.argv) > 1: host = sys.argv[1] print "Sending Data" s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.sendto("Hello World",addr) print "Looking for replies; press Ctrl-C or Ctrl-Break to stop." while 1: data,addr = s.recvfrom(1200) if not data: break print "Received: %s" % data 

он работает для меня, используя ваш server.cpp

 macmini:stackoverflow samm$ ./client.py Sending Data Looking for replies; press Ctrl-C or Ctrl-Break to stop. Received: Hello World 

оригинальный ответ ниже.

host unreachable – это то, что я ожидал бы, если клиент, отправивший сообщение, не sender_endpoint_ порт sender_endpoint_ . Когда я скомпилировал ваш server.cc и использовал пример эхо-клиента udp- блока Boost.Asio, он отлично работает

 macmini:stackoverflow samm$ g++ server.cpp -lboost_system -o server macmini:stackoverflow samm$ g++ client.cpp -lboost_system -o client macmini:stackoverflow samm$ ./server 10000 

в другой оболочке

 macmini:stackoverflow samm$ ./client 127.0.0.1 10000 Enter message: hello Reply is: hello macmini:stackoverflow samm$ ./client 127.0.0.1 10000 Enter message: goodbye Reply is: goodbye macmini:stackoverflow samm$ 
  • Вызов функций C в Python
  • Как устранить ошибку сегментации при работе с Python Ctypes и C ++?
  • Эквивалент генератора питона в C ++ для буферизованных чтений
  • Как загрузить C DLL из SXS в Python?
  • Как сделать SWIG в VS2010?
  • Swig downcasting from Base * to Derived *
  • Обработка изображений OpenCV - C ++ vs C vs Python
  • эффективный поиск подстроки python
  • Python быстрее, чем C ++? Как это произошло?
  • Как я могу прочитать базу данных / файл пиренейского пика из C?
  • Фрагмент Python для удаления комментариев на C и C ++
  • Python - лучший язык программирования в мире.