I/O完成端口(IOCP)
服务器:
#include "stdafx.h"
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#include <iostream>
using namespace std; // 单句柄数据
typedef struct tagPER_HANDLE_DATA
{
SOCKET Socket;
SOCKADDR_STORAGE ClientAddr;
// 将和这个句柄关联的其他有用信息,尽管放在这里面吧 }PER_HANDLE_DATA, *LPPER_HANDLE_DATA; // 但I/O 操作数据
typedef struct tagPER_IO_DATA
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
char buffer[];
int BufferLen;
int OperationType; // 可以作为读写的标志,为简单,我忽略了
}PER_IO_DATA, *LPPER_IO_DATA; //线程函数
DWORD WINAPI ServerWorkerThread(LPVOID lpParam); DWORD WINAPI ServerWorkerThread(LPVOID lpParam)
{
HANDLE CompletionPort = (HANDLE)lpParam;
DWORD BytesTransferred;
LPOVERLAPPED lpOverlapped;
LPPER_HANDLE_DATA PerHandleData = NULL;
LPPER_IO_DATA PerIoData = NULL;
DWORD SendBytes;
DWORD RecvBytes;
DWORD Flags;
BOOL bRet = FALSE; while (TRUE) //无限循环
{
bRet = GetQueuedCompletionStatus(CompletionPort,&BytesTransferred,(PULONG_PTR)&PerHandleData,(LPOVERLAPPED*)&lpOverlapped,INFINITE); // 检查成功的返回,这儿要注意使用这个宏CONTAINING_RECORD
PerIoData = (LPPER_IO_DATA)CONTAINING_RECORD(lpOverlapped,PER_IO_DATA,Overlapped);
// 先检查一下,看看是否在套接字上已有错误发生 if ( == BytesTransferred)
{
closesocket(PerHandleData->Socket);
GlobalFree(PerHandleData);
GlobalFree(PerIoData);
continue;
} // 数据处理
char sendBuf[];
sprintf(sendBuf,"Welcome %s to %d %d \n",PerIoData->DataBuf.buf,PerHandleData->Socket,::GetCurrentThreadId());
send(PerHandleData->Socket,sendBuf,strlen(sendBuf)+,);
//WSASend()
/*DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = buffer;
for(i=0; i < SEND_COUNT ;i++) {
WSASend(PerHandleData->Socket, &DataBuf, 1, &SendBytes, 0, &SendOverlapped, NULL); */ // 成功了!!!这儿就收到了来自客户端的数据
cout << PerIoData->DataBuf.buf << ::GetCurrentThreadId() << endl; Flags = ;
// 为下一个重叠调用建立单I/O 操作数据
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED)); PerIoData->DataBuf.len = ;
PerIoData->DataBuf.buf = PerIoData->buffer;
PerIoData->OperationType = ; // read WSARecv(PerHandleData->Socket,&(PerIoData->DataBuf),,&RecvBytes,&Flags,&(PerIoData->Overlapped),NULL);
}
return ;
} int main(int argc, _TCHAR* argv[])
{
//头部申明
HANDLE CompletionPort;
WSADATA wsd;
SYSTEM_INFO SystemInfo;
SOCKADDR_IN InternetAddr;
SOCKET Listen; // 加载WinSock2.2
WSAStartup(MAKEWORD(, ), &wsd); // 1.创建一个I/O 完成端口
CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,,); // 2.确定系统中有多少个处理器
GetSystemInfo(&SystemInfo); // 3.基于系统中可用的处理器数量创建工作器线程
for (int i = ; i < int(SystemInfo.dwNumberOfProcessors * ); ++i)
{
HANDLE ThreadHandle;
// 创建一个服务器的工作器线程,并将完成端口传递到该线程
ThreadHandle = CreateThread(NULL,,ServerWorkerThread,CompletionPort,,NULL);
CloseHandle(ThreadHandle);
} // 4.创建一个监听套接字,以下的套路都是固定的。
Listen = WSASocket(AF_INET,SOCK_STREAM,,NULL,,WSA_FLAG_OVERLAPPED); //绑定和监听
InternetAddr.sin_family = PF_INET;
InternetAddr.sin_port = htons();
InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(Listen, (SOCKADDR*)&InternetAddr, sizeof(InternetAddr));
listen(Listen, ); //无限循环
BOOL b = TRUE;
while (b)
{
PER_HANDLE_DATA * PerHandleData = NULL;
SOCKADDR_IN saRemote;
SOCKET Accept;
int RemoteLen;
// 5.接收连接,并分配完成端口,这儿可以用AcceptEx 来代替,以创
// 建可伸缩的Winsock 应用程序。
RemoteLen = sizeof(saRemote);
Accept = accept(Listen, (SOCKADDR*)&saRemote, &RemoteLen); // 6.创建用来和套接字关联的单句柄数据信息结构
PerHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA)); //cout << "Socket number " << Accept << " connected" << endl; PerHandleData->Socket = Accept;
memcpy(&PerHandleData->ClientAddr, &saRemote, RemoteLen); // 7.将接受套接字和完成端口关联起来
CreateIoCompletionPort((HANDLE)Accept,CompletionPort,(DWORD)PerHandleData,); // 开始在接受套接字上处理I/O
// 使用重叠I/O 机制,在新建的套接字上投递一个或多个异步
// WSARecv 或 WSASend 请求。这些I/O 请求完成后,工作者线程
// 会为I/O 请求提供服务,之后就可以坐享其成了
static int const DATA_BUFSIZE = ;
DWORD RecvBytes = ;
DWORD Flags = ; // 单I/O 操作数据
LPPER_IO_DATA PerIoData = NULL;
PerIoData = (LPPER_IO_DATA)GlobalAlloc(GPTR, sizeof(PER_IO_DATA));
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->DataBuf.len = ;
PerIoData->DataBuf.buf = PerIoData->buffer;
PerIoData->OperationType = ; // read
WSARecv(PerHandleData->Socket,&(PerIoData->DataBuf),,&RecvBytes,&Flags,&(PerIoData->Overlapped),NULL);
} return ;
}
客户端:
#include "stdafx.h"
#include <Winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#include <stdio.h> void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err; wVersionRequested = MAKEWORD( , ); err = WSAStartup( wVersionRequested, &wsaData );
if ( err != ) {
return;
} if ( LOBYTE( wsaData.wVersion ) != ||
HIBYTE( wsaData.wVersion ) != ) {
WSACleanup( );
return;
} while (true)
{
SOCKET sockClient=socket(AF_INET,SOCK_STREAM,); SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons();
connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); send(sockClient,"This is lisi",strlen("This is lisi")+,); char recvBuf[];
recv(sockClient,recvBuf,,);
printf("%s\n",recvBuf); closesocket(sockClient);
} WSACleanup();
}
I/O完成端口(IOCP)的更多相关文章
- DELPHI中完成端口(IOCP)的简单分析(4)
DELPHI中完成端口(IOCP)的简单分析(4) 在我以前写的文章中,一直说的是如何接收数据.但是对于如何发送数据却一点也没有提到.因为从代码量上来说接收的代码要比发送多很多.今天我就来写一下如 ...
- DELPHI中完成端口(IOCP)的简单分析(3)
DELPHI中完成端口(IOCP)的简单分析(3) fxh7622关注4人评论7366人阅读2007-01-17 11:18:24 最近太忙,所以没有机会来写IOCP的后续文章.今天好不容易有 ...
- DELPHI中完成端口(IOCP)的简单分析(2)
DELPHI中完成端口(IOCP)的简单分析(2) 今天我写一下关于DELPHI编写完成端口(IOCP)的工作者线程中的东西.希望各位能提出批评意见.上次我写了关于常见IOCP的代码,对于IOCP ...
- DELPHI中完成端口(IOCP)的简单分析(1)
DELPHI中完成端口(IOCP)的简单分析(1) 用DELPHI开发网络代码已经有一段时间了! 我发现在网上用VC来实现完成端口(IOCP)的代码很多,但是使用DELPHI来实现的就比较少了.对 ...
- 完成端口iocp——在螺丝壳里做道场
WINDOWS 2000以后的操作系统才支持IOCP.WINSOCK2.0才支持IOCP. 首先要有一个WINSOCK2.PAS的WINSOCK2.0接口调用声明单元. WINSOCK的版本号: WI ...
- 【windows核心编程】IO完成端口(IOCP)复制文件小例前简单说明
1.关于IOCP IOCP即IO完成端口,是一种高伸缩高效率的异步IO方式,一个设备或文件与一个IO完成端口相关联,当文件或设备的异步IO操作完成的时候,去IO完成端口的[完成队列]取一项,根据完成键 ...
- 完成端口IOCP详解
修改自: http://blog.csdn.net/piggyxp/article/details/6922277 ps: 原作者很厉害了, 把一个iocp模型讲解的这么形象,不过在实践过程中发现一些 ...
- TCP服务器并发编程构架:完成端口IOCP模式
windows下socket网络编程模式:IOCP 完成端口 1)IOCP异步事件的获取放到操作系统的网络驱动层来处理,实际上反而是降低了编程难度, 2)同时对于多线程的并发调度,也放到操作系统级别来 ...
- 套接字I/O模型-完成端口IOCP
“完成端口”模型是迄今为止最为复杂的一种I/O模型.然而,假若一个应用程序同时需要管理为数众多的套接字,那么采用这种模型,往往可以达到最佳的系统性能!但不幸的是,该模型只适用于Windows NT和W ...
- 完成端口(IOCP)怎么判断某个连接是否断开
完成端口函数: BOOL GetQueuedCompletionStatus( HANDLE CompletionPort, LPDWORD lpNumberOfBytes, PULONG_PTR l ...
随机推荐
- 用java.lang.Math.random()语句,随机输出{size:自定义参数}个数不重复并且按顺序从小到大排列(冒泡排序)
package com.test; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.lan ...
- How to use Jenkins
一.关键点 1.how to start the build server? do i need to start some app to do this? I don't believe so... ...
- QT 创建主窗口 MainWindow 实例
1. 2. mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include & ...
- JAVA Properties配置文件的读写
通常我们就会看到一个配置文件,比如:jdbc.properties,它是以“.properties”格式结尾的.在java中,这种文件的内容以键值对<key,value>存储,通常以“=” ...
- VS10_慢_优化
参考网址: http://blog.csdn.net/cll131421/article/details/15341367 1. 我暂时只做了这个: “ 一.VS2010选项视觉体验设置 工具-> ...
- js中出现问题--Type Syntax error on token "catch", Identifier expected jquery.js
解决方案: 1.选中jQuery报错的web工程: 2.右键-->Myeclipse-->Exclude From Validation,选中: 3.继续右键Myeclipse--> ...
- ssh学习(1)
雇员薪资管理系统(crud) ①先搞定spring ②引入spring包 ③编写applicationContext.xml文件(或者beans.xml),我们把该文件放在src目录下 ④测试一下sp ...
- Model compatibility cannot be checked because the database does not contain model metadata. Ensure that IncludeMetadataConvention has been added to the DbModelBuilder conventions
Model compatibility cannot be checked because the database does not contain model metadata. Ensure t ...
- SQL Compare
http://pan.baidu.com/s/1jGIEEm6 来源:数据库同步工具: Red Gate Sql Compare
- es6语法入门let 和 const 命令
let块级作用域 { let a = 10; var b = 1; } a // ReferenceError: a is not defined. b for循环的计数器,就很合适使用let命令(防 ...