2014-03-27 111 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