主要思想是:
第一个线程只是等待客户端的连接。所以这个线程是一个管理器(communicationthread)。 一旦accept == true,该线程就会创建另一个线程(线程向量),其中发生 recv 和发送。 这是实施:
bool CServerClientCommunication::OpenConnectionForClient(int Port)
{
long rc;
SOCKADDR_IN addr;
rc=StartWinsock();
if(rc!=0)
{
return false;
}
server=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(server==INVALID_SOCKET)
{
return false;
}
memset(&addr,0,sizeof(SOCKADDR_IN));
addr.sin_family=AF_INET;
addr.sin_port=htons(Port);
addr.sin_addr.s_addr=ADDR_ANY;
rc=bind(server,(SOCKADDR*)&addr,sizeof(SOCKADDR_IN));
if(rc==SOCKET_ERROR)
{
return false;
}
long rc2=listen(server,10);
if(rc2==SOCKET_ERROR)
{
return false;
}
WAIT_FOR_CLIENT:
if(Terminated)
{
return false;
}
// Accept Client to Serversocket
client=accept(server,NULL,NULL);
// Check if Accept failed
if(client==INVALID_SOCKET)
{
if( Clients.size()>0)
{
for (int i = 0; i < Clients.size(); i++)
{
if(Clients[i]->isKilled == true)
{
Clients[i]->Terminate();
Clients[i]->WaitFor();
delete Clients[i];
Clients[i] = NULL;
}
}
}
goto WAIT_FOR_CLIENT;
}
CServerClientProcessing * ServerClientProcessing = new CServerClientProcessing(true);
ServerClientProcessing->FreeOnTerminate = false;
Clients.push_back(ServerClientProcessing);
ServerClientProcessing->client = client;
Sleep(100);
if( Clients.size()>0)
{
for (int i = 0; i < Clients.size(); i++)
{
if(Clients[i]->isKilled == true)
{
Clients[i]->Terminate();
Clients[i]->WaitFor();
delete Clients[i];
Clients[i] = NULL;
}
}
}
ServerClientProcessing->Resume();
goto WAIT_FOR_CLIENT;
}
int CServerClientCommunication::StartWinsock()
{
WSADATA wsa;
return WSAStartup(MAKEWORD(2,0),&wsa);
}
bool CServerClientCommunication::GetConnectionStatus()
{
return server != -1;
}
//---------------------------------------------------------------------------
void __fastcall CServerClientCommunication::Execute()
{
int Port = PortProperties->ClientPort;
bool check=OpenConnectionForClient(Port);
}
我们在这里有一个线程向量,它执行recv和send(处理线程)。如果我们松开与客户端的通信,我们将bool isKilled设置为true,因此communicationthread可以在vector中终止此线程。 这是processingthread的实现:
void __fastcall CServerClientProcessing::Execute()
{
AnsiString Answer = "";
AnsiString CheckCase = "GetTemperature";
AnsiString CheckCase2 = "GetSetTemperature";
AnsiString ToSend = "";
AnsiString Error = "WRONG_ORDER";
AnsiString AllUp;
int ByteOffset = 0;
int Receive = 0;
int Send = 0;
char recvbuf[255];
while(!Terminated)
{
memset(recvbuf, 0x00, sizeof(recvbuf));
int StartTime = GetTickCount(); //100
ByteOffset = 0;
while(GetTickCount()-StartTime<1000 && !Terminated && isKilled == false)
{
// recv function to recieve information from server
// bitwise recieve information from client
Receive = recv(client,&recvbuf[ByteOffset],1,0);
// Receive > 0 true.
if (Receive > 0 )
{
// find last char \r and delete it
if(recvbuf[ByteOffset] == '\r')
{
recvbuf[ByteOffset] = '\0' ;
AnsiString temp = recvbuf;
AllUp = recvbuf;
AllUp=AllUp.UpperCase();
break;
}
ByteOffset++;
}
if (Receive < 0)
{
int value = WSAGetLastError();
if (value == 10054 || value == 10093)
{
isKilled = true;
closesocket(client);
break;
}
else
continue;
}
if (Receive = 0)
{
isKilled = true;
closesocket(client);
break;
}
}
// check content of receive
if(AllUp.Length()!= NULL)
{
CheckCase = CheckCase.UpperCase();
if(AllUp == CheckCase)
{
ToSend = FloatToStr(ConnectionThread->CurrentTemperature/10.0);
Answer = ToSend + "\r";
// copy information into buffer to send the answer client
memcpy(recvbuf,Answer.c_str(), Answer.Length());
}
CheckCase2 = CheckCase2.UpperCase();
if( AllUp == CheckCase2)
{
ToSend = FloatToStr(ConnectionThread->TemperatureLimit1/10.0);
Answer = ToSend + "\r";
// copy information into buffer to send the answer client
memcpy(recvbuf,Answer.c_str(), Answer.Length());
}
if( AllUp == CheckCase && AllUp == CheckCase2 )
{
Error = Error + "\r";
memcpy(recvbuf,Error.c_str(), Error.Length());
}
}
else
{
Error = Error + "\r";
memcpy(recvbuf,Error.c_str(), Error.Length());
}
// send answer(buffer) to client
Send = send( client, recvbuf, sizeof(recvbuf), 0 );
Sleep(1000);
// check if failed sending
if (Send == SOCKET_ERROR)
{
closesocket(client);
isKilled = true;
WSACleanup();
break;
}
}
}
一旦我打开一个客户端,一切正常。但是当我关闭客户端时,会发生不需要的事情:我无法连接另一个客户端而新客户端会死掉。此外,两个客户同时也是不可能的。
是否需要关键部分,还是结构的逻辑问题?我也因为删除了矢量而获得访问冲突,即使我检查它是否为空。
答案 0 :(得分:0)
我发现了错误:
这是一个糟糕的想法,因为我使用的是TCP_Socket,这可以实现安全的信息传输。所以我必须阅读这些信息。
而不是它,我找到\ r后分手了。消息的其余部分,大约有230个标志仍在流量中。
这就是它破坏连接的原因。我必须发送不是缓冲区的消息长度。