socket-重叠模型(overlap)
重叠模型的基本设计原理便是让应用程序使用一个重叠的数据结构,一次投递一个或多个Winsock I/O请求。针对那些提交的请求,在它们完成之后,应用程序可为它们提供服务。该模型适用于除Windows CE之外的各种Windows平台。模型的总体设计以Win32重叠I/O机制为基础。那个机制可以通过ReadFile和WriteFile两个函数,针对设备执行I/O操作。

关键是理解“重叠”两个字,就是你把发送的数据交给系统,然后自己做别的事情,在你干自己的事情时,系统同时也正在完成你交给他的任务,两者同时进行。系统完成后会调用你给他的代码或者通知你。所以,“重叠”指的是时间上的重叠。

要想在一个套结字上使用重叠I/O模型,首先必须使用WSA_FLAG_OVERLAPPED这个标志,创建一个套结字。如下所示:
s = WSASocket( AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED );
创建套结字时,假如使用的是socket函数,而非WSASocket函数,那么会默认设置WSA_FLAG_OVERLAPPED标志。该标志可与下面函数相关联:

WSASend
WSASendTo
WSARecv
WSARecvFrom
WSAIoctl
AcceptEx
TransmitFile

若随一个WSAOVERLAPPED结构一起调用这些函数,函数会立即完成并返回,无论套结字是否设置为阻塞模式。主要有两个方法用来管理一个重叠I/O请求的完成:我们的应用程序客等待“事件对象通知”,亦可通过“完成例程”,对已完成的请求加以处理。

编写一个简单重叠I/O模式服务器程序,基本步骤如下:
1)创建一个套结字,开始在指定的端口上监听连接请求。
2)接受一个进入的连接请求。
3)为接受的套结字新建一个WSAOVERLAPPED结构,并为该结构分配一个事件对象句柄。也将事件对象句柄分配给一个事件数组,以便稍后WSAWaitForMultipleEvents函数使用。
4)在套结字上投递一个异步WSARecv请求,指定参数为WSAOVERLAPPED结构。(函数通常会以失败告终,返回SOCKET_ERROR错误状态WSA_IO_PENDING)。
5)使用步骤3)的事件数组,调用WSAWaitForMultipleEvents函数,并等待与重叠调用关联在一起的事件进入“已传信”状态(等待那个事件触发)。
6)WSAWaitForMultipleEvents函数完成后,针对事件数组,调用WSAResetEvent(重设事件)函数,从而重设事件对象,并对完成的重叠请求进行处理。
7)使用WSAGetOverlappedResult函数,判断重叠调用的返回状态是什么。
8)在套结字上投递另一个重叠WSARecv请求。
9)重复步骤5)~8)。

下面附上源代码

Server端代码:

#include <stdio.h>
#include <Winsock2.h>
#pragma comment(lib, "WS2_32.lib")

#define MYPORT 8001
#define MYIP "127.0.0.1"
#define DATA_BUFSIZE 1024

void showerror(const char* function);
void main()
{
WORD wVersion = MAKEWORD( 2, 0 );
WSADATA wsdata;
WSABUF DataBuf;
DWORD EventTotal = 0;
DWORD RecvBytes = 0;
DWORD BytesTransferred = 0;
DWORD Flags = 0;
DWORD Index = 0;
WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];
WSAOVERLAPPED AcceptOverlapped;
SOCKET ListenSocket, AcceptSocket;
struct sockaddr_in addr;
int addrlen = sizeof(struct sockaddr);
char szbuffer[DATA_BUFSIZE];

// 加载socket2.0 dll
int nResult = WSAStartup( wVersion, &wsdata );
if( nResult != 0 )
{
printf( "error in function WSAStartup(): %d\n", WSAGetLastError() );
return;
}
printf("WSAStartup success\n");

// Step 1:
// Start Winsock and set up a listening socket
printf("create socket...\n");
ListenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
if( ListenSocket == INVALID_SOCKET )
{
showerror( "socket" );
return;
}
printf("create socket success\n");

addr.sin_family = AF_INET;
addr.sin_port = htons( MYPORT );
addr.sin_addr.s_addr = inet_addr( MYIP );
printf("bind socket...\n");
nResult = bind( ListenSocket, (struct sockaddr*)&addr, sizeof(struct sockaddr_in) );
if( nResult == SOCKET_ERROR )
{
showerror( "bind" );
return;
}
printf("bind socket success\n");

printf("listen socket...\n");
nResult = listen( ListenSocket, 5 );
if( nResult == SOCKET_ERROR )
{
showerror( "listen" );
return;
}
printf("listen socket success\n");

// Step 2:
// Accept an inbound connection
AcceptSocket = accept( ListenSocket, NULL, NULL );

// Step 3:
// Set up an overlapped structure
EventArray[EventTotal] = WSACreateEvent();
ZeroMemory(&AcceptOverlapped, sizeof(WSAOVERLAPPED));
AcceptOverlapped.hEvent = EventArray[EventTotal];

DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = szbuffer;

EventTotal++;

// Step 4:
// Post a WSARecv request to begin receiving data on the socket
WSARecv( AcceptSocket, &DataBuf, 1, &RecvBytes, &Flags, &AcceptOverlapped, NULL );

while(TRUE)
{
// Step 5:
// Wait for the overlapped I/O call to complete
Index = WSAWaitForMultipleEvents( EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE );

// Step 6:
// Reset the signaled event
WSAResetEvent( EventArray[Index - WSA_WAIT_EVENT_0] );

// Step 7:
// Determine the status of the overlapped
WSAGetOverlappedResult( AcceptSocket, &AcceptOverlapped, &BytesTransferred, FALSE, &Flags );

// First check to see whether the peer has closed the connection,
// and if so, close the socket
if( BytesTransferred == 0 )
{
showerror( "Closing socket" );
closesocket( AcceptSocket );
WSACloseEvent( EventArray[Index - WSA_WAIT_EVENT_0] );
return;
}

// Do someting with the received data
// DataBuf contains the received data
printf( "Received: %s\n", DataBuf.buf );

// Step 8:
// Post another WSARecv() request on the socket
Flags = 0;
ZeroMemory( &AcceptOverlapped, sizeof(AcceptOverlapped) );
AcceptOverlapped.hEvent = EventArray[Index - WSA_WAIT_EVENT_0];

DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = szbuffer;

WSARecv( AcceptSocket, &DataBuf, 1, &RecvBytes, &Flags, &AcceptOverlapped, NULL );
}

// 关闭socket
closesocket( ListenSocket );

// 卸载socket2.0 dll
WSACleanup();
}

void showerror(const char* function)
{
LPVOID lpMsgBuf;

FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,0, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //默认语言
(LPTSTR)&lpMsgBuf, 0, NULL );

printf("error in function %s:\n描述: %s\n", function, (char*)lpMsgBuf);

//释放内存
LocalFree( lpMsgBuf );
}

 

socket-重叠模型(overlap)的更多相关文章

  1. 很幽默的讲解六种Socket IO模型

    很幽默的讲解六种Socket IO模型 本文简单介绍了当前Windows支持的各种Socket I/O模型,如果你发现其中存在什么错误请务必赐教. 一:select模型二:WSAAsyncSelect ...

  2. Socket编程模型之完毕port模型

    转载请注明来源:viewmode=contents">http://blog.csdn.net/caoshiying?viewmode=contents 一.回想重叠IO模型 用完毕例 ...

  3. 很幽默的讲解六种Socket IO模型 Delphi版本(自己Select查看,WM_SOCKET消息通知,WSAEventSelect自动收取,Overlapped I/O 事件通知模型,Overlapped I/O 完成例程模型,IOCP模型机器人)

    很幽默的讲解六种Socket IO模型(转)本文简单介绍了当前Windows支持的各种Socket I/O模型,如果你发现其中存在什么错误请务必赐教. 一:select模型 二:WSAAsyncSel ...

  4. Socket重叠IO

    1.为什么到现在才弄懂这个 不知道这个Socket重叠IO这种模型是不是socket IO完成端口的基础,不过我感觉,学习一下这个再去学习socket IO完成端口是比较有好处的. 这个Scoket重 ...

  5. 洛谷P2202 [USACO13JAN]方块重叠Square Overlap

    P2202 [USACO13JAN]方块重叠Square Overlap 题目描述 Farmer John is planning to build N (2 <= N <= 50,000 ...

  6. Linux 的 Socket IO 模型

    前言 之前有看到用很幽默的方式讲解Windows的socket IO模型,借用这个故事,讲解下linux的socket IO模型: 老陈有一个在外地工作的女儿,不能经常回来,老陈和她通过信件联系. 他 ...

  7. 卷积与反卷积、步长(stride)与重叠(overlap)

    1. 卷积与反卷积 如上图演示了卷积核反卷积的过程,定义输入矩阵为 I(4×4),卷积核为 K(3×3),输出矩阵为 O(2×2): 卷积的过程为:Conv(I,W)=O 反卷积的过称为:Deconv ...

  8. 一个Socket数据处理模型

    Socket编程中,如何高效地接收和处理数据,这里介绍一个简单的编程模型. Socket索引 - SocketId 在给出编程模型之前,先提这样一个问题,程序中如何描述Socket连接? 为什么这么问 ...

  9. socket select模型

    由于socket recv()方法是堵塞式的,当多个客户端连接服务器时,其中一个socket的recv调用时,会产生堵塞,使其他连接不能继续. 如果想改变这种一直等下去的焦急状态,可以多线程来实现(不 ...

随机推荐

  1. English trip V1 - 9.Do you Ever Say Never? 你有没有说永远不会? Teacher:Lamb Key: Adverbs of frequency (频率副词)

    In this lesson you will learn to describe what you do at home. 在本课中,您将学习如何描述您在家中所做的事情. 课上内容(Lesson) ...

  2. LeetCode--383--赎金信

    问题描述: 给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串ransom能不能由第二个字符串magazines里面的字符构成.如果可以构成,返回 true ...

  3. uva11552

    将字符串分为len/k块.用dp[i][j]表示第i个块必须以j结尾的最小划分.当第i块没有字符j时,dp[i][j]多计一个.如果当前块只有1种字符,那么就等于dp[i-1][j].否则对于第i块的 ...

  4. CCPC2017湘潭 1263 1264 1267 1268

    1263 拉升一下就A了 #include <iostream> #include <vector> #include <algorithm> #include & ...

  5. vue项目 sockjs-node一直报错问题

    vue3下 vue.config.js中 devServer: { host: '0.0.0.0', port: 8080, proxy: { '/': { target: 'http://127.0 ...

  6. python-flask-wtforms

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. svn: 提交终止

    今天我遇到了svn 的问题  svn: 提交终止: “/var/www/modelfinance/modules/incomereport/views/purchase” 处于冲突状态 冲突状态搞的我 ...

  8. python 小练习3

    求大蜜题:给你两个正整数a(0 < a < 100000)和n(0 <= n <=100000000000),计算(a^n) % 20132013并输出结果 ret = 1 d ...

  9. DDOS 攻击的防范

    ddos 攻击介绍 可以看下面的文章 http://www.ruanyifeng.com/blog/2018/06/ddos.html 下面转自:  http://www.escorm.com/arc ...

  10. MySql多个count查询

    现有一个student表结构数据如下: id hight sex age 1 160 0 16 2  170  1  16  3  180  1  17  4  160  1  16  5  170  ...