Ce code est identique au serveur original async echo d'udp, mais avec un socket différent.Pourquoi ce code Boost ASIO ne fonctionne-t-il pas avec ce client python?
La réponse est transmise et affichée dans wireshark, mais une erreur ICMP Port Unreachable est renvoyée au serveur. J'essaie de comprendre pourquoi parce que tout semble correct.
Vous pouvez copier ce code directement dans un fichier source, par ex. server.cpp. puis compiler avec
gcc server.cpp -lboost_system
Exécuter avec une commande comme: ./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;
}
La raison pour laquelle j'ai besoin c'est parce que j'ai plusieurs threads de réception de données à partir d'une file d'entrée alimentée par un serveur UDP. Maintenant, je veux que ces threads puissent envoyer des réponses directement, mais je ne peux pas le faire fonctionner.
Si j'utilise le socket d'origine (c'est-à-dire socket_) dans l'appel async_send_to alors cela fonctionne.
Ok ... voici le client de test qui ne fonctionne pas avec le code ci-dessus (mais qui fonctionne avec la version originale des exemples 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
Cela me déroute. Mais au moins, je peux utiliser le client C++ UDP et cela fonctionne.
Certains ports sont protégés par le système d'exploitation. D'autres ports sont déjà utilisés. Si vous avez tué le serveur de force, le système d'exploitation peut ne pas remarquer pendant soixante secondes que le port est pratiquement mort et que le port sera inutilisable jusqu'à ce qu'il soit nettoyé par le système d'exploitation. Quel numéro de port essayez-vous d'utiliser? –
35200 ce n'est pas la raison. Si je change de handle_receive_from de socket vers la variable membre socket_ alors cela fonctionne. – Matt
J'ai mis à jour ma réponse en fonction de votre code client python. –