thread.cpp
上传用户:sycq158
上传日期:2008-10-22
资源大小:15361k
文件大小:10k
源码类别:

游戏

开发平台:

Visual C++

  1. #include <winsock2.h>
  2. #include <windows.h>
  3. #include "struct.h"
  4. #include "pool.h"
  5. #include "netmsg.h"
  6. HANDLE iocp;
  7. SOCKET slisten;
  8. int sport = 5500;
  9. CInordPool<OVERLAPPEDEX> olexPool;
  10. CInordPool<PLAYER> playerPool;
  11. GAMETABLE gTable;
  12. void Notice( int num, ... );
  13. void Notice( LPCTSTR head, int msgid );
  14. //-----------------------------------------------------------------------------
  15. // Name: 
  16. // Desc:
  17. //-----------------------------------------------------------------------------
  18. void WSAErrorTrigger( int error, LPCTSTR msg ) {
  19. switch (error)
  20. {
  21. case WSA_IO_PENDING:
  22. break;
  23. case WSAENOBUFS:
  24. // Notice(defstr,"No buffers!");
  25. break;
  26. case WSANOTINITIALISED:
  27. // Notice(defstr,"Need Startup()!");
  28. break;
  29. case WSAEINVAL:
  30. // Notice(defstr,"Call listen() first!");
  31. break;
  32. case WSAENOTSOCK:
  33. // Notice(defstr,"Not a socket!");
  34. break;
  35. default:;
  36. // Notice(defstr);
  37. }
  38. }
  39. //-----------------------------------------------------------------------------
  40. // Name: 
  41. // Desc:
  42. //-----------------------------------------------------------------------------
  43. bool InitServer()
  44. {
  45. WSADATA wsd;
  46. sockaddr_in local;
  47. // initiates use of Ws2_32.dll 
  48. if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
  49. return false;
  50. // create listening socket
  51. slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
  52.     if (slisten == SOCKET_ERROR) {
  53. WSACleanup();
  54.      return false;
  55. }
  56. // bind address and port
  57. local.sin_addr.s_addr = htonl(INADDR_ANY);
  58. local.sin_family   = AF_INET;
  59. local.sin_port   = htons(sport);
  60. if(bind(slisten,(struct sockaddr *)&local,
  61. sizeof(local)) == SOCKET_ERROR) {
  62. closesocket( slisten );
  63. WSACleanup();
  64. return false;
  65. }
  66. // set nonblock property
  67. // if(ioctlsocket(slisten,FIONBIO,&ul)== SOCKET_ERROR)
  68. // return false;
  69. // create iocp, and add listen socket on it
  70. iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
  71. if ( !iocp ) {
  72. closesocket( slisten );
  73. WSACleanup();
  74. return false;
  75. }
  76. // initialize pools
  77. if ( !olexPool.InitPool(0) || !playerPool.InitPool(16) ) {
  78. closesocket( slisten );
  79. WSACleanup();
  80. return false;
  81. }
  82. ZeroMemory( &gTable, sizeof(GAMETABLE) );
  83. // start listening
  84. if ( listen(slisten,SOMAXCONN) != 0 ) {
  85. closesocket( slisten );
  86. WSACleanup();
  87. return false;
  88. }
  89. Notice(1, "Server start successfully!");
  90. return true;
  91. }
  92. //-----------------------------------------------------------------------------
  93. // Name: 
  94. // Desc:
  95. //-----------------------------------------------------------------------------
  96. void TerminateServer() {
  97. closesocket( slisten );
  98. WSACleanup();
  99. }
  100. //-----------------------------------------------------------------------------
  101. // Name: 
  102. // Desc:
  103. //-----------------------------------------------------------------------------
  104. void RecvMsg( LPOVERLAPPEDEX lpolex ) 
  105. {
  106. DWORD flags = 0;
  107. lpolex->op = OP_READ;
  108. lpolex->wbuf.buf = lpolex->buf;
  109. lpolex->wbuf.len = DEFBUFFERSIZE;
  110. ZeroMemory(&(lpolex->ol),sizeof(OVERLAPPED));
  111. // int ret = 
  112. WSARecv((lpolex->socket),&(lpolex->wbuf),1,&(lpolex->bytes),
  113. &flags,&(lpolex->ol),NULL);
  114. // if ( ret == SOCKET_ERROR  ) {
  115. // ret = WSAGetLastError();
  116. // WSAErrorTrigger(ret, "RecvError:");
  117. // }
  118. }
  119. //-----------------------------------------------------------------------------
  120. // Name: 
  121. // Desc:
  122. //-----------------------------------------------------------------------------
  123. void SendMsg( int msg, SOCKET socket, LPVOID param, int size )
  124. {
  125. int length;
  126. int *ibuf;
  127. LPOVERLAPPEDEX lpolex = olexPool.GetUsable();
  128. ibuf = (int *)(lpolex->buf);
  129. ibuf[0] = msg;
  130. if( param ) {
  131. length = DEFBUFFERSIZE - sizeof(int)*2;
  132. if ( size < length )
  133. length = size;
  134. memcpy( &ibuf[2], param, length );
  135. else
  136. length = 0;
  137. ibuf[1] = length;
  138. lpolex->ppla = NULL;
  139. lpolex->socket = socket;
  140. lpolex->op = OP_WRITE;
  141. lpolex->wbuf.buf = lpolex->buf;
  142. lpolex->wbuf.len = length + sizeof(int)*2;
  143. ZeroMemory(&(lpolex->ol),sizeof(OVERLAPPED));
  144. // int ret = 
  145. WSASend(socket, &(lpolex->wbuf), 1, &(lpolex->bytes), 0,
  146. &(lpolex->ol), NULL );
  147. // if ( ret == SOCKET_ERROR  ) {
  148. // ret = WSAGetLastError();
  149. // WSAErrorTrigger(ret, "RecvError:");
  150. // }
  151. // !! DEBUG
  152. //Notice(temp);
  153. }
  154. //-----------------------------------------------------------------------------
  155. // Name: 
  156. // Desc:
  157. //-----------------------------------------------------------------------------
  158. void SendMsgToTable( int msg, GAMETABLE table, LPVOID param, int size ) {
  159. for ( int i=0; i<MAXPLAYER; i++ ) {
  160. if ( table.players[i] == NULL )
  161. break;
  162. SendMsg( msg, table.players[i]->socket, param, size );
  163. }
  164. }
  165. //-----------------------------------------------------------------------------
  166. // Name: 
  167. // Desc:
  168. //-----------------------------------------------------------------------------
  169. void SendMsgToOther( int msg, GAMETABLE table,int except, LPVOID param, int size ) {
  170. for ( int i=0; i<MAXPLAYER; i++ ) {
  171. if ( i != except && table.players[i] != NULL ) 
  172. SendMsg( msg, table.players[i]->socket, param, size );
  173. }
  174. }
  175. //-----------------------------------------------------------------------------
  176. // Name: 
  177. // Desc:
  178. //-----------------------------------------------------------------------------
  179. DWORD WINAPI AcceptThread( LPVOID pParam ) {
  180. sockaddr_in client;
  181. int size;
  182. SOCKET ret;
  183. OVERLAPPEDEX *lpolex;
  184. while(true) {
  185. size = sizeof(sockaddr_in);
  186. ret = accept(slisten,(sockaddr *)&client,&size);
  187. if(ret != INVALID_SOCKET)
  188. {
  189. Notice(2, "Connect:", inet_ntoa(client.sin_addr));
  190. lpolex = olexPool.GetUsable();
  191. if ( lpolex )
  192. {
  193. CreateIoCompletionPort((HANDLE)ret, iocp, NULL, 0);
  194. // initiate communication
  195. lpolex->socket = ret;
  196. RecvMsg( lpolex );
  197. else {
  198. closesocket( ret );
  199. // Notice(2, "NULLOLEX:", inet_ntoa(client.sin_addr));
  200. }
  201. else { // accept error
  202. ret = WSAGetLastError();
  203. WSAErrorTrigger(ret, TEXT("AcceptErr: "));
  204. }
  205. }
  206. return 0;
  207. }
  208. //-----------------------------------------------------------------------------
  209. // Name: 
  210. // Desc:
  211. //-----------------------------------------------------------------------------
  212. DWORD WINAPI WorkerThread(LPVOID pParam) {
  213. ULONG_PTR ckey;
  214. OVERLAPPED *pol;
  215.     OVERLAPPEDEX *polex;
  216. // LPGAMETABLE ptable;
  217.     DWORD           BytesTransferred;
  218. int ret;
  219. int *ibuf;
  220. while(true) {
  221. ret = GetQueuedCompletionStatus(iocp, &BytesTransferred,
  222. &ckey,&pol,INFINITE);
  223. // structure-hack-a-roo
  224. polex = CONTAINING_RECORD(pol, OVERLAPPEDEX, ol);
  225. // Operation failed
  226. if ( ret == 0) {
  227. // May a remote player has been disconnected.
  228. int size = sizeof(sockaddr_in);
  229. sockaddr_in client;
  230. getpeername(polex->socket,(sockaddr *)&client,&size);
  231. Notice(2, "Discont:", inet_ntoa(client.sin_addr));
  232. // remove the seat
  233. for ( int i=0; i<gTable.current; i++ ) {
  234. if ( gTable.players[i] == polex->ppla ) {
  235. if ( i > 0 )
  236. gTable.players[i-1]->next = polex->ppla->next;
  237. break;
  238. }
  239. }
  240. for ( ; i<gTable.current-1; i++ )
  241. gTable.players[i] = gTable.players[i+1];
  242. gTable.current--;
  243. // Pool recycle
  244. playerPool.Recycle( polex->ppla );
  245. olexPool.Recycle( polex );
  246. continue;
  247. }
  248. // Operation succeeded
  249. switch (polex->op) {
  250. case OP_READ:
  251. ibuf = (int *)(polex->wbuf.buf);
  252. switch ( ibuf[0] ) {
  253. // allocate a player seat and a table
  254. case NETMSGTK_ASKGROUPINFO:
  255. Notice( "AskGroup: ", ibuf[2] );
  256. polex->ppla = playerPool.GetUsable();
  257. polex->ppla->seat = gTable.current;
  258. gTable.players[gTable.current] = polex->ppla;
  259. gTable.players[gTable.current]->socket = polex->socket;
  260. SendMsg( NETMSGTK_ANSWERSEATINFO, polex->socket, 
  261. &gTable.current, sizeof(int) );
  262. Notice( "AnswerSeat: ", gTable.current );
  263. // set list pointer
  264. polex->ppla->next = NULL;
  265. if ( gTable.current > 0 ) {
  266. gTable.players[gTable.current-1]->next = polex->ppla;
  267. SendMsgToOther( NETMSGTK_MOREPLAYER, gTable, gTable.current,
  268. &gTable.current, sizeof(int) );
  269. }
  270. if ( ++gTable.current == MAXPLAYER )
  271. SendMsgToTable( NETMSGTK_GAMEREADY, gTable, NULL, 0 );
  272. break;
  273. case NETMSGTK_PLAYERREADY:
  274. if ( ++gTable.counter == MAXPLAYER ) {
  275. SendMsgToTable( NETMSGTK_GAMESTART, gTable, NULL, 0 );
  276. // initialize table's food creator
  277. gTable.food.exsit = false;
  278. gTable.food.existnum = DEFFOODEXFRAME;
  279. gTable.food.notexistnum = DEFFOODNOTEXFRAME;
  280. gTable.food.counter = DEFFOODNOTEXFRAME;
  281. // reset table counter
  282. gTable.counter = 0;
  283. }
  284. break;
  285. case NETMSGTK_CMDINFO:
  286. if ( gTable.food.counter-- <= 0 ) {
  287. if ( gTable.food.exsit ) { // delete
  288. gTable.food.counter = gTable.food.notexistnum;
  289. SendMsgToTable( NETMSGTK_CMDFOODDELETE, gTable, NULL, 0 );
  290. } else { // create
  291. gTable.food.counter = gTable.food.existnum;
  292. int foodparam[3];
  293. foodparam[0] = rand() % FOOD_MAX;
  294. foodparam[1] = rand() % 608; // !TODO: CONVERT with different sizes
  295. foodparam[2] = rand() % 608;
  296. SendMsgToTable( NETMSGTK_CMDFOODCREATE, gTable, foodparam, sizeof(int)*3 );
  297. }
  298. gTable.food.exsit = !gTable.food.exsit;
  299. }
  300. // 
  301. SendMsgToOther( NETMSGTK_CMDINFO, gTable, polex->ppla->seat, ibuf+2, ibuf[1] );
  302. break;
  303. case NETMSGTK_TEAMVICTORY:
  304. // Notice( "Victory: ", ibuf[2] );
  305. SendMsgToTable( NETMSGTK_TEAMVICTORY, gTable, ibuf+2, ibuf[1] );
  306. break;
  307. }
  308. // Notice(2, "RecvMsg: ", polex->wbuf.buf+8);
  309. RecvMsg( polex );
  310. break;
  311. case OP_WRITE:
  312. // Recycle
  313. olexPool.Recycle( polex );
  314. break;
  315. }
  316. }
  317. return 0;
  318. }