📄 thread.cpp
字号:
#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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -