【问题标题】:Switching between TCP and UDP simultaneously同时在 TCP 和 UDP 之间切换
【发布时间】:2017-02-06 03:07:20
【问题描述】:

我正在从事机器人控制项目,我应该主要 (1) 向机器人发送一些有关速度和固定位置的数据,然后 (2) 使用我的 PC 启动实时控制并重复。 我选择使用 TCP/IP 作为第一步和实时 UDP/IP。 我尝试编写此代码,但我认为缺少某些内容。

我有一些问题:

1- 当没有传入(客户端)连接时,接受函数没有返回有效的套接字,也没有打印 Message[10]!!

2- Sendto 可以使用相同的服务器 IP 和端口吗?

3- 这是在 UDP 和 TCP 之间来回切换的正确方法还是应该考虑一些因素?

while(Comm_Loop)
{
    while (TCP_Loop)
    {   
        TCP_Client = accept(TCP_Server, (struct sockaddr*) &Client_Address, &Client_Address_Length) ;
        if ( TCP_Client != INVALID_SOCKET)
        {                   
            if (Data_Trans) 
            {
                State = send(TCP_Client, Msg, sizeof(Msg), 0) ;
                if (State != SOCKET_ERROR)
                    TCP_Loop = 0 ;
                else 
                    cout << Message[8] ;
            }
        }
        else cout << Message[10] ;
    }
    Check_Send = sendto(UDP_Socket,
                        UDP_Send_Packet,
                        sizeof(UDP_Send_Packet),
                        0,
                        (LPSOCKADDR) &Socket_Address, 
                        sizeof(Socket_Address));

        fd_set  SockSet  ;  
        timeval Time_Out ; 

        FD_ZERO(&SockSet) ;        
        FD_SET(UDP_Socket, &SockSet);  

        Time_Out.tv_sec  = 5;  
        Time_Out.tv_usec = 0 ;  

        State = select(0, &SockSet, (fd_set *)NULL, (fd_set *)NULL, &Time_Out) ;

        if((State > 0) && (FD_ISSET(UDP_Socket, &SockSet) != 0)) 
        { 
            Check_Recieve = recvfrom(UDP_Socket,
                                    UDP_Recieve_Packet,
                                    Buffer_Length,
                                    0,
                                    NULL,
                                    NULL);
            TCP_Loop = 1 ;
        }
        else 
        { 
            // Reception timeout
            Comm_Loop = 0; 
        }
    }

    closesocket(TCP_Client) ;
    closesocket(TCP_Server) ;
    closesocket(UDP_Socket) ;

     WSACleanup() ;

     return 0;
     }

【问题讨论】:

  • 你关心丢包吗?如果是,请坚持 TCP/IP。如果没有使用UDP。如果您觉得需要实现 UDP 包重新发送(以防丢失),请使用 TCP/IP。大多数 TCP/IP 开销是在打开初始连接时。一旦打开,可靠连接的速度几乎没有差异。
  • 我会尝试这两种技术,但我认为 TCP/IP 是非实时的

标签: c++ sockets tcp


【解决方案1】:

1- 当没有传入(客户端)连接时接受函数 没有返回有效的套接字,也没有打印 Message[10]!!

accept() 的正常行为是阻塞(即不返回),直到接收到传入的 TCP 连接或发生错误。如果您不希望accept() 阻塞,可以将TCP_Server 套接字设置为非阻塞,这样它不会阻塞,而是返回-1 并将errno 设置为EWOULDBLOCK。

就 Message[10] 不打印而言,请记住 stdout/cout 流是缓冲的,这意味着您发送给它的任何文本实际上都不会显示在终端窗口中直到您打印了换行符('\n' 或 std::endl)或手动刷新了流。因此,如果您没有及时看到预期的输出,您可能需要验证您的 Message[10] 字符串是否包含换行符,或者将&lt;&lt; std::endl; 附加到您的cout &lt;&lt; blah 调用的末尾。

2- Sendto 可以使用相同的服务器 IP 和端口吗?

这个问题含糊不清——服务器 IP 和端口与什么相同?

如果您询问是否可以将 UDP 套接字发送到在 accept() 调用中设置的相同 IP 地址和端口(即代码中的 Client_Address),您可以这样做,但它只会起作用如果您的机器人已设置 UDP 套接字以绑定到 UDP 端口空间中的该端口号。 (请注意,UDP 套接字和 TCP 套接字都可以绑定到同一个端口而不会相互干扰,因为它们具有不同的端口空间,但出于同样的原因,您将永远不会看到 TCP 数据出现在您的 UDP 套接字或反之亦然)

3- 这是在 UDP 和 TCP 之间来回切换的正确方法吗 还是有一些考虑?

看起来它或多或少可以工作,尽管更健壮的设计是使用非阻塞套接字并始终传递所有套接字(即您传递给 accept() 的原始 TCP 套接字, accept() 返回的每个 TCP 连接的 TCP 套接字和您的 UDP 套接字)到每个 select 调用的 read-fd_set,然后总是在 select() 返回后检查所有这些套接字(通过 FD_ISSET())并在其中任何一个准备好阅读时做出适当的反应。这样,您的程序可以始终处理传入的 TCP 数据,同时处理传入的 UDP 数据,而不是从仅处理 TCP 的模式切换到仅处理 UDP 的模式(并忽略与其当前模式不对应的任何数据; 因为通常忽略传入数据会给您忽略其请求的客户端/机器人带来糟糕的体验)。这也将允许您随时接受()传入的 TCP 连接(因为传入的 TCP 连接会导致您的 TCP_Server 套接字选择为准备读取,此时您可以再次调用 accept() )。

【讨论】:

    猜你喜欢
    • 2017-08-02
    • 1970-01-01
    • 2016-08-15
    • 2018-04-22
    • 2023-03-28
    • 2017-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多