server.cpp
资源名称:1731.rar [点击查看]
上传用户:swkcbjrc
上传日期:2016-04-02
资源大小:45277k
文件大小:6k
源码类别:
游戏
开发平台:
Visual C++
- #include <stdio.h>
- #include <winsock2.h>
- #include <stdlib.h>
- #pragma comment (lib,"WS2_32.lib")
- #define SERV_TCP_PORT 9999
- #define DATA_BUFSIZE 1024
- struct _OVERLAPPELUS
- {
- SOCKET socket;
- char InBuffer[DATA_BUFSIZE]; // 输入
- OVERLAPPED ovIn;
- int nOutBufIndex;
- char OutBuffer[DATA_BUFSIZE]; // 输出
- OVERLAPPED ovOut;
- DWORD dwWritten;
- }OVERLAPPELUS, *LPOVERLAPPELUS;
- _OVERLAPPELUS pKey;
- HANDLE ghCompletionPort;
- void CreateWorkerThreads();
- DWORD WINAPI WorkerThread(LPVOID pvoid);
- void IssueRead(struct _OVERLAPPELUS *pCntx);
- void CheckOsVersion();
- void FatalError(char *s);
- void SendString(char *p,struct _OVERLAPPELUS *pCntx);
- ///////////////////////////////////////////////////////////
- int main(int argc, char *argv[])
- {
- SOCKET listener;
- SOCKET newsocket;
- WSADATA WsaData;
- struct sockaddr_in serverAddress;
- int err;
- CheckOsVersion();
- err = WSAStartup (0x0202, &WsaData);
- if (err == SOCKET_ERROR)
- {
- FatalError("网络初始化失败.");
- return EXIT_FAILURE;
- }
- if ((listener = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
- {
- printf("WSASocket() failed with error %dn", WSAGetLastError());
- return EXIT_FAILURE;
- }
- memset(&serverAddress, 0, sizeof(serverAddress));
- serverAddress.sin_family = AF_INET;
- serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
- serverAddress.sin_port = htons(SERV_TCP_PORT);
- err = bind(listener, (struct sockaddr *)&serverAddress, sizeof(serverAddress));
- if (err < 0)
- {
- FatalError("bind() 错误-请检查 TCP/IP 是否正确安装?");
- }
- ghCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL,0,0);
- if (ghCompletionPort == NULL)
- {
- FatalError("CreateIoCompletionPort() 错误-请检查系统是否是Windows NT version 3.51 或更高版本.");
- }
- CreateWorkerThreads();
- listen(listener, 5);
- fprintf(stderr, "I/O Completion Ports 模式:端口 %dn", SERV_TCP_PORT);
- fprintf(stderr, "Ctrl+C 停止服务器程序n");
- printf("written by http://www.wantsoft.comn");
- fprintf(stderr, "开始监听客户端:n");
- // 无限循环,接受并处理新的连接
- while (true)
- {
- if ((newsocket = WSAAccept(listener, NULL, NULL, NULL, 0)) == SOCKET_ERROR)
- {
- printf("WSAAccept() failed with error %dn", WSAGetLastError());
- return EXIT_FAILURE;
- }
- //建立一个 key 并初始化它.
- pKey.socket = newsocket;
- pKey.ovOut.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); //为写信息包过程设置(事件对象) event .
- pKey.ovOut.hEvent = (HANDLE)((DWORD)pKey.ovOut.hEvent | 0x1);
- CreateIoCompletionPort( //为请求绑定端口
- (HANDLE)newsocket,
- ghCompletionPort,
- (DWORD)&pKey,
- 0 );
- IssueRead(&pKey); // 完成第一次读操作
- }
- return 0;
- }
- void CreateWorkerThreads()
- {
- SYSTEM_INFO sysinfo;
- DWORD dwThreadId;
- DWORD dwThreads;
- DWORD i;
- GetSystemInfo(&sysinfo);
- dwThreads = sysinfo.dwNumberOfProcessors * 2 + 2;
- for (i=0; i<dwThreads; i++)
- {
- HANDLE hThread;
- hThread = CreateThread(NULL, 0, WorkerThread, NULL, 0, &dwThreadId);
- CloseHandle(hThread);
- }
- }
- // 每一个工作线程从这里开始.
- DWORD WINAPI WorkerThread(LPVOID pVoid)
- {
- BOOL bResult;
- DWORD dwNumRead;
- struct _OVERLAPPELUS *pCntx;
- LPOVERLAPPED lpOverlapped = NULL;
- UNREFERENCED_PARAMETER(pVoid);
- // 无限循环从 I/O completion port 获取信息.
- while (true)
- {
- bResult = GetQueuedCompletionStatus(ghCompletionPort, &dwNumRead, (DWORD*)&pCntx, &lpOverlapped, INFINITE);
- if (bResult == FALSE && lpOverlapped == NULL)
- {
- FatalError("WorkerThread - GetQueuedCompletionStatus()错误.n");
- }
- else if (bResult == FALSE && lpOverlapped != NULL)
- {
- fprintf(stderr,"用户非正常退出.n");
- }
- else if (dwNumRead == 0)
- {
- fprintf(stderr, "用户已经退出.n");
- fprintf(stderr, "------------------.n");
- }
- else
- {
- printf("recv data from client: %sn", pCntx->InBuffer);
- SendString(pCntx->InBuffer, pCntx);
- IssueRead(pCntx);
- }
- }
- ExitThread(0);
- return 0;
- }
- ///////////////////////////////////////////////////////
- //调用 WSARecv 开始一个异步请求重复获取我们的句柄状态//
- ///////////////////////////////////////////////////////
- void IssueRead(struct _OVERLAPPELUS *pCntx)
- {
- DWORD RecvBytes;
- DWORD Flags =0;
- WSABUF DataBuff;
- if (pCntx == NULL)
- return;
- memset(pCntx->InBuffer, 0, sizeof(pCntx->InBuffer));
- ZeroMemory( &(pCntx->ovIn), sizeof(OVERLAPPED));
- DataBuff.len = DATA_BUFSIZE;
- DataBuff.buf = pCntx->InBuffer;
- if (WSARecv(pCntx->socket, &DataBuff, 1, &RecvBytes, &Flags,
- &(pCntx->ovIn), NULL) == SOCKET_ERROR)
- {
- if (WSAGetLastError() != ERROR_IO_PENDING)
- {
- printf("WSARecv() failed with error %dn", WSAGetLastError());
- return ;
- }
- }
- }
- // 确保我们运行在正确的版本下 Windows NT (3.51, 4.0, or later)
- void CheckOsVersion()
- {
- OSVERSIONINFO ver;
- BOOL bResult;
- ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- bResult = GetVersionEx((LPOSVERSIONINFO) &ver);
- if ( (!bResult) ||
- (ver.dwPlatformId != VER_PLATFORM_WIN32_NT) )
- {
- FatalError("ECHOSRV requires Windows NT 3.51 or later.");
- }
- }
- //发送字符串子程序
- void SendString(char *p, struct _OVERLAPPELUS *pCntx)
- {
- DWORD SendBytes;
- WSABUF DataBuff;
- int len;
- strcpy(pCntx->OutBuffer,p);
- len = strlen(pCntx->OutBuffer);
- pCntx->OutBuffer[len] = ' ';
- pCntx->nOutBufIndex = strlen(pCntx->OutBuffer);
- DataBuff.len = len;
- DataBuff.buf = pCntx->OutBuffer;
- if (WSASend(pCntx->socket, &DataBuff, 1, &SendBytes, 0,
- &(pCntx->ovOut), NULL) == SOCKET_ERROR)
- {
- if (WSAGetLastError() != ERROR_IO_PENDING)
- {
- printf("WSASend() failed with error %dn", WSAGetLastError());
- return ;
- }
- }
- }
- // 错误句柄
- void FatalError(char *s)
- {
- fprintf(stdout, "%sn", s);
- exit(EXIT_FAILURE);
- }