此代碼與原始的udp異步回顯服務器相同,但使用不同的套接字。爲什麼Boost ASIO代碼不能用於這個python客戶端?
響應被傳輸並顯示在wireshark中,但隨後ICMP端口不可達錯誤被髮送回服務器。我試圖理解爲什麼,因爲一切都看起來正確。
您可以將此代碼直接複製到源文件中,例如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服務器的輸入隊列。現在我希望那些線程能夠直接發送響應,但我無法實現它的工作。
如果我在async_send_to調用中使用原始套接字(即socket_),那麼它將起作用。
好的...這裏是測試客戶端不能使用上面的代碼(但與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
這讓我感到莫名其妙。但至少我可以使用C++ UDP客戶端,它的工作原理。
某些端口受OS保護。其他端口已被使用。如果您強行殺死了服務器,操作系統可能會在60秒內未注意到該端口已基本死亡,因此該端口在OS清理之前將無法使用。您嘗試使用哪個端口號。 – 2010-08-26 00:06:32
35200那不是原因。如果我將handle_receive_from從套接字更改爲成員變量socket_,那麼它將起作用。 – Matt 2010-08-26 00:11:00
我已經根據您的python客戶端代碼更新了我的答案。 – 2010-08-26 12:34:44