求完成端口的服务端和客户端源码。本人第一次发帖,一定给分。 客户端测试的时候,要尽可能显示服务端的iocp特性。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 #include <stdio.h>#include <winsock2.h>#include <stdlib.h>#pragma comment (lib,"WS2_32.lib")#define SERV_TCP_PORT 9999#define DATA_BUFSIZE 1024struct _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 %d\n", 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 模式:端口 %d\n", SERV_TCP_PORT); fprintf(stderr, "Ctrl+C 停止服务器程序\n"); printf("written by http://www.wantsoft.com\n"); fprintf(stderr, "开始监听客户端:\n"); // 无限循环,接受并处理新的连接 while (true) { if ((newsocket = WSAAccept(listener, NULL, NULL, NULL, 0)) == SOCKET_ERROR) { printf("WSAAccept() failed with error %d\n", 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: %s\n", 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 %d\n", 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] = '\0'; 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 %d\n", WSAGetLastError()); return ; } } }// 错误句柄void FatalError(char *s){ fprintf(stdout, "%s\n", s); exit(EXIT_FAILURE);} http://www.codeproject.com/info/search.aspx?artkw=iocp Windows网络与通信程序设计(源码)http://download.csdn.net/source/192329其中就有IOCP相关的demo。lz可以参考书籍一起看,效果更好些 代码网上很多的,搜下就有。你可以用NetAssist(网络调试助手),帮你测试。并发的发送和接收大流量的数据 http://topic.csdn.net/u/20100715/14/76aa6ed0-b964-429d-b3a4-fad472d69d92.html?91138我帖子的地址,里面有我前面上传的服务器源码,还有个客户端测试程序,可搜索我上传的资源 http://www.codeproject.com/KB/IP/iocp_server_client.aspx 准备运行于同一个进程的多个activex编写时,如何较好的避免全局变量冲突 ocx控件在网页中自动下载安装 两个小问题 一般手机上用的是什么操作系统? SQL2000+vc++6.0 100分相送!请问如何将单文档多视中的窗口分割条固定,不让其移动?一定给分! 如何在vc++下保存图片 想学数据库,我该学什么呢! 易水大哥,你的qq是多少呀??? 如何在ActiveX控件实现数据的串行化 急 急 急!!!!!!!@!!! 下班了,留个帖.你感觉C++最难的语法是哪一部分? 多个DLL,设置断点问题
#include <winsock2.h>
#include <stdlib.h>
#pragma comment (lib,"WS2_32.lib")#define SERV_TCP_PORT 9999
#define DATA_BUFSIZE 1024struct _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 %d\n", 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 模式:端口 %d\n", SERV_TCP_PORT);
fprintf(stderr, "Ctrl+C 停止服务器程序\n");
printf("written by http://www.wantsoft.com\n");
fprintf(stderr, "开始监听客户端:\n"); // 无限循环,接受并处理新的连接
while (true)
{
if ((newsocket = WSAAccept(listener, NULL, NULL, NULL, 0)) == SOCKET_ERROR)
{
printf("WSAAccept() failed with error %d\n", 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: %s\n", 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 %d\n", 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] = '\0';
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 %d\n", WSAGetLastError());
return ;
}
}
}// 错误句柄
void FatalError(char *s)
{
fprintf(stdout, "%s\n", s);
exit(EXIT_FAILURE);
}
http://download.csdn.net/source/192329其中就有IOCP相关的demo。lz可以参考书籍一起看,效果更好些
你可以用NetAssist(网络调试助手),帮你测试。并发的发送和接收大流量的数据
我帖子的地址,里面有我前面上传的服务器源码,还有个客户端测试程序,可搜索我上传的资源