here에서 여러 클라이언트 (한 클라이언트 당 하나의 스레드)를 처리 할 수있는 작업 서버가 있습니다. 순간 그것은 다음과 같이 작동여러 클라이언트가있는 서버 : 한 클라이언트에서 다른 클라이언트로 메시지를 전달하는 방법
- 클라이언트가 서버 측 콘솔에서 서버로 전송 (그리고 표시되는 클라이언트 콘솔에서 서버에
- 사용자 유형의 메시지를 연결
- 사용자 유형의 메시지를 서버 콘솔에.
그러나 내가하고 싶은 것은 클라이언트 1에서 처리를 위해 서버로가는 메시지를 수신 한 다음 클라이언트 3 (어떤 클라이언트 메시지는 서버에 의해 결정됩니다.)
내 생각에 clientHandleThread
을 수정해야하지만, 내가 무엇을해야하는지 모르겠습니다. 또한 현재 스레드와 별도의 스레드에 액세스 할 수 있는지 확실하지 않습니다.
나는 소켓 프로그래밍과 스레드에 익숙하며 배우기가 힘들다. 그래서 어떤 도움을 환영 할 것이다! 입력 한 및 출력을위한 하나 : 당신이 두 개의 큐를 가질 수 있습니다 각 연결을 위해 (! 내가 다른 코드를 첨부해야하는지 알려 주시기 바랍니다)
myLog winLog;
DWORD WINAPI clientHandleThread(LPVOID threadInfo)
{
//this structure will contain all the data this callback will work on
myThreadArgument* clientArgument = (myThreadArgument*)threadInfo;
//the semamphore to protect the access to the std output
mySemaphore* coutSemaphore = clientArgument->getCoutSemaphore();
/*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->receiveMessage(messageFromClient);
if (numBytes == -99) break;
//write to the console and the log file, so lock the semaphore
coutSemaphore->lock();
cout << "[RECV fr " << clientName << "]: " << messageFromClient << endl;
winLog << "[RECV fr " << clientName << "]: " << messageFromClient << endl;
msgInfo proMsgFrCli = msgClassification(messageFromClient);
//if the client wants to discount
if (messageFromClient.compare("quit") == 0 || messageFromClient.compare("Quit") == 0)
{
coutSemaphore->unlock();
break;
}
else // send to the client
{
char messageToClient[MAX_MSG_LEN+1];
memset(messageToClient,0,sizeof(messageToClient));
cout << "[SEND to " << clientName << "]: ";
cin.getline(messageToClient,MAX_MSG_LEN);
winLog << "[SEND to " << clientName << "]: " << messageToClient << endl;
clientConnection->sendMessage(string(messageToClient));
coutSemaphore->unlock();
}
}
// 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;
}
DWORD WINAPI serverHandleThread(LPVOID threadInfo) //server thread
{
//this structure will contain all the data this callback will work on
myThreadArgument* serverArgument = (myThreadArgument*)threadInfo;
//the semamphore to protect the access to the std output
mySemaphore* coutSemaphore = serverArgument->getCoutSemaphore();
//get the server
myTcpSocket* myServer = serverArgument->getClientConnect();
string serverName = serverArgument->getHostName();
//bind the server to the socket
myServer->bindSocket();
cout << endl << "server finishes binding process... " << endl;
winLog << endl << "server finishes binding process... " << endl;
//server starts to wait for client calls
myServer->listenToClient();
cout << "server is waiting for client calls ... " << endl;
winLog << "server is waiting for client calls ... " << endl;
//server starts to listen, and generates a thread to handle each client
myThreadArgument* clientArgument[MAX_NUM_CLIENTS];
myThread* clientHandle[MAX_NUM_CLIENTS];
for (int i = 0; i < MAX_NUM_CLIENTS; i++)
{
clientArgument[i] = NULL;
clientHandle[i] = NULL;
}
int currNumOfClients = 0;
char buffer [100]; //temp buffer to convert currNumOfClients to char
while (1)
{
//wait to accept a client connection.
//processing is suspended until the client connects
myTcpSocket* client; //connection dedicated for client communication
string clientName; //client name
client = myServer->acceptClient(clientName);
clientName = clientName + "-" + itoa(currNumOfClients, buffer, 10);//char(65+currNumOfClients);
//lock the std out so we can write to the console
coutSemaphore->lock();
cout << endl << endl << "==> a client from [" << clientName << "] is connected!" << endl;
winLog << endl << "==> a client from [" << clientName << "] is connected!" << endl << endl;
coutSemaphore->unlock();
//for this client, generate a thread to handle it
if (currNumOfClients < MAX_NUM_CLIENTS-1)
{
clientArgument[currNumOfClients] = new myThreadArgument(client,coutSemaphore,clientName);
clientHandle[currNumOfClients] = new myThread(clientHandleThread,(void*)clientArgument[currNumOfClients]);
serverArgument->addClientArgument(clientArgument[currNumOfClients]);
clientHandle[currNumOfClients]->execute();
currNumOfClients++;
}
}
return 1;
}
int main()
{
/*build a semaphore so we can synchronize the access to std cout
also includes the log file*/
mySemaphore coutSemaphore(string(""),1);
//initialize the winsock library
myTcpSocket::initialize();
/*create the server: local host will be used as the server, let us
first use myHostInfo class to show the name and IP address
of the local host*/
winLog << endl;
winLog << "retrieve the local host name and address:" << endl;
myHostInfo serverInfo;
string serverName = serverInfo.getHostName();
string serverIPAddress = serverInfo.getHostIPAddress();
cout << "my localhost (server) information:" << endl;
cout << " name: " << serverName << endl;
cout << " address: " << serverIPAddress << endl;
winLog << " ==> name: " << serverName << endl;
winLog << " ==> address: " << serverIPAddress << endl;
//open socket on the local host(server) and show its configuration
myTcpSocket myServer(PORTNUM);
cout << myServer;
winLog << myServer;
//read connectivityFile
neighbourInfo = connFrFile(numberOfFiles, intBtwnChange);
//read routingFile
nextHopInfo = routFrFile(numberOfFiles, intBtwnChange);
/*create a thread to implement server process: listening to the socket,
accepting client calls and communicating with clients. This will free the
main control (see below) to do other process*/
myThreadArgument* serverArgument = new myThreadArgument(&myServer,&coutSemaphore,serverName);
myThread* serverThread = new myThread(serverHandleThread,(void*)serverArgument);
serverThread->execute();
// main control: since the serverThread is handling the server functions,
// this main control is free to do other things.
while (1)
{
/*do whatever you need to do here, I am using Sleep(x)
to make a little delay, pretending to be the other
possible processings*/
Sleep(50000);
//report the server status
coutSemaphore.lock();
cout << endl << "-----------------------------------------------------------------" << endl;
winLog << endl << "-----------------------------------------------------------------" << endl;
cout << "server (name:" << serverName << ") status report:" << endl;
winLog << "server (name:" << serverName << ") status report:" << endl;
cout << " the following clients have successfully connected with server: " << endl;
winLog << " the following clients have successfully connected with server: " << endl;
for (int i = 0; i < MAX_NUM_CLIENTS; i ++)
{
myThreadArgument* clientInfo = serverArgument->getClientArgument(i);
if (clientInfo)
{
cout << " " << clientInfo->getHostName() << endl;
winLog << " " << clientInfo->getHostName() << endl;
}
}
cout << " the following clients have shutdown the connection: " << endl;
winLog << " the following clients have shutdown the connection: " << endl;
for (int i = 0; i < MAX_NUM_CLIENTS; i ++)
{
myThreadArgument* clientInfo = serverArgument->getClientArgument(i);
if (clientInfo && clientInfo->getExitEvent()->waitForEvent(0))
{
clientInfo->setSignalToEnd(true);
cout << " " << clientInfo->getHostName() << endl;
winLog << " " << clientInfo->getHostName() << endl;
}
}
cout << "-----------------------------------------------------------------" << endl << endl;
winLog << "-----------------------------------------------------------------" << endl << endl;
coutSemaphore.unlock();
}
return 1;
}
대기열 가지고 -이에 대한 자세한 내용을 모르고 내 사과. 내 프로그램에 이미 구현 된 큐가 있습니까 (그렇게 생각하지는 않지만 아마도이 오류가있을 수 있습니다)? 대답에서 내 이해는 1/clientHandleThread 아래에 현재 클라이언트에 메시지를 보내고받는 큐를 구현해야합니다. 2/현재 기존 서버 스레드가 하나이며 하나 추가해야합니다. 이 대기열을 처리하는 데 더 많은 시간이 필요합니까? 그리고 나는이 주제에 대해 더 많이 알고 싶습니다. 그러나 이것을 수행하는 좋은 예를 알고 있습니까? (그리고 지금까지 도와 줘서 고맙습니다.) – sccs
@sccs 구현 방법에 대한 간단한 의사 코드 예제가 추가되었습니다. 대기열은 배열 및 목록 뒤에있는 가장 기본적인 데이터 구조 중 하나입니다. –
감사합니다. 나는 이것을 시험해보고 그것이 어떻게 진행되는지 보게 될 것이다. – sccs