socket-重叠模型(overlap)
关键是理解“重叠”两个字,就是你把发送的数据交给系统,然后自己做别的事情,在你干自己的事情时,系统同时也正在完成你交给他的任务,两者同时进行。系统完成后会调用你给他的代码或者通知你。所以,“重叠”指的是时间上的重叠。
要想在一个套结字上使用重叠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)的更多相关文章
- 很幽默的讲解六种Socket IO模型
很幽默的讲解六种Socket IO模型 本文简单介绍了当前Windows支持的各种Socket I/O模型,如果你发现其中存在什么错误请务必赐教. 一:select模型二:WSAAsyncSelect ...
- Socket编程模型之完毕port模型
转载请注明来源:viewmode=contents">http://blog.csdn.net/caoshiying?viewmode=contents 一.回想重叠IO模型 用完毕例 ...
- 很幽默的讲解六种Socket IO模型 Delphi版本(自己Select查看,WM_SOCKET消息通知,WSAEventSelect自动收取,Overlapped I/O 事件通知模型,Overlapped I/O 完成例程模型,IOCP模型机器人)
很幽默的讲解六种Socket IO模型(转)本文简单介绍了当前Windows支持的各种Socket I/O模型,如果你发现其中存在什么错误请务必赐教. 一:select模型 二:WSAAsyncSel ...
- Socket重叠IO
1.为什么到现在才弄懂这个 不知道这个Socket重叠IO这种模型是不是socket IO完成端口的基础,不过我感觉,学习一下这个再去学习socket IO完成端口是比较有好处的. 这个Scoket重 ...
- 洛谷P2202 [USACO13JAN]方块重叠Square Overlap
P2202 [USACO13JAN]方块重叠Square Overlap 题目描述 Farmer John is planning to build N (2 <= N <= 50,000 ...
- Linux 的 Socket IO 模型
前言 之前有看到用很幽默的方式讲解Windows的socket IO模型,借用这个故事,讲解下linux的socket IO模型: 老陈有一个在外地工作的女儿,不能经常回来,老陈和她通过信件联系. 他 ...
- 卷积与反卷积、步长(stride)与重叠(overlap)
1. 卷积与反卷积 如上图演示了卷积核反卷积的过程,定义输入矩阵为 I(4×4),卷积核为 K(3×3),输出矩阵为 O(2×2): 卷积的过程为:Conv(I,W)=O 反卷积的过称为:Deconv ...
- 一个Socket数据处理模型
Socket编程中,如何高效地接收和处理数据,这里介绍一个简单的编程模型. Socket索引 - SocketId 在给出编程模型之前,先提这样一个问题,程序中如何描述Socket连接? 为什么这么问 ...
- socket select模型
由于socket recv()方法是堵塞式的,当多个客户端连接服务器时,其中一个socket的recv调用时,会产生堵塞,使其他连接不能继续. 如果想改变这种一直等下去的焦急状态,可以多线程来实现(不 ...
随机推荐
- English trip V1 - 10.Family Ties 家庭关系 Teacher:Emily Key: Possessive s (所有格 s)
In this lesson you will learn to talk about people in a family. 课上内容(Lesson) What are you Spring Fes ...
- Fiddler抓包—搞定接口测试
·包的定义 在包交换网络里,单个消息被划分为多个数据块,这些数据块称为包,它包含发送者和接受者的地址信息.这些包然后沿着不同的路径在一个或多个网络中传输,并且在目的地重新组合. ·应用 简 ...
- 『TensorFlow』生成式网络中的图片预处理
简介 这里的生成式网络是广义的生成式,不仅仅指gan网络,还有风格迁移中的类自编码器网络,以及语义分割中的类自编码器网络,因为遇到次数比较多,所以简单的记录一下. 背景 1.像素和数字 图像处理目标一 ...
- E. Intersection of Permutations
题意:给两个排列,2种操作1,查询两个区间a和b一样的值个数,2,交换b的两个值 题解:树套树,先把a变成1到n的排列,对b做相同的变换,然后问题就变成了查询区间lb,rb中la到ra的个数,带修改可 ...
- 让你明白kvm是什么
参考:https://blog.csdn.net/bbwangj/article/details/80465320 KVM 工具集合: libvirt:操作和管理KVM虚机的虚拟化 API,使用 C ...
- 3月26 document的练习
1.Window.document对象 一.找到元素: docunment.getElementById("id"):根据id找,最多找一个: var a =docunme ...
- 托管DLL和非托管DLL的区别
首先解释一下,托管DLL和非托管DLL的区别.狭义解释讲,托管DLL就在Dotnet环境生成的DLL文件.非托管DLL不是在Dotnet环 境生成的DLL文件. 托管DLL文件,可以在Dotnet环境 ...
- Nginx+Tomcat集群配置
Nginx+Tomcat集群配置 一台虚拟机作为Nginx服务 两太虚拟机配置Tomcat+jdk环境 Nginx测试 启动: cd usr/local/nginx/sbin ./nginx ---& ...
- 青蛙跳N阶(变态跳)
https://www.nowcoder.com/questionTerminal/22243d016f6b47f2a6928b4313c85387 描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级 ...
- CSS:font-family常用字体中英文对照
CSS:font-family常用字体中英文对照如下: 推荐网址:https://www.cnblogs.com/EnSnail/p/6792853.html 微软雅黑: Microsoft YaHe ...