【问题标题】:sendto() fails for Custom UDP Protocol, using Seagull Protocol Traffic Generator自定义 UDP 协议的 sendto() 失败,使用 Seagull 协议流量生成器
【发布时间】:2018-12-14 12:31:11
【问题描述】:

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

我现在正尝试使用此客户端向本地网络 (192.x.x.x) 上的服务器发送消息,但 Seagull 始终无法发送消息。这不是网络问题,因为我已经能够 ping 该地址而没有丢包。我已将错误的根源追溯到sendto() 函数,该函数由于参数无效而一直失败。当目标设置为本地环回和其他 IP 时,我已经使用 GDB 逐步完成了代码,并且传递给 sendto() 函数的参数完全相同,但 sockaddr 结构中的不同 IP 地址除外,这当然是意料之中的。但是,当我在sendto() 中的系统调用之后查看寄存器时,包含消息长度长度值的寄存器在调用过程中变为负数,这就是从函数调用返回的值 -本地环回网络不会发生这种情况。以下是调用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 主机上的 VM(Virtualbox)在 Ubuntu v 14.04 上运行客户端,我正在尝试发送消息。提前致谢!

【问题讨论】:

    标签: sockets networking udp network-protocols sendto


    【解决方案1】:

    经过几天的调试和查看源代码后,我找到了答案,我想更新它,以防将来任何可怜的灵魂遇到同样的问题。最初的 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 可以工作了,我可以发送我的自定义协议了!我打开了原始源代码的拉取请求,以便可以修复此问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-25
      • 2023-03-10
      • 1970-01-01
      • 2021-03-09
      • 1970-01-01
      • 1970-01-01
      • 2014-04-05
      • 2010-12-14
      相关资源
      最近更新 更多