Привет всем гуру программирования сетевых приложений! Пишу простенький telnet клиент в качестве упражнения, и решил воспользоваться такой фишкой как многопоточность. Есть два потока: один занимается приемом от пользователя команд с клавиатуры ( cin.getline() ) и отсыланием их на сервер, другой же принимает данные с сервера и печатает на консоль. Все общение client-server происходит через объект класса NVT (Network Virtual Terminal), который является простой оберткой над BSD Sockets API. По идее, когда один поток ждет от пользователя команд, другой каждую секунду опрашивает сервер и печатает данные, если они были им посланы. В теории, эти два потока выполняются параллельно и благополучно общаются, синхронизируясь через mutex-ы. Вот фрагмент кода:
boost::mutex nvtMutex;
boost::mutex quitMutex;
bool quit = false;
ПОТОК1: void *processServerOutput(void *arg)
{
NVT *nvt = (NVT*)arg;
while(1)
{
// Lock the quitMutex before trying to access to quit variable
quitMutex.lock();
if(quit)
{
quitMutex.unlock();
pthread_exit(NULL);
}
else
quitMutex.unlock();
// Receive output from server
nvtMutex.lock();
nvt->receive();
cout << Util::Instance()->iconv("koi8-r", "utf-8", nvt->getOutBuffer()); // convert the output from KOI8-R to UTF-8
nvtMutex.unlock();
// Delay
sleep(1);
}
}
ПОТОК2: void *processUserInput(void *arg)
{
NVT *nvt = (NVT*)arg;
while(1)
{
// Get user's input
cin.getline(str, 1023);
// If we type 'quit', exit from thread
if(strcmp(str, "quit") == 0)
{
// Lock quit variable before trying to modify it
quitMutex.lock();
quit = true;
quitMutex.unlock();
// Exit from thread
pthread_exit(NULL);
}
// Send the input to server
nvtMutex.lock();
nvt->writeUserCommand(Util::Instance()->iconv("utf-8", "koi8-r", str)); // Convert the output from UTF-8 to KOI8-R
nvt->send();
nvtMutex.unlock();
}
}
NVT->receive() и NVT->send() являются обертками над операциями с сокетами send() и recv(). Проблема в том, что когда сервер в ожидании и не отправляет никаких данных, ОБА потока зависают! То есть, выполнение приостанавливается на NVT->receive()! В чем же тогда суть многопоточности? Потестировав, заметил что ПОТОК1 выполняется бесконечно если закомментировать строку NVT->receive(), когда ПОТОК2 в ожидании ввода. Но почему-же ПОТОК2 зависает когда ПОТОК1 ожидает данных с сервера?