2017-02-05 9 views
0

Я работаю над проектом управления роботом, где я должен прежде всего (1) отправить некоторые данные о скорости и фиксированных позициях роботу, затем (2) запустить управление в реальном времени с помощью моего ПК и повторить. Я решил использовать TCP/IP для первого шага и для UDP/IP в реальном времени. Я пытался это кодировать, но я считаю, что чего-то не хватает.Переключение между TCP и UDP одновременно

У меня есть некоторые проблемы:

1- Когда нет входящих (клиентов) соединений принимают функцию не возвращать допустимый сокет, ни сообщение [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; 
    } 
+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 составляет буферизованный, что означает, что любой текст, который вы отправляете на него, фактически не появится в окне терминала, ve напечатал символ новой строки ('\ n' или std :: endl) или вручную сбросил поток. Поэтому, если вы не видите ожидаемый результат своевременно, вы можете проверить, что строка Message [10] содержит символ новой строки или, альтернативно, добавляет << std::endl; в конец ваших звонков cout << blah.

2. Согласен ли Sendto использовать тот же IP-адрес сервера и порт?

Этот вопрос неоднозначен - тот же сервер IP и порт как и что?

Если вы спрашиваете, можете ли вы отправлять сокеты UDP на тот же IP-адрес и порт, которые были установлены в вызове accept() (т.е. Client_Address в вашем коде), вы можете это сделать, но это будет работать, только если ваш робот настроил UDP-сокет для привязки к этому номеру порта в пространстве портов UDP. (Обратите внимание, что сокет UDP и сокет TCP могут связываться с одним и тем же портом, не мешая друг другу, поскольку они имеют разные пространства портов, но тем не менее, вы никогда не увидите TCP-данные в вашем UDP-сокете или наоборот)

3- это правильный способ для переключения между UDP и TCP вперед и назад или есть некоторые соображения должны быть предприняты?

Похоже, что он может работать более или менее, хотя более надежная конструкция будет такой, которая использует неблокирующие сокеты и всегда передает все сокеты (т.исходный TCP-сокет, который вы передаете, чтобы принимать(), TCP-сокеты TCP каждого TCP-соединения, которые были возвращены accept() и вашим UDP-сокетом) в каждый read-fd_set каждого выбранного вызова, а затем всегда проверяет все из этих сокетов (через FD_ISSET()) после того, как select() возвращает и реагирует соответствующим образом, когда любой из них готов к чтению. Таким образом, ваша программа всегда может обрабатывать входящие TCP-данные, одновременно обрабатывая входящие данные UDP, а не переключается с режима, когда он обрабатывает только TCP в режиме, где он обрабатывает только UDP (и игнорирует любые данные, которые не соответствуют его текущему режиму потому что обычно игнорирование входящих данных делает плохой опыт для клиента/робота, чьи запросы вы игнорируете). Это также позволит вам принимать() входящие TCP-соединения в любое время (поскольку входящее TCP-соединение приведет к тому, что ваш сокет TCP_Server будет выбран как готовый для чтения, после чего вы сможете снова вызвать accept() на нем).

+0

Удивительный человек: D – Mahjob