[英]Multi-threaded client not receiving messages from server
I have a multiclient-server program. 我有一个多客户端服务器程序。 The client console will need to wait for user to input a message to send onto the server, and the client also needs to always be available for receiving messages from the server (this happens intermittently).
客户端控制台将需要等待用户输入要发送到服务器的消息,并且客户端还需要始终可用于接收来自服务器的消息(这是间歇性发生的)。 In order to do this, I have tried to set up two threads on the client-side, one for receiving, and one for sending.
为了做到这一点,我尝试在客户端设置两个线程,一个用于接收,另一个用于发送。
Initially, the client program (which I downloaded from here ) was designed to send a message to the server and receive a message back immediately. 最初,客户端程序(我从这里下载了 )旨在将消息发送到服务器并立即收到消息。 This is the initial code (I have not included the functions here because I know they work, and the function names are self-explanatory):
这是初始代码(我在这里未包括这些功能,因为我知道它们可以工作,并且这些功能的名称不言而喻):
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;
}
This code works, but since the server does not always have a message to send back to the client upon receiving a message, this holds up processes on the client side, which is why I am using a multi-threaded structure as below (functions not included for the above reason), separating the receiving and sending functions into different threads: 这段代码有效,但是由于服务器在接收到消息时并不总是有消息要发送回客户端,因此这会阻塞客户端的进程,这就是为什么我使用如下所示的多线程结构(功能包括在内),将接收和发送功能分为不同的线程:
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;
}
I have tested that I have set up the threads properly - but only my send thread works ie when the user inputs a message, it will be sent to and received by the server. 我测试过我已经正确设置了线程-但是只有我的发送线程有效,即当用户输入消息时,它将被发送到服务器并由服务器接收。 However, I cannot seem to receive the message from my server.
但是,我似乎无法从服务器收到消息。
I'm new to this - is there anything that I am doing wrongly? 我是新手-我做错了什么吗? Sorry if the question isn't clear enough - I don't know what else is needed.
很抱歉,这个问题还不够清楚-我不知道还需要什么。
The relevant snippet of my server code is here for reference (I don't know if more is required, since the server portion seems to work the way I need it to) - at the moment I have set it up for testing so that when it receives a message from a client, it will 'reply' immediately (so that I can test the receiving thread on my client). 我的服务器代码的相关代码段在这里供参考(我不知道是否需要更多代码,因为服务器部分似乎可以按我需要的方式工作)-目前,我已将其设置为进行测试,以便它从客户端收到一条消息,它将立即“回复”(以便我可以在客户端上测试接收线程)。 Subsequently it will not reply immediately, but only when it has messages to pass on to the client.
随后,它不会立即答复,而只会在有消息传递给客户端时答复。
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;
}
In your multi-threaded program, you are creating two clients, one in sendHandleThread
and the other in recHandleThread
, and therewith two connections. 在多线程程序中,您将创建两个客户端,一个在
sendHandleThread
,另一个在recHandleThread
,并recHandleThread
两个连接。 Of course, the server sends its reply message over the connection where the client's message came in, ie to the sendHandleThread
, which is not prepared to receive it, while the recHandleThread
receives nothing over its connection, because nothing was sent there. 当然,服务器通过客户端消息进入的连接发送答复消息,即发送到不准备接收消息的
sendHandleThread
,而recHandleThread
接收任何消息,因为那里没有发送任何消息。 To rectify that, you must create only one client connection and let both threads use the same. 要解决此问题,您必须仅创建一个客户端连接,并让两个线程使用相同的连接。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.