2012-08-17 15 views
1

當boost :: asio實現一個簡單的udp客戶端服務器時,我遇到了一個問題: :ip :: udp.if我使用ipv6鏈接範圍單播地址綁定服務器,它可以在某些PC上運行,但不能在某些其他PC上運行。在ipv6鏈接範圍中應用boost :: asio :: ip :: udp unicast udp客戶端服務器deamon,有時可以使用,但有時不會

//main.cpp 
#include <iostream> 
#include <string> 
#include <vector> 
#include <cstring> 

#include <boost/asio.hpp> 
#include <boost/format.hpp> 

void test_udp_server(std::string const& host_, std::string const& port_) 
{ 
    boost::asio::io_service io_service; 
    boost::asio::ip::udp::socket socket(io_service); 
    boost::asio::ip::udp::resolver resolver(io_service); 
    boost::asio::ip::udp::endpoint endpoint= *resolver.resolve(boost::asio::ip::udp::resolver::query(host_, port_)); 
    socket.open(endpoint.protocol()); 

    std::cout << "address:" << endpoint.address().to_string() << " port:" << port_ << std::endl; 

    boost::system::error_code e; 
    socket.bind(endpoint, e); 
    if (e) 
    { 
     std::cerr << "bind error:" << e.message() << std::endl; 
     return; 
    } 

    //recieve from 
    boost::asio::ip::udp::endpoint remote_endpoint; 
    char buffer[4096]; 
    unsigned int size; 

    while (1) 
    { 
     memset(buffer, 0, 4096); 
     size = 0; 
     size = socket.receive_from(boost::asio::buffer(buffer, 4096), remote_endpoint); 

     std::cout << "receive: " << std::string(buffer) << std::endl; 
    } 
} 

void test_udp_client(std::string const& host_, std::string const& port_) 
{ 
    boost::asio::io_service io_service; 
    boost::asio::ip::udp::socket socket(io_service); 
    boost::asio::ip::udp::resolver resolver(io_service); 
    boost::asio::ip::udp::endpoint dest_endpoint= *resolver.resolve(boost::asio::ip::udp::resolver::query(host_, port_)); 
    socket.open(dest_endpoint.protocol()); 

    int i = 0; 
    boost::system::error_code e; 

    while (i < 10) 
    { 
     std::string msg = boost::str(boost::format("udp message %d") % i); 

     socket.send_to(boost::asio::buffer(msg.c_str(), msg.size()), dest_endpoint, boost::asio::detail::message_do_not_route, e); 
     if (!e) 
     { 
      std::cout << "send: " << msg << std::endl; 
     } 
     else 
     { 
      std::cerr << "send error: " << e.message() << std::endl; 
     } 

     i ++; 
    } 
} 

int main(int ac, char* av[]) 
{ 
    if (ac != 4) 
    { 
     std::cout << "ac != 4" << std::endl; 
     return -1; 
    } 

    if (std::string(av[1]) == "c") 
    { 
     test_udp_client(std::string(av[2]), std::string(av[3])); 
    } 
    else if (std::string(av[1]) == "s") 
    { 
     test_udp_server(std::string(av[2]), std::string(av[3])); 
    } 
    else 
    { 
     std::cout << "av[1] != \"c\" and av[1] != \"s\"" << std::endl; 
     return -1; 
    } 
} 

complite它,並運行,因爲這:

./main s fe80::211:85ff:fe6c:44ac%eth0 100 #server, "s" means server, 
              #"fe80::211:85ff:fe6c:44ac%eth0" means your ipv6 address 
              #and 100 is port 
./main c fe80::211:85ff:fe6c:44ac 100  #run it in another ssh or shell 

但結果是:

- 1 UDP服務器從不接收客戶端

[[email protected] Tmp2]# ls<br> 
main main.cpp main.o Makefile<br> 
[[email protected] Tmp2]# ./main s fe80::211:85ff:fe6c:44ac%eth0 100<br> 
address:fe80::211:85ff:fe6c:44ac%eth0 port:100<br> 
sended味精

2 udp客戶端,已發送msg successf ULY

[[email protected] Tmp2]# ./main c fe80::211:85ff:fe6c:44ac 100<br> 
send: udp message 0<br> 
send: udp message 1<br> 
send: udp message 2<br> 
send: udp message 3<br> 
send: udp message 4<br> 
send: udp message 5<br> 
send: udp message 6<br> 
send: udp message 7<br> 
send: udp message 8<br> 
send: udp message 9<br> 

3當我打開tcpdum,它真正抓住客戶機

[[email protected] Tmp2]# tcpdump -i lo udp and host fe80::211:85ff:fe6c:44ac<br> 
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode<br> 
listening on lo, link-type EN10MB (Ethernet), capture size 96 bytes<br> 
10:55:41.215110 IP6 fe80::211:85ff:fe6c:44ac.59007 > fe80::211:85ff:fe6c:44ac.100: UDP, length 13<br> 
10:55:41.215295 IP6 fe80::211:85ff:fe6c:44ac.59007 > fe80::211:85ff:fe6c:44ac.100: UDP, length 13<br> 
10:55:41.215360 IP6 fe80::211:85ff:fe6c:44ac.59007 > fe80::211:85ff:fe6c:44ac.100: UDP, length 13<br> 
10:55:41.215431 IP6 fe80::211:85ff:fe6c:44ac.59007 > fe80::211:85ff:fe6c:44ac.100: UDP, length 13<br> 
10:55:41.215516 IP6 fe80::211:85ff:fe6c:44ac.59007 > fe80::211:85ff:fe6c:44ac.100: UDP, length 13<br> 
10:55:41.215585 IP6 fe80::211:85ff:fe6c:44ac.59007 > fe80::211:85ff:fe6c:44ac.100: UDP, length 13<br> 
10:55:41.215790 IP6 fe80::211:85ff:fe6c:44ac.59007 > fe80::211:85ff:fe6c:44ac.100: UDP, length 13<br> 
10:55:41.215926 IP6 fe80::211:85ff:fe6c:44ac.59007 > fe80::211:85ff:fe6c:44ac.100: UDP, length 13<br> 
10:55:41.216069 IP6 fe80::211:85ff:fe6c:44ac.59007 > fe80::211:85ff:fe6c:44ac.100: UDP, length 13<br> 
10:55:41.216130 IP6 fe80::211:85ff:fe6c:44ac.59007 > fe80::211:85ff:fe6c:44ac.100: UDP, length 13<br> 

4 sended味精,這是我的ifconfig:

[[email protected] Tmp2]# ifconfig<br> 
eth0  Link encap:Ethernet HWaddr 00:11:85:6C:44:AC 
      inet addr:192.168.23.38 Bcast:192.168.23.255 Mask:255.255.255.0<br> 
      inet6 addr: fe80::211:85ff:fe6c:44ac/64 Scope:Link<br> 
      UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1<br> 
      RX packets:1174940938 errors:0 dropped:0 overruns:0 frame:0<br> 
      TX packets:626463551 errors:0 dropped:0 overruns:0 carrier:0<br> 
      collisions:0 txqueuelen:100<br> 
      RX bytes:378565405153 (352.5 GiB) TX bytes:126427805747 (117.7 GiB)<br> 
      Base address:0x3400 Memory:fd000000-fd020000<br> 

lo  Link encap:Local Loopback 
      inet addr:127.0.0.1 Mask:255.0.0.0<br> 
      inet6 addr: ::1/128 Scope:Host<br> 
      inet6 addr: ::127.0.0.1/0 Scope:Compat<br> 
      UP LOOPBACK RUNNING MTU:16436 Metric:1<br> 
      RX packets:188781410 errors:0 dropped:0 overruns:0 frame:0<br> 
      TX packets:188781410 errors:0 dropped:0 overruns:0 carrier:0<br> 
      collisions:0 txqueuelen:0<br> 
      RX bytes:582726106596 (542.7 GiB) TX bytes:582726106596 (542.7 GiB)<br> 

由在運行服務器和客戶端之前,我已經停止了iptables。並且更奇怪,在我的另一臺pc中它運行正常。

爲什麼?

+0

如果試圖只綁定到該端口,而不是主機,它更好的工作呢?即跳過所有解析和綁定,只需創建如下這樣的套接字:'boost :: asio :: ip :: udp :: socket套接字(io_service,boost :: asio :: ip :: udp :: endpoint(udp :: v6 ),atoi(port_.c_str())));' – 2012-08-17 05:13:08

+0

感謝Mr.Pileborg.As你的建議,它現在運行如此健康!但有一點遺憾,它不適合我的需要。事實上,我想分配爲主機的每個接口指定num個線程來接收和處理消息,然後我必須將接口綁定到套接字。 – LinYihang 2012-08-17 07:23:41

回答

0

除了在我的評論中提供的解決方案,也許你應該嘗試一種類似的解決方案,允許你綁定到一個特定的接口。

我認爲,問題在於您對主機和端口執行DNS查詢,而您應該直接綁定到主機地址和端口。

事情是這樣的:

// First convert the address string to its binary form 
boost::asio::ip::address_v6 address = 
    boost::asio::ip::address_v6::from_string(host_); 

// Create the endpoint 
boost::asio::ip::udp::endpoint endpoint(address, atoi(port_.c_str())); 

// And finally create a bound socket 
boost::asio::ip::udp::socket socket(io_service, endpoint); 
+0

TO全局作用域或環回作用域的單播ipv6地址,它可以正常工作,但鏈接作用域是特殊的!當使用鏈接作用域ipv6地址時,還需要將其接口指向爲「fe80 :: 211:85ff:fe6c:44ac %eth0「,或boost :: asio :: ip :: udp :: socket :: bind – LinYihang 2012-08-17 08:26:10

+0

對不起,我新來問Stack Overflow的問題。
TO全局作用域或環回作用域單播ipv6地址,它會工作的很好。但鏈接作用域是特殊的!當使用鏈接作用域ipv6地址時,還需要指出其接口爲「fe80 :: 211:85ff:fe6c: 44ac%eth0「,或boost :: asio :: ip :: udp :: socket :: bind將會抱怨」Invalid Argument「!但是如果你輸入ipv6與接口,那麼它將不會通過boost :: asio :: ip: :address_v6 :: from_string()func。所以我使用解析器來解決它,並且它在我的家用PC中運行良好。但奇怪的是,在我公司的PC中它不起作用! – LinYihang 2012-08-17 08:35:33