【发布时间】:2016-01-05 15:08:42
【问题描述】:
我是多线程新手,想设计服务器
这是我当前的代码:
typedef struct Session
{
HANDLE handlers[2];
//HANDLE h_Send;
//main session handler
HANDLE h_MainHandler;
HANDLE sema_MessageQ;
char* UserName;
SOCKET Socket;
PList MessageQ;
}Session,*pSession;
#define NUM_OF_WORKER_THREADS 5
#define MAX_LOOPS 5
#define SEND_STR_SIZE 256
static Session ClientSessions[NUM_OF_WORKER_THREADS];
void MainServer()
{
int Ind;
int Loop;
int bindRes;
int ListenRes;
unsigned long Address;
char SendStr[SEND_STR_SIZE];
SOCKET MainSocket = INVALID_SOCKET;
SOCKADDR_IN service;
XPacket Packet;
TransferResult_t RecvRes;
TransferResult_t SendRes;
//doing all the WSAStartup / bind / listen
//and error checkinh
// Initialize all thread handles to NULL, to mark that they have not been initialized
for ( Ind = 0; Ind < NUM_OF_WORKER_THREADS; Ind++ )
ClientSessions[Ind].h_MainHandler = NULL;
printf( "Waiting for a client to connect...\n" );
for ( Loop = 0; Loop < MAX_LOOPS; Loop++ )
{
SOCKET AcceptSocket = accept( MainSocket, NULL, NULL );
if ( AcceptSocket == INVALID_SOCKET )
{
printf( "Accepting connection with client failed, error %ld\n", WSAGetLastError());
goto server_cleanup_3;
}
printf( "Client Connected.\n" );
Ind = FindFirstUnusedThreadSlot();
if ( Ind == NUM_OF_WORKER_THREADS ) //no slot is available
{
printf( "No slots available for client, dropping the connection.\n" );
closesocket( AcceptSocket ); //Closing the socket, dropping the connection.
continue;
}
else
{
/*check that user name is not in use*/
char *AcceptedStr = NULL;
//get UserName
RecvRes = ReceivePacket(&Packet, AcceptSocket);
if ( RecvRes == TRNS_FAILED || RecvRes == TRNS_DISCONNECTED )
{
printf( "Service socket error while reading, closing socket.\n" );
closesocket( AcceptSocket );
continue;
}
if (FALSE == CheckForUsedName((char*)Packet.Data))
{
strcpy(SendStr ,(char*)Packet.Data);
strcpy( SendStr + strlen((char*)Packet.Data), " already taken!" );
SendRes = (TransferResult_t)PROTOCOL_SendCommand(
SendStr,
strlen(SendStr) + 1,
PROT_SERVER_RECEIVE_SYSTEM_MSG,
AcceptSocket);
closesocket(AcceptSocket);
continue;
}
printf("\r\nCode:%d Length:%lu Text:%s",Packet.Code,Packet.Length,(char*)Packet.Data);
ClientSessions[Ind].UserName = (char*)Packet.Data;
ClientSessions[Ind].Socket = AcceptSocket;
ClientSessions[Ind].h_MainHandler = CreateThread(
NULL,
0,
( LPTHREAD_START_ROUTINE ) ServiceThread,
&( ClientSessions[Ind]),
0,
NULL
);
}
} // for ( Loop = 0; Loop < MAX_LOOPS; Loop++ )
//~~~~~~~~server clean up~~~~~~~~~~~
server_cleanup_3:
CleanupWorkerThreads();
server_cleanup_2:
if ( closesocket( MainSocket ) == SOCKET_ERROR )
printf("Failed to close MainSocket, error %ld. Ending program\n", WSAGetLastError() );
server_cleanup_1:
if ( WSACleanup() == SOCKET_ERROR )
printf("Failed to close Winsocket, error %ld. Ending program.\n", WSAGetLastError() );
}
我当前的代码是在等待客户端断开连接之前等待客户端连接的数量 这显然不是很好 我想要的是某种形式
服务器:
{
//accept first client
\\while( InterlockedAdd(&number_of_connected_client , 0) >0 ) ?
while(number_of_connected_client > 0)
{
//wait for new client
}
//close server
}
每个客户会话:
{
//do somthing
//once finish
InterlockedDecrement(number_of_connected_client );
}
我的问题是如何实现不在spin-lock中的while()部分
【问题讨论】:
-
在我看来,您不应该在这里使用无锁方法。你只会以一场比赛告终。使用锁。通过该锁保护客户端的连接和断开连接。当客户端计数变为零时,发出终止信号。也许通过发出一个主线程阻塞的事件。当主线程检测到事件发出信号时,它会关闭。
-
@DavidHeffernan 我不确定我是否理解,您能否发布一些代码或链接到更完整的示例
-
我没有时间。你知道多线程中的事件是什么吗?
标签: c multithreading winapi client-server interlocked