2016-09-18 1 views
2

У меня есть сервер, который может принимать два соединения сокета. Он создает поток для каждого сокета, чтобы сообщения могли отправляться параллельно.
socket: многопоточность не работает, когда клиент читает сообщения

Теперь я пытаюсь закодировать своего клиента.

Я создаю класс с именем SocketThread как нить сокета. Вот основной код:

void SocketThread::ReadData() 
{ 
    int n = 0; 
    while (!finished) 
    { 
     while ((n = read(sockfd, recvBuff, sizeof(Data))) > 0) 
     { 
      std::cout<<std::this_thread::get_id()<<std::endl; 
      std::this_thread::sleep_for(std::chrono::milliseconds(2000)); 
     } 
    } 
} 

std::thread SocketThread::run() 
{ 
    return std::thread([=] { ReadData(); }); 
} 

в функции main:

SocketThread s0("127.0.0.1", 10000); 
SocketThread s1("127.0.0.1", 10000); 
std::thread td0{sts[0].run()}; 
std::thread td1{sts[1].run()}; 
td0.join(); // stop here 
td1.join(); 
// something else 

Когда я выполнить программу, он будет блокировать на td0.join();, что означает, что я могу получить идентификатор нити td0 на консоли, и я НИКОГДА не получаю другой поток.

Однако, когда я удаляю (n = read(sockfd, recvBuff, sizeof(Data))) > 0, это означает, что теперь клиент - это просто поток, который ничего не получит, все будет хорошо. Я могу получить два идентификатора из двух потоков.

Почему?

EDIT Похоже, что я использовал join неправильно.
Мне нужно то, что main не выполняет //something else, пока оба потока не получат 1000 символов.
Что мне делать?

+0

У меня возникли трудности с пониманием вашего вопроса, но 'read()' call является блокирующим по умолчанию. –

+0

@AbhinavGauniyal Когда я выполняю клиент, 'main' будет блокироваться на' td0.join() '. Зачем. – Yves

+0

, потому что 'join()' блокируется. 'join()' возвращается, когда поток заканчивается. Что вы хотите сделать точно? – shrike

ответ

0

Вы не использовали join(). Если вы хотите, чтобы main() блокировался до тех пор, пока оба потока не закончились, ваш код верен: td0.join() будет блокироваться до тех пор, пока нить td0 не закончится, и то же самое для td1.

Теперь, если вы хотите, чтобы ваши темы до конца после получения sizeof(Data) байт, ваша функция void SocketThread::ReadData() должна скорее выглядеть следующим образом:

void SocketThread::ReadData() 
{ 
    int n, total = 0; 
    while (!finished) 
    { 
     while ((n = read(sockfd, &recvBuff[total], sizeof(Data) - total)) > 0) 
     { 
      total += n; 
     } 
     if (n == -1) 
     { 
      // manage error here 
     } 
     if (n == 0) 
     { 
      std::cout << "client shut the socket down; got " << total << " bytes over " << sizeof(Data) << std::endl; 
      finished = true; 
     } 
    } 
} 

За короткое объяснение: нет никакой гарантии, что вы можете получить все данные, передаваемые по клиенту в одной операции read(), поэтому вам нужно позвонить read() и накапливать данные в буфер до тех пор, пока не получите возвращаемое значение 0 (это означает, что клиент отключил сокет). read(sockfd, &recvBuff[total], sizeof(Data) - total) гарантирует, что входящие данные будут правильно добавлены в нужное положение в буфере.

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