为什么此Boost ASIO代码无法与此python客户端一起使用? [英] Why doesn't this Boost ASIO code work with this python client?

查看:72
本文介绍了为什么此Boost ASIO代码无法与此python客户端一起使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此代码与原始的udp异步回显服务器相同,但套接字不同.

This code is identical to the original udp async echo server, but with a different socket.

传输响应并将其显示在Wireshark中,但是随后将ICMP Port Unreachable错误发送回服务器.我试图了解原因,因为一切看起来都正确.

The response is transmitted and showing in wireshark, but then an ICMP Port Unreachable error is sent back to the server. I'm trying to understand why because everything looks correct.

您可以将此代码直接复制到源文件中,例如server.cpp.然后用

You can copy this code directly into a source file e.g. server.cpp. and then compile with

gcc server.cpp -lboost_system

gcc server.cpp -lboost_system

使用如下命令运行它:./a.out 35200

Run it with a command like: ./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服务器提供的输入队列接收数据.现在,我希望这些线程能够直接发送响应,但无法正常工作.

The reason I need this is because I have multiple threads receiving data from an input queue that is fed with a UDP server. Now I want those threads to be able to send responses directly but I can't get it working.

如果我在async_send_to调用中使用原始套接字(即socket_),那么它将起作用.

If I use the original socket (i.e. socket_) in the async_send_to call then it works.

好吧...这是测试客户端,它与上面的代码不兼容(但与asio示例中的原始版本兼容).

Ok... here is the test client that doesn't work with the code above (but works with the original version from the asio examples).

#!/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

这让我感到困惑.但是至少我可以使用C ++ UDP客户端,并且可以使用.

It's got me baffled. But at least I can use the C++ UDP client and it works.

推荐答案

在这里.我再回答我自己的问题.问题与我的python代码有关 这是我从其他人那里抢来的样本.

Here we go. I'm answering my own question again. The problem relates to my python code which was a sample I grabbed from someone else.

此版本可更好地处理整个堆并正确读取结果.并且,使用的是正确的API sendto recvfrom,这是您通常在udp数据包中通常使用的.

This version works a whole heap better and reads the result correctly. And, is using the correct API sendto recvfrom which is what you would normally use with udp packets.

#!/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()

另一件事是,正如Ben在他的回答中指出的那样,有一次我正在创建一个套接字,该套接字后来在函数超出范围时被删除,并且仍然具有待处理的I/O.我认为使用异步I/O对我来说没有什么好处,因为它不必要地使代码复杂化,并且不会对性能产生太大影响.

The other thing is, that the as Ben has pointed out in his answer that at one point I was creating a socket that was later being deleted as the function went out of scope and it still had pending I/O. I have decided that there is little benefit in my case to use asynchronous I/O as it unnecessarily complicates the code and won't affect performance much.

这篇关于为什么此Boost ASIO代码无法与此python客户端一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆