使用 Seagull 协议流量生成器的自定义 UDP 协议的 sendto() 失败

sendto() fails for Custom UDP Protocol, using Seagull Protocol Traffic Generator

我是网络、协议和套接字方面的新手运行,但这个问题已经困扰我好几天了,我似乎找不到解决方案。我正在使用 Seagull, an open source multi-protocol traffic generator (source code),创建一个带有自定义 UDP 的客户端。不幸的是,没有人真正跟上这个软件了,其他人也遇到过这个问题,但没有解决方案,它可能是生成器软件中的一个错误。我能够编写 运行 流量生成器所需的 XML 脚本,当我 运行 本地环回 (127.0.0.1) 上的客户端时,生成器工作正常,我能够收集数据包并使用 Wireshark 对其进行分析,它们包含正确的数据。

我现在正尝试使用此客户端向本地网络 (192.x.x.x) 上的服务器发送消息,但 Seagull 始终无法发送消息。这不是网络问题,因为我已经能够 ping 地址而没有丢包。我已经将错误的来源追溯到 sendto() 函数,该函数由于参数无效而一直失败。当目标设置为本地环回和其他 IP 并且传递给 sendto() 函数的参数完全相同时,我使用 GDB 逐步执行了代码,除了 [=12= 中的不同 IP 地址之外] 结构,这当然是预期的。但是,当我在 sendto() 中的系统调用之后查看寄存器时,包含消息长度值的寄存器在调用中途变为负数,这就是从函数返回的值call-本地环回网络不会发生这种情况。这是调用 sendto() 并失败的代码部分:

  size_t C_SocketWithData::send_buffer(unsigned char     *P_data, 
                                     size_t             P_size){
  //                                     T_SockAddrStorage *P_remote_sockaddr,
  //                                     tool_socklen_t    *P_len_remote_sockaddr) {

  size_t L_size = 0 ;
  int    L_rc       ;

  if (m_write_buf_size != 0) { 

    // Try to send pending data 
    if (m_type == E_SOCKET_TCP_MODE) {
      L_rc = _call_write(m_write_buf, m_write_buf_size) ;
    } else {
      L_rc = _write(m_write_buf, m_write_buf_size) ;
    }

    if (L_rc < 0) {
      SOCKET_ERROR(0,
                   "send failed [" << L_rc << "] [" << strerror(errno) << "]");
      switch (errno) {
      case EAGAIN:
        SOCKET_ERROR(0, "Flow control not implemented");
        break ;
      case ECONNRESET:
        break ;
      default:
        SOCKET_ERROR(0, "process error [" << errno << "] not implemented");
        break ;
      }
      return(0);

其中 _write()sendto() 的包装器。

我不太确定是什么原因导致它这样做,我花了几个小时查看源代码并跟踪发生了什么,但一切似乎都很正常,直到缓冲区长度被修改系统调用。我查看了 socket() 初始化、绑定和其他函数,但一切似乎都很好。如果有人对 Seagull 有任何经验或此问题,请告诉我您是否有任何建议。我浏览了本网站上几乎所有 sendto() 相关问题,但没有找到解决方案。

我正在 运行通过 Windows 10 主机上的虚拟机 (Virtualbox) 在 Ubuntu v 14.04 上连接客户端,我正在尝试向其中发送消息。提前致谢!

经过几天的调试和查看源代码,我找到了这个问题的答案,我想更新这个,以防将来有任何可怜的人遇到同样的问题。最初的 Seagull 实现总是在调用 send/sendto 之前尝试绑定套接字。在这种情况下,由于 sendto 自动绑定套接字,因此我能够删除这种情况下的绑定。

C_SocketClient::_open 中的原始实现(C_Socket.cpp 第 666 行):

} else {
  L_rc = call_bind(m_socket_id, 
                   (sockaddr *)(void *)&(m_remote_addr_info->m_addr_src),
                   SOCKADDR_IN_SIZE(&(m_remote_addr_info->m_addr_src)));

编辑版本:

 } else {
  L_rc = call_bind(m_socket_id, 

  /* UDP Does not need to bind first */
  if(m_type != E_SOCKET_UDP_MODE) {
    L_rc = call_bind(m_socket_id, 
                    (sockaddr *)(void *)&(m_remote_addr_info->m_addr_src),
                    SOCKADDR_IN_SIZE(&(m_remote_addr_info->m_addr_src)));

    } else {
  L_rc = 0;
    }

现在 Seagull 可以工作了,我可以发送我的自定义协议了!我打开了原始源代码的拉取请求,以便可以修复此问题。