2014-03-27 109 views
0

對於某些通過UDP傳輸的數據,我使用的是async_receive_from函數。我的接收功能是async_receive_from沒有收到任何東西

 udp::socket socket_; 
     udp::endpoint remote_endpoint_; 
     boost::array<char, 200> recv_buffer_; 

     void start_receive() 
     { 
      std::fill(recv_buffer_.begin(), recv_buffer_.end(), '\0'); 
      socket_.async_receive_from(boost::asio::buffer(recv_buffer_), remote_endpoint_, boost::bind(&udp_server_ping::handle_receive, this, boost::asio::placeholders::error)); 
     } 

     void handle_receive(const boost::system::error_code& error) 
     { 
      if (!error || error == boost::asio::error::message_size) 
      { 
       for(int i = 0; i < 200; i++) 
        std::cout << recv_buffer_.c_array()[i]; 
       std::cout << '\n'; 
       for(auto it = boost::begin(recv_buffer_); it != boost::end(recv_buffer_); ++it) 
        std::cout << *it; 
       std::cout << '\n'; 
       switch(recv_buffer_.c_array()[0]) 
       { 
       case '#': 
        { 
         got_ping = true; 
         std::cout << "Gotcha!\n"; 
         break; 
        } 
       case '$': 
        { 
         std::vector<char> char_buf(boost::begin(recv_buffer_), boost::end(recv_buffer_)); 
         std::stringstream ss(std::string(char_buf.begin(), char_buf.end())); 
         std::vector<std::string> ip_list; 
         std::string ip; 
         std::cout << "Char_buf is: "; 
         for(auto it = boost::begin(recv_buffer_); it != boost::end(recv_buffer_); ++it) 
          std::cout << *it; 
         std::cout << "\nStringstream is: " << ss << '\n'; 
         while(std::getline(ss, ip, '$')) 
         { 
          ip_list.push_back(ip); 
         }; 
         ip_adr_ccd = ip_list[0]; 
         ip_adr_daisy = ip_list[1]; 
         std::cout << "ip_adr_ccd is: " << ip_list[1] << " and ip_adr_daisy is: " << ip_list[2] << '\n'; 
         ip_adr_display.push_back(ip_list[3]); 
         break; 
        } 
       default: 
        break; 

       start_receive(); 
       } 

,而我的傳送功能是

DLL void transmit_ip(void) 
{ 
    WORD wVersionRequested; 
    WSADATA wsaData; 
    int err; 

    wVersionRequested = MAKEWORD(2, 2); 

    err = WSAStartup(wVersionRequested, &wsaData); 
    if (err != 0) { 
     /* Tell the user that we could not find a usable */ 
     /* WinSock DLL.         */ 
     return; 
    } 


    struct sockaddr_in sa; 
    struct hostent  *hp; 
    SOCKET s; 
    std::string ip_adr; 
    if(Use == 'T') 
     ip_adr = ip_adr_ccd; 
    else 
    { 
     if(Use == 'S') 
      ip_adr = ip_adr_daisy; 
     else 
      ip_adr = ip_adr_display[0]; 
    }; 
    //Debug 
    //std::cout << "Pinging ip: " << ip_adr << '\n'; 
    hp = gethostbyname(ip_adr.c_str()); 
    if (hp == NULL) /* we don't know who this host is */ 
     return; 

    memset(&sa,0,sizeof(sa)); 
    memcpy((char *)&sa.sin_addr, hp->h_addr, hp->h_length); /* set address */ 
    sa.sin_family = hp->h_addrtype; 
    sa.sin_port = htons((u_short)PORTNUM_UDP_OUT); 

    s = socket(hp->h_addrtype, SOCK_DGRAM, 0); 
    if (s == INVALID_SOCKET) 
     return; 
    std::string tx_str = '$' + ip_adr_ccd + '$' + ip_adr_daisy + '$' + retLocalIP() + '$'; 
    //char str[] = "$127.0.0.1$128.0.0.1$129.0.0.1$"; 
    std::cout << "tx_str is: " << tx_str << '\n'; 
    char * buffer = new char[tx_str.length() + 1]; 
    std::strcpy(buffer, tx_str.c_str()); 
    int ret; 
    ret = sendto(s, buffer, sizeof(buffer), 0, (struct sockaddr *)&sa, sizeof(sa)); 
    delete buffer; 

} 

當我使用STR [1]傳輸,一切都很好,但是當我想要傳輸的我tx_str,接收器崩潰一次只顯示$ 192作爲收到的數據。我在做什麼錯誤來創建緩衝區溢出?

+0

嗯。沒有看過你的具體用法,但你知道UDP專門用於非保證傳輸? – sehe

+0

是的,我只是想與另一臺電腦ping一些數據(100字節或更少)。 –

回答

3

bufferchar*時,sizeof(buffer)返回指針的大小,而不是指向字符串的長度。看起來好像編譯它的系統使用4個字節作爲指針,因此只傳輸4個字符。在接收到4個字節時,handle_receive()在嘗試訪問ip_list中的無效索引時會調用未定義的行爲,因爲該代碼假定始終從接收消息中提取3個字符串。

要解決該問題,請明確提供緩衝區大小爲sendto()而不是使用sizeof()。變化:

ret = sendto(s, buffer, sizeof(buffer), 0, ...) 

到:

ret = sendto(s, buffer, tx_str.length() + 1, 0, ...) 

這也可能是值得考慮的檢查輸入和索引到它之前驗證ip_list是預期的大小。


char[]char*是不同的類型。在char*的情況下,sizeof()將返回給定系統上指針的大小,而不是指針指向的字符串的長度。另一方面,對於char[]sizeof()將返回數組的大小。例如:

#include <iostream> 

int main() 
{ 
    char str[] = "123456789ABCDEF"; 
    char* buffer = new char[100]; 
    std::cout << "char[] size = " << sizeof(str) << "\n" 
       "char* size = " << sizeof(buffer) << std::endl; 
} 

結果:

char[] size = 16 
char* size = 8 
+0

Oooh。那一個。不錯的地方。這是一段時間,因爲我已經看到這個bug源:) – sehe