Многопоточный клиент не получает сообщения от сервера

У меня есть многоклиент-серверная программа. Клиентская консоль должна будет ждать, пока пользователь введет сообщение для отправки на сервер, и клиент также должен быть всегда доступен для приема сообщений от сервера (это происходит периодически). Для этого я попытался настроить два потока на стороне клиента, один для получения и один для отправки.

Изначально клиентская программа (которую я скачал с Вот) был предназначен для отправки сообщения на сервер и немедленного получения сообщения обратно. Это исходный код (я не включил функции здесь, потому что я знаю, что они работают, и имена функций говорят сами за себя):

int main()
{
//initialize the winsock library
myTcpSocket::initialize();

//get client's information
string clientName = clientInfo.getHostName();
string clientIPAddress = clientInfo.getHostIPAddress();

//get server's IP address and name
string serverIPAddress = "";
readServerConfig(serverIPAddress);

myHostInfo serverInfo(serverIPAddress,ADDRESS);
string serverName = serverInfo.getHostName();

//create the socket for client
myTcpSocket myClient(PORTNUM);

// connect to the server.
myClient.connectToServer(serverIPAddress, ADDRESS);

int recvBytes = 0;
while (1)
{
// send message to server
char messageToServer[MAX_MSG_LEN+1];
memset(messageToServer, 0, sizeof(messageToServer));
cout << "[SEND] ";
cin.getline(messageToServer,MAX_MSG_LEN);

winLog << "[SEND] " << messageToServer << endl;
myClient.sendMessage(string(messageToServer));

if ( !string(messageToServer).compare("Quit") || !string(messageToServer).compare("quit") )
break;

//receive message from server
string messageFromServer = "";
recvBytes = myClient.receiveMessage(messageFromServer);
if ( recvBytes == -99 ) break;

cout   << "[RECV:" << serverName << "]: " << messageFromServer << endl;
winLog << "[RECV:" << serverName << "]: " << messageFromServer << endl;

}

return 1;
}

Этот код работает, но так как сервер не всегда имеет сообщение для отправки клиенту после получения сообщения, это задерживает процессы на стороне клиента, поэтому я использую многопоточную структуру, как показано ниже (функции не включается по вышеуказанной причине), разделяя функции получения и отправки в разные потоки:

DWORD WINAPI sendHandleThread(LPVOID threadInfo) //sending thread
{
//this structure contains all the data this callback will work on
myThreadArgument* sendArgument = (myThreadArgument*)threadInfo;

//create the socket for client
myTcpSocket myClient(PORTNUM); //PORTNUM = 1200

// connect to the server.
string serverIPAddress = "";
readServerConfig(serverIPAddress);
myClient.connectToServer(serverIPAddress, ADDRESS);

myHostInfo serverInfo(serverIPAddress,ADDRESS);
string serverName = serverInfo.getHostName();

int recvBytes = 0;

while (1)
{
// send message to server
char messageToServer[MAX_MSG_LEN+1];
memset(messageToServer, 0, sizeof(messageToServer));
cout << "[SEND] ";
cin.getline(messageToServer,MAX_MSG_LEN);

winLog << "[SEND] " << messageToServer << endl;
myClient.sendMessage(string(messageToServer));

if ( !string(messageToServer).compare("Quit") || !string(messageToServer).compare("quit") )
break;
}
return 1;
}

DWORD WINAPI recHandleThread(LPVOID threadInfo) //receiving thread
{
//this structure contains all the data this callback will work on
myThreadArgument* recArgument = (myThreadArgument*)threadInfo;

//create the socket for client
myTcpSocket myClient(PORTNUM); //PORTNUM = 1200

// connect to the server.
string serverIPAddress = "";
readServerConfig(serverIPAddress);
myClient.connectToServer(serverIPAddress, ADDRESS);

myHostInfo serverInfo(serverIPAddress,ADDRESS);
string serverName = serverInfo.getHostName();

int recvBytes = 0;

while (1)
{
//receive message from server
string messageFromServer = "";
recvBytes = myClient.receiveMessage(messageFromServer);
if ( recvBytes == -99 ) break;

cout   << "[RECV:" << serverName << "]: " << messageFromServer << endl;
winLog << "[RECV:" << serverName << "]: " << messageFromServer << endl;
}
return 1;
}

int main()
{
//semaphore
mySemaphore coutSemaphore(string(""), 1);

//initialize the winsock library
myTcpSocket::initialize();

//get client's information (assume neither the name nor the address is given)
string clientName = clientInfo.getHostName();
string clientIPAddress = clientInfo.getHostIPAddress();

//get server's IP address and name
string serverIPAddress = "";
readServerConfig(serverIPAddress);

myHostInfo serverInfo(serverIPAddress,ADDRESS);
string serverName = serverInfo.getHostName();

//create sending thread
myTcpSocket send;
string sendName = "sendName";
myThreadArgument* sendArgument = new myThreadArgument(&send, &coutSemaphore, sendName);
myThread* sendThread = new myThread(sendHandleThread, (void*)sendArgument);
sendThread->execute();

//create receiving thread
myTcpSocket rec;
string recName = "recName";
myThreadArgument* recArgument = new myThreadArgument(&rec, &coutSemaphore, recName);
myThread* recThread = new myThread(recHandleThread, (void*)recArgument);
recThread->execute();

while (1)
{

//dummy process
Sleep(30000);
cout << "--" << endl;

}

return 1;
}

Я проверил, что я правильно настроил потоки, но работает только мой поток отправки, т.е. когда пользователь вводит сообщение, оно будет отправлено и получено сервером. Тем не менее, я не могу получить сообщение от моего сервера.

Я новичок в этом — есть ли что-то, что я делаю неправильно? Извините, если вопрос недостаточно ясен — я не знаю, что еще нужно.

Соответствующий фрагмент моего серверного кода приведен здесь для справки (я не знаю, требуется ли больше, поскольку серверная часть, кажется, работает так, как мне нужно) — в данный момент я настроил его для тестирования, чтобы при он получает сообщение от клиента, он немедленно «ответит» (чтобы я мог проверить принимающий поток на моем клиенте). Впоследствии он не будет отвечать сразу, а только тогда, когда у него есть сообщения для передачи клиенту.

DWORD WINAPI clientHandleThread(LPVOID threadInfo)
{
// this structure will contain all the data this callback will work on
myThreadArgument* clientArgument = (myThreadArgument*)threadInfo;

// get the client connection: receiving messages from client and
// sending messages to the client will all be done by using
// this client connection
myTcpSocket* clientConnection = clientArgument->getClientConnect();
string clientName = clientArgument->getHostName();

// the server is communicating with this client here
while(1)
{
string messageFromClient = "";

// receive from the client

int numBytes = clientConnection->recieveMessage(messageFromClient);
if ( numBytes == -99 ) break;

cout   << "[RECV fr " << clientName << "]: " << messageFromClient << endl;

// if the client wants to disconnect
if ( messageFromClient.compare("quit") == 0 || messageFromClient.compare("Quit") == 0 )
{
break;
}
else // send to the client
{
clientConnection->sendMessage(string("testing")); //test reply
}
}

// if we reach here, this session with the client is done,
// so we set the event on this thread to inform the main
// control that this session is finished
clientArgument->getExitEvent()->setEvent();
return 1;
}

0

Решение

В вашей многопоточной программе вы создаете двух клиентов, один в sendHandleThread а другой в recHandleThreadи вместе с тем два соединения. Конечно, сервер отправляет ответное сообщение по соединению, куда пришло сообщение клиента, т.е. е. к sendHandleThread, который не готов получить его, в то время как recHandleThread ничего не получает через свою связь, потому что ничего не было отправлено туда.
Чтобы исправить это, вы должны создать только одно клиентское соединение и позволить обоим потокам использовать одно и то же.

0

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector