2015-11-04 2 views
0

Я использовал метод «Create-new-thread» для работы с новыми клиентами и встретился с проблемой в UDP. Сначала я использовал основной поток, чтобы создать один поток TCP для обработки нового accept() и создать один поток UDP для работы с новым recvfrom(). (TCP-коды в порядке) После первого обратного вызова recvfrom() я пытаюсь передать клиент в новый поток UDP и сохранить текущую связь со следующим новым клиентом UDP. Это должна быть работа, передавая адрес и новые, созданный datagram-сокет для нового потока, чтобы продолжить делать recvfrom(), правильно?Реализация многопотокового параллельного сервера с помощью C++ (случай UDP)

Во время эксперимента я обнаружил, что поток OLD UDP продолжает получать датаграмму от клиента, в то время как новый поток, выполняющий только цикл, и recvfrom() превращается в неблокирующий способ и возвращает -1 в результате.

Поэтому в чем проблема с моим кодом .... спасибо ~ Я что-то неправильно понимаю ..?

PassToUDPThread является TypeOf структура я сделал для данных, передаваемых в новый поток:

typedef struct { 
    sockaddr_in ReceiverSocket; 
    SOCKET sendSocket; 
    char* recvbuf; 
    long packet_size; 

}PassToUDPThread; 

Вот мой код функции потока FIRST UDP (дело с первой recvfrom() ONLY):

sockaddr_in *ReceiverSocket = new sockaddr_in; 

ReceiverSocket->sin_family = AF_INET; 
if (strcmp(recv_hostname, "INADDR_ANY") != 0) 
inet_pton(AF_INET, ip_addr_char, &ReceiverSocket->sin_addr.s_addr); 
else ReceiverSocket->sin_addr.s_addr = INADDR_ANY; 
ReceiverSocket->sin_port = htons((u_short)recv_port); 

//*** Create the socket 
SOCKET s; 

s = socket(AF_INET, SOCK_DGRAM, 0); 
printf("Receiver: Socket Created - UDP connection\n"); 
bind(s, (struct sockaddr *)ReceiverSocket, sizeof(struct sockaddr_in)); 

do 
{ 
    int fromlen = (int)sizeof(struct sockaddr_in); 
    retVal = recvfrom(s, recvbuf, packet_size, 0, (struct sockaddr*)ReceiverSocket, &fromlen); 
    std::cout << "UDP recv by MAIN "<<std::endl; 
    if (retVal == SOCKET_ERROR) { 
     std::cout << "UDP Socket error : " + WSAGetLastError()<<std::endl; 
     return 0; 
    } 
    else { 
     SOCKET sendSocket = socket(AF_INET, SOCK_DGRAM, 0); 
     PassToUDPThread _p; 
     PassToUDPThread *p = &_p; 
     p->sendSocket = sendSocket; 
     p->ReceiverSocket = *ReceiverSocket; 
     p->recvbuf = recvbuf; 
     p->packet_size = packet_size; 

     thrd_t UDPthread; 
     if (thrd_create(&UDPthread, ThreadUDPReceiver, (void*)p) == thrd_success) { 
      std::cout<<"success create new UDP thread"<<std::endl; 
          } 




    } 
    } while (retVal>0); 
    closesocket(s); 
    UDPReceiver(arg); 
    return 1; 
} 

Вот код для функции на NEW-СОЗДАЛАСЬ UDP нить:

int ThreadUDPReceiver(void *arg) { 

    int retVal; 
    SOCKET s = ((PassToUDPThread*)arg)->sendSocket; 
    char* recvbuf = ((PassToUDPThread*)arg)->recvbuf; 
    long packet_size = ((PassToUDPThread*)arg)->packet_size; 
    sockaddr_in *ReceiverSocket = new sockaddr_in; 
    memcpy(ReceiverSocket, &(((PassToUDPThread*)arg)->ReceiverSocket), sizeof sockaddr_in); 

    bind(s, (struct sockaddr *)ReceiverSocket, sizeof(struct sockaddr_in)); 

    do { 
     int fromlen = (int)sizeof(struct sockaddr_in); 
     retVal = recvfrom(s, recvbuf, packet_size, 0, (struct sockaddr *)ReceiverSocket, &fromlen); 
     std::cout << "UDP recv by thread "<< std::endl; 
    } while (true); 

    return 0; 

    } 

ответ

0
  1. Используйте пул потоков.
  2. Избавьтесь от дополнительных гнезд UDP. Используйте тот же самый, чтобы отправить ответ, на который был отправлен запрос. Упрощение для клиента тоже.
+0

SO Мне нужно выбросить сокет s в новую резьбу? –

Смежные вопросы