マルチクライアントサーバープログラムがあります。クライアントコンソールは、ユーザーがサーバーに送信するメッセージを入力するのを待つ必要があります。また、クライアントはサーバーからのメッセージを常に受信できる必要があります(これは断続的に発生します)。これを行うために、クライアント側に2つのスレッドを設定しようとしました。1つは受信用、もう1つは送信用です。
当初、クライアントプログラム(ここからダウンロードしたもの)は、サーバーにメッセージを送信し、すぐにメッセージを受信するように設計されていました。これは初期コードです(関数が機能することがわかっているため、ここには関数を含めていません。関数名は一目瞭然です)。
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;
}