thread.cpp
上传用户:sycq158
上传日期:2008-10-22
资源大小:15361k
文件大小:10k
- #include <winsock2.h>
- #include <windows.h>
- #include "struct.h"
- #include "pool.h"
- #include "netmsg.h"
- HANDLE iocp;
- SOCKET slisten;
- int sport = 5500;
- CInordPool<OVERLAPPEDEX> olexPool;
- CInordPool<PLAYER> playerPool;
- GAMETABLE gTable;
- void Notice( int num, ... );
- void Notice( LPCTSTR head, int msgid );
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- void WSAErrorTrigger( int error, LPCTSTR msg ) {
- switch (error)
- {
- case WSA_IO_PENDING:
- break;
- case WSAENOBUFS:
- // Notice(defstr,"No buffers!");
- break;
- case WSANOTINITIALISED:
- // Notice(defstr,"Need Startup()!");
- break;
- case WSAEINVAL:
- // Notice(defstr,"Call listen() first!");
- break;
- case WSAENOTSOCK:
- // Notice(defstr,"Not a socket!");
- break;
- default:;
- // Notice(defstr);
- }
- }
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- bool InitServer()
- {
- WSADATA wsd;
- sockaddr_in local;
- // initiates use of Ws2_32.dll
- if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
- return false;
- // create listening socket
- slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
- if (slisten == SOCKET_ERROR) {
- WSACleanup();
- return false;
- }
- // bind address and port
- local.sin_addr.s_addr = htonl(INADDR_ANY);
- local.sin_family = AF_INET;
- local.sin_port = htons(sport);
- if(bind(slisten,(struct sockaddr *)&local,
- sizeof(local)) == SOCKET_ERROR) {
- closesocket( slisten );
- WSACleanup();
- return false;
- }
-
- // set nonblock property
- // if(ioctlsocket(slisten,FIONBIO,&ul)== SOCKET_ERROR)
- // return false;
- // create iocp, and add listen socket on it
- iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
- if ( !iocp ) {
- closesocket( slisten );
- WSACleanup();
- return false;
- }
- // initialize pools
- if ( !olexPool.InitPool(0) || !playerPool.InitPool(16) ) {
- closesocket( slisten );
- WSACleanup();
- return false;
- }
- ZeroMemory( &gTable, sizeof(GAMETABLE) );
- // start listening
- if ( listen(slisten,SOMAXCONN) != 0 ) {
- closesocket( slisten );
- WSACleanup();
- return false;
- }
- Notice(1, "Server start successfully!");
- return true;
- }
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- void TerminateServer() {
- closesocket( slisten );
- WSACleanup();
- }
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- void RecvMsg( LPOVERLAPPEDEX lpolex )
- {
- DWORD flags = 0;
- lpolex->op = OP_READ;
- lpolex->wbuf.buf = lpolex->buf;
- lpolex->wbuf.len = DEFBUFFERSIZE;
- ZeroMemory(&(lpolex->ol),sizeof(OVERLAPPED));
- // int ret =
- WSARecv((lpolex->socket),&(lpolex->wbuf),1,&(lpolex->bytes),
- &flags,&(lpolex->ol),NULL);
- // if ( ret == SOCKET_ERROR ) {
- // ret = WSAGetLastError();
- // WSAErrorTrigger(ret, "RecvError:");
- // }
- }
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- void SendMsg( int msg, SOCKET socket, LPVOID param, int size )
- {
- int length;
- int *ibuf;
- LPOVERLAPPEDEX lpolex = olexPool.GetUsable();
- ibuf = (int *)(lpolex->buf);
- ibuf[0] = msg;
- if( param ) {
- length = DEFBUFFERSIZE - sizeof(int)*2;
- if ( size < length )
- length = size;
- memcpy( &ibuf[2], param, length );
- }
- else
- length = 0;
- ibuf[1] = length;
- lpolex->ppla = NULL;
- lpolex->socket = socket;
- lpolex->op = OP_WRITE;
- lpolex->wbuf.buf = lpolex->buf;
- lpolex->wbuf.len = length + sizeof(int)*2;
- ZeroMemory(&(lpolex->ol),sizeof(OVERLAPPED));
- // int ret =
- WSASend(socket, &(lpolex->wbuf), 1, &(lpolex->bytes), 0,
- &(lpolex->ol), NULL );
- // if ( ret == SOCKET_ERROR ) {
- // ret = WSAGetLastError();
- // WSAErrorTrigger(ret, "RecvError:");
- // }
- // !! DEBUG
- //Notice(temp);
- }
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- void SendMsgToTable( int msg, GAMETABLE table, LPVOID param, int size ) {
- for ( int i=0; i<MAXPLAYER; i++ ) {
- if ( table.players[i] == NULL )
- break;
- SendMsg( msg, table.players[i]->socket, param, size );
- }
- }
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- void SendMsgToOther( int msg, GAMETABLE table,int except, LPVOID param, int size ) {
- for ( int i=0; i<MAXPLAYER; i++ ) {
- if ( i != except && table.players[i] != NULL )
- SendMsg( msg, table.players[i]->socket, param, size );
- }
- }
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- DWORD WINAPI AcceptThread( LPVOID pParam ) {
- sockaddr_in client;
- int size;
- SOCKET ret;
- OVERLAPPEDEX *lpolex;
-
- while(true) {
- size = sizeof(sockaddr_in);
- ret = accept(slisten,(sockaddr *)&client,&size);
- if(ret != INVALID_SOCKET)
- {
- Notice(2, "Connect:", inet_ntoa(client.sin_addr));
- lpolex = olexPool.GetUsable();
- if ( lpolex )
- {
- CreateIoCompletionPort((HANDLE)ret, iocp, NULL, 0);
- // initiate communication
- lpolex->socket = ret;
- RecvMsg( lpolex );
- }
- else {
- closesocket( ret );
- // Notice(2, "NULLOLEX:", inet_ntoa(client.sin_addr));
- }
- }
- else { // accept error
- ret = WSAGetLastError();
- WSAErrorTrigger(ret, TEXT("AcceptErr: "));
- }
- }
- return 0;
- }
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- DWORD WINAPI WorkerThread(LPVOID pParam) {
- ULONG_PTR ckey;
- OVERLAPPED *pol;
- OVERLAPPEDEX *polex;
- // LPGAMETABLE ptable;
- DWORD BytesTransferred;
- int ret;
- int *ibuf;
- while(true) {
- ret = GetQueuedCompletionStatus(iocp, &BytesTransferred,
- &ckey,&pol,INFINITE);
- // structure-hack-a-roo
- polex = CONTAINING_RECORD(pol, OVERLAPPEDEX, ol);
- // Operation failed
- if ( ret == 0) {
- // May a remote player has been disconnected.
- int size = sizeof(sockaddr_in);
- sockaddr_in client;
- getpeername(polex->socket,(sockaddr *)&client,&size);
- Notice(2, "Discont:", inet_ntoa(client.sin_addr));
-
- // remove the seat
- for ( int i=0; i<gTable.current; i++ ) {
- if ( gTable.players[i] == polex->ppla ) {
- if ( i > 0 )
- gTable.players[i-1]->next = polex->ppla->next;
- break;
- }
- }
- for ( ; i<gTable.current-1; i++ )
- gTable.players[i] = gTable.players[i+1];
- gTable.current--;
- // Pool recycle
- playerPool.Recycle( polex->ppla );
- olexPool.Recycle( polex );
- continue;
- }
- // Operation succeeded
- switch (polex->op) {
- case OP_READ:
- ibuf = (int *)(polex->wbuf.buf);
- switch ( ibuf[0] ) {
- // allocate a player seat and a table
- case NETMSGTK_ASKGROUPINFO:
- Notice( "AskGroup: ", ibuf[2] );
- polex->ppla = playerPool.GetUsable();
- polex->ppla->seat = gTable.current;
- gTable.players[gTable.current] = polex->ppla;
- gTable.players[gTable.current]->socket = polex->socket;
- SendMsg( NETMSGTK_ANSWERSEATINFO, polex->socket,
- &gTable.current, sizeof(int) );
- Notice( "AnswerSeat: ", gTable.current );
- // set list pointer
- polex->ppla->next = NULL;
- if ( gTable.current > 0 ) {
- gTable.players[gTable.current-1]->next = polex->ppla;
- SendMsgToOther( NETMSGTK_MOREPLAYER, gTable, gTable.current,
- &gTable.current, sizeof(int) );
- }
-
- if ( ++gTable.current == MAXPLAYER )
- SendMsgToTable( NETMSGTK_GAMEREADY, gTable, NULL, 0 );
- break;
- case NETMSGTK_PLAYERREADY:
- if ( ++gTable.counter == MAXPLAYER ) {
- SendMsgToTable( NETMSGTK_GAMESTART, gTable, NULL, 0 );
- // initialize table's food creator
- gTable.food.exsit = false;
- gTable.food.existnum = DEFFOODEXFRAME;
- gTable.food.notexistnum = DEFFOODNOTEXFRAME;
- gTable.food.counter = DEFFOODNOTEXFRAME;
- // reset table counter
- gTable.counter = 0;
- }
- break;
- case NETMSGTK_CMDINFO:
- if ( gTable.food.counter-- <= 0 ) {
- if ( gTable.food.exsit ) { // delete
- gTable.food.counter = gTable.food.notexistnum;
- SendMsgToTable( NETMSGTK_CMDFOODDELETE, gTable, NULL, 0 );
- } else { // create
- gTable.food.counter = gTable.food.existnum;
- int foodparam[3];
- foodparam[0] = rand() % FOOD_MAX;
- foodparam[1] = rand() % 608; // !TODO: CONVERT with different sizes
- foodparam[2] = rand() % 608;
- SendMsgToTable( NETMSGTK_CMDFOODCREATE, gTable, foodparam, sizeof(int)*3 );
- }
- gTable.food.exsit = !gTable.food.exsit;
- }
- //
- SendMsgToOther( NETMSGTK_CMDINFO, gTable, polex->ppla->seat, ibuf+2, ibuf[1] );
- break;
- case NETMSGTK_TEAMVICTORY:
- // Notice( "Victory: ", ibuf[2] );
- SendMsgToTable( NETMSGTK_TEAMVICTORY, gTable, ibuf+2, ibuf[1] );
- break;
- }
- // Notice(2, "RecvMsg: ", polex->wbuf.buf+8);
- RecvMsg( polex );
- break;
- case OP_WRITE:
- // Recycle
- olexPool.Recycle( polex );
- break;
- }
- }
- return 0;
- }