2017-02-05 115 views
0

我正在开发机器人控制项目,主要应该(1)向机器人发送一些关于速度和固定位置的数据,然后(2)使用我的PC启动实时控制并重复。 我选择使用TCP/IP作为第一步和实时UDP/IP。 我试图编码这个,但我相信缺少一些东西。同时在TCP和UDP之间切换

我有一些问题:

1-当不存在输入的(客户机)的连接接受功能没有返回有效的套接字也不消息[10]印刷!!

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

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; 
    } 
+0

你关心丢包吗?如果是坚持TCP/IP。如果没有使用UDP。如果您觉得需要实施UDP包重新发送(如果丢失),然后使用TCP/IP。大部分TCP/IP开销都是打开初始连接。一旦打开,通过可靠连接的速度差别很小。 –

+0

我会尝试这两种技术,但我认为TCP/IP是非实时的 – Mahjob

回答

0

1-当不存在输入的(客户机)的连接接受功能 没有返回有效的套接字也不消息[10]印刷!!

accept()的正常行为是阻止(即不返回),直到收到一个传入的TCP连接或发生错误。如果你不想accept()来阻塞,你可以将TCP_Server套接字设置为非阻塞,这样就可以不用阻塞而是返回-1,而是将errno设置为EWOULDBLOCK。

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

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

这个问题是不明确的 - 相同的服务器IP和端口是什么?

如果您问是否可以将UDP套接字发送到在accept()调用中设置的相同IP地址和端口(即代码中的Client_Address),那么您可以这样做,但它只会在if你的机器人已经建立了一个UDP套接字来绑定到UDP端口空间中的端口号。 (需要注意的是UDP套接字和TCP套接字既可以绑定到同一个端口,而不互相干扰,因为他们有不同的端口空间,但出于同样的原因,你永远不会看到你的UDP套接字或TCP数据显示反之亦然)

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

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

+0

真棒谢谢人:D – Mahjob