简体   繁体   中英

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. 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. To rectify that, you must create only one client connection and let both threads use the same.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM