2017-02-05 114 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