我遇到了客户端服务器应用程序的一个特殊问题。 我编写了一个基于控制台的多线程客户端服务器。 多个客户端尝试发送和接收数千次。 当我运行多个客户端时,我的旧客户端停止发送接收数据和新客户端启动操作。 我无法理解为什么我的第一个客户端在我启动另一个客户端时被阻止。
这里我添加了一些代码。 这些是TCP操作。我刚才提到了关键功能。
bool LicTCPServer::Initialize()
{
m_socketAccept = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP );
if (m_socketAccept == INVALID_SOCKET)
return false;
int *p_int;
p_int = (int*)malloc(sizeof(int));
*p_int = 1;
if( (setsockopt(m_socketAccept, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int)) == -1 )||
(setsockopt(m_socketAccept, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int)) == -1 ) ){
printf("Error setting options %d\n", WSAGetLastError());
free(p_int);
}
free(p_int);
/*int iMode = 1;
ioctlsocket(m_socketAccept, FIONBIO, (u_long FAR*) &iMode);*/
SOCKADDR_IN oSockAddr;
::ZeroMemory(&oSockAddr, sizeof(SOCKADDR_IN));
oSockAddr.sin_family = AF_INET;
oSockAddr.sin_port = htons(m_wPortNoServer);
oSockAddr.sin_addr.s_addr = m_dwInetAddrServer;
int ret = bind(m_socketAccept, (const sockaddr*) &oSockAddr, sizeof(SOCKADDR_IN));
int error;
if (ret == SOCKET_ERROR)
{
closesocket(m_socketAccept);
error = WSAGetLastError();
return false;
}
error = listen(m_socketAccept, SOMAXCONN);
DWORD temp = GetLastError();
if (error == SOCKET_ERROR)
return false;
return true;
}
bool LicTCPServer::CheckConnection(struct sockaddr_in *clientAddress, SOCKET *sockValue)
{
//struct sockaddr_in clientAddress1;
int clientAddressLen = sizeof(struct sockaddr_in);
//struct sockaddr_in clientAddress; // Address of the client that sent data
SOCKET socket = accept(m_socketAccept, (struct sockaddr *)clientAddress, &clientAddressLen);
printf("Port - %d \n",clientAddress->sin_port);
//m_socketConnect = socket;
*sockValue = socket;
return true;
}
int LicTCPServer::ReceiveData(SOCKET socketNo, char* pszBuf, int & bufLen)
{
/*struct timeval tvTimeout;
tvTimeout.tv_sec = 0;
tvTimeout.tv_usec = (long) (10 * 1000);
fd_set fdSet;
FD_ZERO(&fdSet);
FD_SET(socketNo, &fdSet);
long lStatus = select(socketNo + 1, &fdSet, NULL, NULL, &tvTimeout);
if (lStatus <= 0)
{
FD_ZERO(&fdSet);
}
if (!FD_ISSET(socketNo, &fdSet))
{
return 0;
}*/
/*if (!CanReadOnBlockingSocket(socketNo))
{
return TELEGRAM_RECEIVE_ERROR;
}*/
bufLen = recv(socketNo, pszBuf, 10, 0);
if(bufLen == -1)
return WSAGetLastError();
else if(bufLen == 0)
{
closesocket(socketNo);
return -1;
}
else
return 0;
}
bool LicTCPServer::SendData(SOCKET socketNo, BYTE *puchBuf, int iBufLen)
{
int ret = send(socketNo, (char*)puchBuf, iBufLen,0);
//printf("Sent from server: %d %d\n\n",test2.a,test2.b);
return true;
}
这是我的main()函数:
void ClientServerCommunication(void *dummy);
struct informationToClient
{
LicTCPServer *serverFunctions;
SOCKET clientSocketNo;
}infoToClient;
int _tmain(int argc, _TCHAR* argv[])
{
DWORD dwInetAddrServer = inet_addr("127.0.0.1");
if(dwInetAddrServer == INADDR_NONE)
return 0;
WORD dwPortNumber = 2001;
LicTCPServer server(dwInetAddrServer, dwPortNumber);
server.Initialize();
struct sockaddr_in clientAddress;
SOCKET sockValue;
infoToClient.serverFunctions = &server;
while(1)
{
bool retValue = server.CheckConnection(&clientAddress, &sockValue);
if( sockValue == INVALID_SOCKET )
{
Sleep(10000);
continue;//or exit from thread
}
infoToClient.clientSocketNo = sockValue;
//retrieve client information from Make Connection and put it into LicenseClientData class
//Create thread for each client which will receive or send data
_beginthread(ClientServerCommunication, 0, (void *)&infoToClient);
//delete
}
return 0;
}
void ClientServerCommunication(void *dummy)
{
int iRetValue;
informationToClient *socketInfo = (informationToClient *)dummy;
char szBuf[10];
int iBufLen = 0;
while(1)
{
iRetValue = socketInfo->serverFunctions->ReceiveData(socketInfo->clientSocketNo, szBuf, iBufLen);
printf("Data received on socket %d %s\n", socketInfo->clientSocketNo, szBuf);
if(iRetValue == WSAECONNRESET)
{
_endthread();
}
socketInfo->serverFunctions->SendData(socketInfo->clientSocketNo, (BYTE*)szBuf, iBufLen);
printf("Data sent on socket %d %s\n", socketInfo->clientSocketNo, szBuf);
}
}
上面提到的所有代码都是测试代码。一旦工作正常,我必须在我的应用程序中使用LicTCPServer类。
答案 0 :(得分:0)
有许多可能的错误。
您的描述与将“连接”存储为全局变量一致,而不是为服务器上的每个线程提供自己的连接实例。
更新
快速浏览代码,infoToClient
是全球性的。