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. java日志及异常错误信息输出的问题

    1.异常信息可以层层传递,直到最后一层再输出日志也来得及 2.错误信息要在发生错误的当时就输出日志,否则到了其它层,很难得到准确的错误信息内容

  2. SSH免密钥登陆

    local ipaddress:10.47.39.7:remote ipaddress:10.47.39.8 1.生成公钥和私钥 [root@local ~]# ssh-keygen -t rsa  ...

  3. public class feign.RetryableException feign.RetryableException: Connection refused (Connection refused) executing POST http://common-wx/wx/auth/client/token/v1

    一.异常出现的场景 Spring Cloud内部两个服务A和B,A调用B时,抛出该异常.提示连接拒绝 public class feign.RetryableException feign.Retry ...

  4. ubuntu vi配置

    1.先卸载tiny版本vi 输入命令:sudo apt-get remove vim-common 2.然后再输入命令: sudo apt-get   install vim sudo vim /et ...

  5. mac下 配置homebrew 和java home

    1.terminal下输入   /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/insta ...

  6. vue element upload图片 回显问题

      beforeUpload (file) { var _this = this; var reader = new FileReader(); reader.readAsDataURL(file); ...

  7. python-day91--JS实现的ajax

    一.AJAX核心(XMLHttpRequest) 其实AJAX就是在Javascript中多添加了一个对象:XMLHttpRequest对象.所有的异步交互都是使用XMLHttpServlet对象完成 ...

  8. HashTable Queue Stack SortedList BitArray

    HashTable 由于是非泛型集合,因此存储进去的都是object类型,不管是键还是值. Hashtable不允许排序 key不允许重复 键不允许为null Queue和Queue<T> ...

  9. echarts的基本使用

    echarts的基本使用 官网:http://echarts.baidu.com/index.html ECharts,一个使用 JavaScript 实现的开源可视化库,可以流畅的运行在 PC 和移 ...

  10. Intersecting Lines

    Intersecting Lines We all know that a pair of distinct points on a plane defines a line and that a p ...