服务器:

 #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)的更多相关文章

  1. DELPHI中完成端口(IOCP)的简单分析(4)

    DELPHI中完成端口(IOCP)的简单分析(4)   在我以前写的文章中,一直说的是如何接收数据.但是对于如何发送数据却一点也没有提到.因为从代码量上来说接收的代码要比发送多很多.今天我就来写一下如 ...

  2. DELPHI中完成端口(IOCP)的简单分析(3)

    DELPHI中完成端口(IOCP)的简单分析(3)   fxh7622关注4人评论7366人阅读2007-01-17 11:18:24   最近太忙,所以没有机会来写IOCP的后续文章.今天好不容易有 ...

  3. DELPHI中完成端口(IOCP)的简单分析(2)

    DELPHI中完成端口(IOCP)的简单分析(2)   今天我写一下关于DELPHI编写完成端口(IOCP)的工作者线程中的东西.希望各位能提出批评意见.上次我写了关于常见IOCP的代码,对于IOCP ...

  4. DELPHI中完成端口(IOCP)的简单分析(1)

    DELPHI中完成端口(IOCP)的简单分析(1)   用DELPHI开发网络代码已经有一段时间了! 我发现在网上用VC来实现完成端口(IOCP)的代码很多,但是使用DELPHI来实现的就比较少了.对 ...

  5. 完成端口iocp——在螺丝壳里做道场

    WINDOWS 2000以后的操作系统才支持IOCP.WINSOCK2.0才支持IOCP. 首先要有一个WINSOCK2.PAS的WINSOCK2.0接口调用声明单元. WINSOCK的版本号: WI ...

  6. 【windows核心编程】IO完成端口(IOCP)复制文件小例前简单说明

    1.关于IOCP IOCP即IO完成端口,是一种高伸缩高效率的异步IO方式,一个设备或文件与一个IO完成端口相关联,当文件或设备的异步IO操作完成的时候,去IO完成端口的[完成队列]取一项,根据完成键 ...

  7. 完成端口IOCP详解

    修改自: http://blog.csdn.net/piggyxp/article/details/6922277 ps: 原作者很厉害了, 把一个iocp模型讲解的这么形象,不过在实践过程中发现一些 ...

  8. TCP服务器并发编程构架:完成端口IOCP模式

    windows下socket网络编程模式:IOCP 完成端口 1)IOCP异步事件的获取放到操作系统的网络驱动层来处理,实际上反而是降低了编程难度, 2)同时对于多线程的并发调度,也放到操作系统级别来 ...

  9. 套接字I/O模型-完成端口IOCP

    “完成端口”模型是迄今为止最为复杂的一种I/O模型.然而,假若一个应用程序同时需要管理为数众多的套接字,那么采用这种模型,往往可以达到最佳的系统性能!但不幸的是,该模型只适用于Windows NT和W ...

  10. 完成端口(IOCP)怎么判断某个连接是否断开

    完成端口函数: BOOL GetQueuedCompletionStatus( HANDLE CompletionPort, LPDWORD lpNumberOfBytes, PULONG_PTR l ...

随机推荐

  1. EntityFramework 学习 一 Multiple Diagrams in Entity Framework 5.0

    Visual Studio 2012 provides a facility to split the design time visual representation of the Entity ...

  2. python爬虫-url

    特此声明: 以下内容来源于博主:http://blog.csdn.net/pleasecallmewhy                                     http://cuiq ...

  3. Spring学习之xml配置Bean总结

    学习Spring时,我用的是Maven来管理jar包,先看看maven的pom.xml: pom.xml <project xmlns="http://maven.apache.org ...

  4. keystone cache

    http://docs.openstack.org/juno/config-reference/content/section_keystone.conf.html http://docs.opens ...

  5. Tensorflow搭建神经网络及使用Tensorboard进行可视化

    创建神经网络模型 1.构建神经网络结构,并进行模型训练 import tensorflow as tfimport numpy as npimport matplotlib.pyplot as plt ...

  6. 查看后台PHP进程(非PHP-FPM)

    ps -ef | grep php | grep -v php-fpm

  7. 2017-03-04 dotnet core网站发布到Linux系统中

    今天开始学习dotnet core的开发,距离Visual Stuio 2017正式版的发布,也就是VS20周岁的生日还有三天,在我的电脑上安装的是VS2017 Enterprise RC版, 在VS ...

  8. node-并发控制

    当我们在做一些爬虫小程序的时候,如果我们一次性爬的数据条较多,那么相关软件也许会有限制或者是认为我们是非法的.那么我们就需要一些机制去限制获取数据的条数.而且node为我们提供的并发获取数据都是异步的 ...

  9. lightoj1422 区间dp

    对于这一题想了很久真的是一点头绪也没有,还有组数明明是200,数据范围100,O(n^3)的复杂度居然不会爆掉(可能是因为一直在想怎么用O(n^2)的复杂度做这题 做法是先预处理dp,对于dp[i][ ...

  10. levelDB, TokuDB, BDB等kv存储引擎性能对比——wiredtree, wiredLSM,LMDB读写很强啊

    在:http://www.lmdb.tech/bench/inmem/ 2. Small Data Set Using the laptop we generate a database with 2 ...