Exemple #1
0
void CGateInfo::ProcSelectServer(SOCKET s, WORD wServerIndex)
{
    _TDEFAULTMESSAGE	DefMsg;
    char				szEncodePacket[128];
    char				szEncodeAllPacket[256];
    char				szEncodeMsg[24];
    char				*pServerIP;
    GAMESERVERINFO		*pServerInfo;

    PLISTNODE pListNode = xUserInfoList.GetHead();

    while (pListNode)
    {
        CUserInfo *pUserInfo = xUserInfoList.GetData(pListNode);

        if (pUserInfo->sock == s)
        {
            if (!pUserInfo->fSelServerOk)
            {
                fnMakeDefMessageA(&DefMsg, SM_SELECTSERVER_OK, 0, pUserInfo->nCertification, 0, 0);
                int nPos = fnEncodeMessageA(&DefMsg, szEncodeMsg, sizeof(szEncodePacket));
                szEncodeMsg[nPos] = '\0';

                for ( PLISTNODE pNode = g_xGameServerList.GetHead(); pNode; pNode = g_xGameServerList.GetNext( pNode ) )
                {
                    pServerInfo = g_xGameServerList.GetData( pNode );

                    if ( pServerInfo->index == wServerIndex )
                    {
                        pServerIP = pServerInfo->ip;
                        pServerInfo->connCnt++;
                        break;
                    }
                }

                if ( !pServerIP )
                    break;

                pUserInfo->nServerID = wServerIndex;

                int nPos2 = fnEncode6BitBufA((unsigned char *)pServerIP, szEncodePacket, memlen(pServerIP), sizeof(szEncodePacket));
                szEncodePacket[nPos2] = '\0';

                memmove(szEncodeAllPacket, szEncodeMsg, nPos);
                memmove(&szEncodeAllPacket[nPos], szEncodePacket, nPos2);
                szEncodeAllPacket[nPos + nPos2] = '\0';

                SendToGate(s, szEncodeAllPacket);

                pUserInfo->fSelServerOk = TRUE;

                pListNode = xUserInfoList.RemoveNode(pListNode);
            }
        }
        else
            pListNode = xUserInfoList.GetNext(pListNode);
    }
}
Exemple #2
0
UINT WINAPI LoadAccountRecords(LPVOID lpParameter)
{
	//InsertLogMsg(IDS_LOADACCOUNTRECORDS);


	//下面这一段是获取服务器相关消息的,暂时屏蔽掉
	//CRecordset *pRec = GetDBManager()->CreateRecordset();
	//pRec->Execute( "UPDATE TBL_ACCOUNT SET FLD_CERTIFICATION=0 WHERE FLD_CERTIFICATION >= 30" );
	//GetDBManager()->DestroyRecordset( pRec );
	//// ----------------------------------------------------------------------------------------

	//GAMESERVERINFO *pServerInfo;

	//pRec = GetDBManager()->CreateRecordset();
	//if ( pRec->Execute( "SELECT * FROM TBL_SERVERINFO" ) )
	//{
	//	while ( pRec->Fetch() )
	//	{			
	//		pServerInfo = new GAMESERVERINFO;
	//		if ( !pServerInfo )
	//			break;

	//		pServerInfo->index = atoi( pRec->Get( "FLD_SERVERIDX" ) );
	//		strcpy( pServerInfo->name, pRec->Get( "FLD_SERVERNAME" ) );
	//		strcpy( pServerInfo->ip,   pRec->Get( "FLD_SERVERIP" ) );
	//		pServerInfo->connCnt = 0;

	//		g_xGameServerList.AddNewNode( pServerInfo );
	//	}
	//}
	//GetDBManager()->DestroyRecordset( pRec );

	GAMESERVERINFO *pServerInfo;
	char szTmp[64];
	for ( PLISTNODE pNode = g_xGameServerList.GetHead(); pNode; pNode = g_xGameServerList.GetNext( pNode ) )
	{
		pServerInfo = g_xGameServerList.GetData( pNode );
		
		sprintf( szTmp, "%d,%s,", pServerInfo->index, pServerInfo->name );
		strcat( g_szServerList, szTmp );
	}
	// ----------------------------------------------------------------------------------------

	InitServerThreadForMsg();

	if (InitServerSocket(g_gcSock, &g_gcAddr, _IDM_GATECOMMSOCK_MSG, 5500, 1))
		SwitchMenuItem(TRUE);

	return 0L;
}
Exemple #3
0
void LoadCharacterRecords()
{
	InsertLogMsg(IDS_LOADACCOUNTRECORDS);

	CRecordset *pRec = GetDBManager()->CreateRecordset();
	if ( pRec->Execute( "SELECT * FROM TBL_GAMEGATEINFO" ) )
	{
		GAMESERVERINFO *pServerInfo;

		while ( pRec->Fetch() )
		{
			pServerInfo = new GAMESERVERINFO;
			if ( !pServerInfo )
				break;

			pServerInfo->index = atoi( pRec->Get( "FLD_SERVERIDX" ) );
			strcpy( pServerInfo->name, pRec->Get( "FLD_SERVERNAME" ) );
			strcpy( pServerInfo->ip,   pRec->Get( "FLD_SERVERIP" ) );
			pServerInfo->connCnt = 0;

			g_xGameServerList.AddNewNode( pServerInfo );
		}
	}
	GetDBManager()->DestroyRecordset( pRec );
}
//UINT WINAPI AcceptThread(LPVOID lpParameter)
DWORD WINAPI AcceptThread(LPVOID lpParameter)
{
	int							nLen = sizeof(SOCKADDR_IN);
	char						szMsg[64];

	SOCKET						Accept;
	SOCKADDR_IN					Address;

	while (TRUE)
	{
		Accept = accept(g_ssock, (struct sockaddr FAR *)&Address, &nLen);

		if (g_fTerminated)
			return 0;

		CSessionInfo* pNewUserInfo = (CSessionInfo*)GlobalAlloc(GPTR, sizeof(CSessionInfo));

		if (pNewUserInfo)
		{
			pNewUserInfo->sock				= Accept;

			CreateIoCompletionPort((HANDLE)pNewUserInfo->sock, g_hIOCP, (DWORD)pNewUserInfo, 0);

			if (g_xSessionList.AddNewNode(pNewUserInfo))
			{
				int zero = 0;
				
				setsockopt(pNewUserInfo->sock, SOL_SOCKET, SO_SNDBUF, (char *)&zero, sizeof(zero) );

				// ORZ:
				pNewUserInfo->Recv();

				UpdateStatusBar(TRUE);

				szMsg[0] = '%';
				szMsg[1] = 'O';

				char *pszPos = ValToAnsiStr((int)Accept, &szMsg[2]);
				
				*pszPos++ = '/';

				pszPos = ValToAnsiStr((int)Address.sin_addr.s_net, pszPos);
				*pszPos++ = '.';
				pszPos = ValToAnsiStr((int)Address.sin_addr.s_host, pszPos);
				*pszPos++ = '.';
				pszPos = ValToAnsiStr((int)Address.sin_addr.s_lh, pszPos);
				*pszPos++ = '.';
				pszPos = ValToAnsiStr((int)Address.sin_addr.s_impno, pszPos);

				*pszPos++	= '$';
				*pszPos		= '\0';

				SendExToServer(szMsg);
			}
		}
	}

	return 0;
}
Exemple #5
0
DWORD WINAPI AcceptThread(LPVOID lpParameter)
{
	int					nLen = sizeof(SOCKADDR_IN);

	SOCKET				Accept;
	SOCKADDR_IN			Address;

	DWORD				dwRecvBytes;
	DWORD				dwFlags;

	TCHAR				szGateIP[16];

	while (TRUE)
	{
		Accept = accept(g_ssock, (struct sockaddr FAR *)&Address, &nLen);

		if (g_fTerminated) return 0L;

		CServerInfo* pServerInfo = (CServerInfo*)GlobalAlloc(GPTR, sizeof(CServerInfo));

		if (pServerInfo)
		{
			pServerInfo->m_sock	= Accept;

			CreateIoCompletionPort((HANDLE)pServerInfo->m_sock, g_hIOCP, (DWORD)pServerInfo, 0);

			if (g_xServerList.AddNewNode(pServerInfo))
			{
				int zero = 0;
				
				setsockopt(pServerInfo->m_sock, SOL_SOCKET, SO_SNDBUF, (char *)&zero, sizeof(zero));

				ZeroMemory(&(pServerInfo->Overlapped), sizeof(OVERLAPPED));

				pServerInfo->DataBuf.len	= DATA_BUFSIZE;
				pServerInfo->DataBuf.buf	= pServerInfo->Buffer;
				pServerInfo->nOvFlag		= OVERLAPPED_RECV;

				dwFlags = 0;

				WSARecv(pServerInfo->m_sock, &(pServerInfo->DataBuf), 1, &dwRecvBytes, &dwFlags, &(pServerInfo->Overlapped), NULL);

				UpdateStatusBarSession(TRUE);

				_stprintf(szGateIP, _T("%d.%d.%d.%d"), Address.sin_addr.s_net, Address.sin_addr.s_host, 
															Address.sin_addr.s_lh, Address.sin_addr.s_impno);

				InsertLogMsgParam(IDS_ACCEPT_GATESERVER, szGateIP, LOGPARAM_STR);
			}
		}
	}

	return 0;
}
Exemple #6
0
UINT WINAPI LoadAccountRecords(LPVOID lpParameter)
{
	//获取服务器列表的
	GAMESERVERINFO *pServerInfo;
	char szTmp[64];
	for ( PLISTNODE pNode = g_xGameServerList.GetHead(); pNode; pNode = g_xGameServerList.GetNext( pNode ) )
	{
		pServerInfo = g_xGameServerList.GetData( pNode );
		
		sprintf( szTmp, "%d,%s,", pServerInfo->index, pServerInfo->name );
		strcat( g_szServerList, szTmp );
	}
	// ----------------------------------------------------------------------------------------

	//服务器线程
	InitServerThreadForMsg();

	ENGINE_COMPONENT_INFO info = g_SeverConfig.getLoginSrvInfo();

	if (InitServerSocket(g_gcSock, &g_gcAddr, _IDM_GATECOMMSOCK_MSG, info.intport?info.intport:5500, 1))
		SwitchMenuItem(TRUE);

	return 0L;
}
Exemple #7
0
DWORD WINAPI AcceptThread(LPVOID lpParameter)
{
    int					nLen = sizeof(SOCKADDR_IN);

    SOCKET				Accept;
    SOCKADDR_IN			Address;

    while (TRUE)
    {
        Accept = accept(g_gcSock, (struct sockaddr FAR *)&Address, &nLen);

        if (g_fTerminated)
            return 0;

        CGateInfo* pGateInfo = new CGateInfo;

        if (pGateInfo)
        {
            pGateInfo->sock = Accept;

            CreateIoCompletionPort((HANDLE)pGateInfo->sock, g_hIOCP, (DWORD)pGateInfo, 0);

            if (g_xGateList.AddNewNode(pGateInfo))
            {
                int zero = 0;

                setsockopt(pGateInfo->sock, SOL_SOCKET, SO_SNDBUF, (char *)&zero, sizeof(zero) );

                pGateInfo->Recv();

                UpdateStatusBar(TRUE);

#ifdef _DEBUG
                TCHAR szGateIP[256];
                wsprintf(szGateIP, _T("%d.%d.%d.%d"), Address.sin_addr.s_net, Address.sin_addr.s_host,
                         Address.sin_addr.s_lh, Address.sin_addr.s_impno);

                InsertLogMsgParam(IDS_ACCEPT_GATESERVER, szGateIP);
#endif
            }
        }
    }

    return 0;
}
UINT WINAPI ThreadFuncForMsg(LPVOID lpParameter)
{
	_TDEFAULTMESSAGE	DefaultMsg;
	char				*pszBegin, *pszEnd;
	int					nCount;
	PLISTNODE			pListNode;
	CGateInfo*			pGateInfo;

	while (TRUE)
	{
		if (g_xGateList.GetCount())
		{
			pListNode = g_xGateList.GetHead();

			while (pListNode)
			{
				pGateInfo = g_xGateList.GetData(pListNode);

				if (pGateInfo)
				{
					nCount = pGateInfo->g_SendToGateQ.GetCount();

					if (nCount)
					{
						for (int nLoop = 0; nLoop < nCount; nLoop++)
						{
							_LPTSENDBUFF pSendBuff = (_LPTSENDBUFF)pGateInfo->g_SendToGateQ.PopQ();

							if (pSendBuff)
							{
								int nLen = memlen(pSendBuff->szData);

								if ((pszBegin = (char *)memchr(pSendBuff->szData, '#', nLen)) &&(pszEnd = (char *)memchr(pSendBuff->szData, '!', nLen)))
								{
									*pszEnd = '\0';

									fnDecodeMessageA(&DefaultMsg, (pszBegin + 2));	// 2 = "#?" ? = Check Code 

									switch (DefaultMsg.wIdent)
									{
										case CM_PROTOCOL:
											break;
										case CM_IDPASSWORD:
											pGateInfo->ProcLogin(pSendBuff->sock, pszBegin + DEFBLOCKSIZE + 2);
											break;
										case CM_SELECTSERVER:
											pGateInfo->ProcSelectServer(pSendBuff->sock, DefaultMsg.wParam);
											break;
										case CM_ADDNEWUSER:
											pGateInfo->ProcAddUser(pSendBuff->sock, pszBegin + DEFBLOCKSIZE + 2);
											break;
										case CM_UPDATEUSER:
											break;
										case CM_CHANGEPASSWORD:
											break;
									}
								}

								delete pSendBuff;
								pSendBuff = NULL;
							}
						}
					}
				}

				pListNode = g_xGateList.GetNext(pListNode);
			}
		}

		SleepEx(1, TRUE);	
	}

	return 0;
}
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
	DWORD					dwBytesTransferred = 0;

	CSessionInfo*			pSessionInfo = NULL;
	_LPTCOMPLETIONPORT		lpPerIoData = NULL;

	char					szPacket[DATA_BUFSIZE * 2];
	char					szMsg[32];
	char					*pszPos;

	while (TRUE)
	{
		if ( GetQueuedCompletionStatus( 
										(HANDLE)CompletionPortID, 
										&dwBytesTransferred, 
										(LPDWORD)&pSessionInfo, 										
										(LPOVERLAPPED *)&lpPerIoData, 
										INFINITE) == 0)
		{
			if (g_fTerminated)
				return 0;

			if (pSessionInfo)
			{
				szMsg[0] = '%';
				szMsg[1] = 'X';

				char *pszPos = ValToAnsiStr((int)pSessionInfo->sock, &szMsg[2]);

				*pszPos++	= '$';
				*pszPos		= '\0';

				SendExToServer(szMsg); 

				g_xSessionList.RemoveNodeByData(pSessionInfo);

				closesocket(pSessionInfo->sock);
				pSessionInfo->sock = INVALID_SOCKET;

				UpdateStatusBar(FALSE);

				GlobalFree(pSessionInfo);
			}

			continue;
		}

		if (g_fTerminated)
			return 0;

		if (dwBytesTransferred == 0)
		{
			szMsg[0] = '%';
			szMsg[1] = 'X';

			char *pszPos = ValToAnsiStr((int)pSessionInfo->sock, &szMsg[2]);

			*pszPos++	= '$';
			*pszPos		= '\0';

			SendExToServer(szMsg); 

			g_xSessionList.RemoveNodeByData(pSessionInfo);

			closesocket(pSessionInfo->sock);
			pSessionInfo->sock = INVALID_SOCKET;

			UpdateStatusBar(FALSE);

			GlobalFree(pSessionInfo);

			continue;
		}


		// ORZ:
		pSessionInfo->bufLen += dwBytesTransferred;

		while ( pSessionInfo->HasCompletionPacket() )
		{
			szPacket[0]	= '%';
			szPacket[1]	= 'A';
			pszPos		= ValToAnsiStr( (int) pSessionInfo->sock, &szPacket[2] );
			*pszPos++	= '/';
			pszPos		= pSessionInfo->ExtractPacket( pszPos );
			*pszPos++	= '$';
			*pszPos		= '\0';

			SendExToServer( szPacket );
		}

		// ORZ:
		if ( pSessionInfo->Recv() == SOCKET_ERROR && WSAGetLastError() != ERROR_IO_PENDING )
		{
				InsertLogMsg(_TEXT("WSARecv() failed"));
			
				CloseSession(pSessionInfo->sock);
				continue;
		}
	}

	return 0;
}
Exemple #10
0
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
    DWORD					dwBytesTransferred = 0;
    CGateInfo*				pGateInfo = NULL;
    LPOVERLAPPED			lpOverlapped = NULL;
    char					szTmp[DATA_BUFSIZE];

    while (TRUE)
    {
        if ( GetQueuedCompletionStatus(
                    (HANDLE)CompletionPortID,
                    &dwBytesTransferred,
                    (LPDWORD)&pGateInfo,
                    (LPOVERLAPPED *)&lpOverlapped,
                    INFINITE) == 0 )
        {
            return 0;
        }

        if (g_fTerminated)
        {
            PLISTNODE		pListNode;

            if (g_xGateList.GetCount())
            {
                pListNode = g_xGateList.GetHead();

                while (pListNode)
                {
                    pGateInfo = g_xGateList.GetData(pListNode);

                    if (pGateInfo)
                        pGateInfo->Close();

                    delete pGateInfo;
                    pGateInfo = NULL;

                    pListNode = g_xGateList.RemoveNode(pListNode);
                }
            }

            return 0;
        }

        if ( dwBytesTransferred == 0 )
        {
            pGateInfo->Close();
            continue;
        }

        pGateInfo->bufLen += dwBytesTransferred;

        while ( pGateInfo->HasCompletionPacket() )
        {
            *(pGateInfo->ExtractPacket( szTmp ) - 1) = '\0';

            switch ( szTmp[1] )
            {
            case '-':
                pGateInfo->SendKeepAlivePacket();
                break;
            case 'A':
                pGateInfo->ReceiveSendUser(&szTmp[2]);
                break;
            case 'O':
                pGateInfo->ReceiveOpenUser(&szTmp[2]);
                break;
            case 'X':
                pGateInfo->ReceiveCloseUser(&szTmp[2]);
                break;
            case 'S':
                pGateInfo->ReceiveServerMsg(&szTmp[2]);
                break;
            case 'M':
                pGateInfo->MakeNewUser(&szTmp[2]);
                break;
            }
        }

        if ( pGateInfo->Recv() == SOCKET_ERROR && WSAGetLastError() != ERROR_IO_PENDING )
        {
            InsertLogMsg(_TEXT("WSARecv() failed"));
            continue;
        }
    }

    return 0;
}
//处理操作
UINT WINAPI ThreadFuncForMsg(LPVOID lpParameter)
{
	_TDEFAULTMESSAGE	DefaultMsg;
	char				*pszBegin, *pszEnd;
	int					nCount;
	PLISTNODE			pListNode;
	CGateInfo*			pGateInfo;

	while (TRUE)
	{
		if (g_xGateList.GetCount())
		{
			pListNode = g_xGateList.GetHead();

			while (pListNode)
			{
				pGateInfo = g_xGateList.GetData(pListNode);

				if (pGateInfo)
				{
					nCount = pGateInfo->g_SendToGateQ.GetCount();

					if (nCount)
					{
						for (int nLoop = 0; nLoop < nCount; nLoop++)
						{
							_LPTSENDBUFF pSendBuff = (_LPTSENDBUFF)pGateInfo->g_SendToGateQ.PopQ();

							//先解密
							if (pSendBuff)
							{
								int nLen = pSendBuff->nLen;

								pSendBuff->szData[nLen] = '\0';

								pszBegin = pSendBuff->szData;
								{
									//解密
									Packet *pPacket = (Packet*)pSendBuff->szData;
									/*pPacket->dlen = pPacket->crc^ pPacket->dlen;*/

									switch(pPacket->Category)
									{
									case ACCOUNT:
										pGateInfo->AccountProcess(pSendBuff->sock,pPacket);
										break;
									default:
										break;
									}
									//switch (DefaultMsg.wIdent)
									//{
									//	case CM_PROTOCOL:
									//		break;
									//	case CM_IDPASSWORD:
									//		pGateInfo->ProcLogin(pSendBuff->sock, pszBegin + DEFBLOCKSIZE + 2);
									//		break;
									//	case CM_SELECTSERVER:
									//		pGateInfo->ProcSelectServer(pSendBuff->sock, DefaultMsg.wParam);
									//		break;
									//	case CM_ADDNEWUSER:
									//		pGateInfo->ProcAddUser(pSendBuff->sock, pszBegin + DEFBLOCKSIZE + 2);
									//		break;
									//	case CM_UPDATEUSER:
									//		break;
									//	case CM_CHANGEPASSWORD:
									//		break;
									//}
								}

								delete pSendBuff;
								pSendBuff = NULL;
							}
						}
					}
				}

				pListNode = g_xGateList.GetNext(pListNode);
			}
		}

		SleepEx(1, TRUE);	
	}

	return 0;
}
Exemple #12
0
void CGateInfo::GetSelectCharacter(SOCKET s, char *pszPacket)
{
	char				szDecodeMsg[128];
	char				szServerIP[32];
	char				szEncodeMsg[32];
	char				szEncodeData[64];
	char				szEncodePacket[256];
	_TDEFAULTMESSAGE	DefaultMsg;
	
	// ORZ: Load Balancing, 접속수가 가장 적은 게이트 서버 IP 선택
	GAMESERVERINFO *pBestServer = NULL;
	GAMESERVERINFO *pTemp;

//	EnterCriticalSection( &g_xGameServerList.m_cs );
	for ( PLISTNODE pNode = g_xGameServerList.GetHead();pNode; pNode = g_xGameServerList.GetNext( pNode ) )
	{
		pTemp = g_xGameServerList.GetData( pNode );
		
		if ( !pBestServer || pTemp->connCnt < pBestServer->connCnt )
		{
			pBestServer = pTemp;
			continue;
		}
	}

	pBestServer->connCnt++;
//	LeaveCriticalSection( &g_xGameServerList.m_cs );

	strcpy( szServerIP, pBestServer->ip );
	// ORZ: from here

	int nPos = fnDecode6BitBufA(pszPacket, szDecodeMsg, sizeof(szDecodeMsg));
	szDecodeMsg[nPos] = '\0';

	char *pszDevide = (char *)memchr(szDecodeMsg, '/', nPos);
	
	if (pszDevide)
	{
		*pszDevide++ = '\0';

		// 서버 선택이 가능하도록 수정
		_TLOADHUMAN		tLoadHuman;
		CServerInfo*	pServerInfo;

		memcpy(tLoadHuman.szUserID, szDecodeMsg, memlen(szDecodeMsg));
		memcpy(tLoadHuman.szCharName, pszDevide, memlen(pszDevide));
		ZeroMemory(tLoadHuman.szUserAddr, sizeof(tLoadHuman.szUserAddr));
		tLoadHuman.nCertification = 0;

		PLISTNODE pListNode = g_xServerList.GetHead();

		if (pListNode)
			pServerInfo = g_xServerList.GetData(pListNode);

		GetLoadHumanRcd(pServerInfo, &tLoadHuman, 0);

		fnMakeDefMessageA(&DefaultMsg, SM_STARTPLAY, 0, 0, 0, 0);
		nPos = fnEncodeMessageA(&DefaultMsg, szEncodeMsg, sizeof(szEncodeMsg));
		int nPos2 = fnEncode6BitBufA((unsigned char *)szServerIP, szEncodeData, memlen(szServerIP) -1, sizeof(szEncodeData));
		
		memmove(szEncodePacket, szEncodeMsg, nPos);
		memmove(&szEncodePacket[nPos], szEncodeData, nPos2);
		szEncodePacket[nPos + nPos2] = '\0';
		
		// ORZ: 전체 리스트에 추가한다.
		// 같은 아이디가 이미 존재하거나 메모리 부족등의 이유로 실패할 수 있다.
//		if ( GetGlobalUserList()->Insert( tLoadHuman.szCharName, szServerIP ) )
			SendToGate(s, szEncodePacket);
//		else
//		{
//			fnMakeDefMessageA(&DefaultMsg, SM_STARTFAIL, 0, 0, 0, 0);
//			nPos = fnEncodeMessageA(&DefaultMsg, szEncodeMsg, sizeof(szEncodeMsg));
//			szEncodeMsg[nPos] = '\0';
			
//			SendToGate(pGateInfo->sock, s, szEncodeMsg);
//		}
	}
}
//UINT WINAPI AcceptThread(LPVOID lpParameter)
//logingate接受线程
DWORD WINAPI AcceptThread(LPVOID lpParameter)
{
	int							nLen = sizeof(SOCKADDR_IN);
	char						szMsg[128] = {0};

	SOCKET						Accept;
	SOCKADDR_IN					Address;

	while (TRUE)
	{
		Accept = accept(g_ssock, (struct sockaddr FAR *)&Address, &nLen);

		if (g_fTerminated)
			return 0;

		CSessionInfo* pNewUserInfo = CSessionInfo::ObjPool().createObject();//(CSessionInfo*)GlobalAlloc(GPTR, sizeof(CSessionInfo));

		if (pNewUserInfo)
		{
			pNewUserInfo->sock				= Accept;

			CreateIoCompletionPort((HANDLE)pNewUserInfo->sock, g_hIOCP, (DWORD)pNewUserInfo, 0);

			if (g_xSessionList.AddNewNode(pNewUserInfo))
			{
				int zero = 0;
				setsockopt(pNewUserInfo->sock, SOL_SOCKET, SO_SNDBUF, (char *)&zero, sizeof(zero) );
				zero = 0;
				setsockopt( pNewUserInfo->sock, SOL_SOCKET, SO_RCVBUF, (char*)&zero, sizeof(zero));

				int nodelay = 1;
				setsockopt( pNewUserInfo->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&nodelay, sizeof(nodelay) );

				// ORZ:接受数据
				int retcode = pNewUserInfo->Recv();
				if ( (retcode == SOCKET_ERROR) && (WSAGetLastError() != WSA_IO_PENDING) )
				{
					continue;
				}

				UpdateStatusBar(TRUE);

				szMsg[0] = '%';
				szMsg[1] = 'O';

				char *pszPos = ValToAnsiStr((int)Accept, &szMsg[2]);
				
				*pszPos++ = '/';

				pszPos = ValToAnsiStr((int)Address.sin_addr.s_net, pszPos);
				*pszPos++ = '.';
				pszPos = ValToAnsiStr((int)Address.sin_addr.s_host, pszPos);
				*pszPos++ = '.';
				pszPos = ValToAnsiStr((int)Address.sin_addr.s_lh, pszPos);
				*pszPos++ = '.';
				pszPos = ValToAnsiStr((int)Address.sin_addr.s_impno, pszPos);

				*pszPos++	= '$';
				*pszPos		= '\0';

				//发送给loginsrv更新
				SendExToServer(szMsg);
			}
		}
	}

	return 0;
}