当前位置: 首页 > wzjs >正文

文秘写作网站二级域名网站查询入口

文秘写作网站,二级域名网站查询入口,国外如何建立个人网站,做的比较早的海淘网站《TCP/IP网络编程》学习笔记 | Chapter 22:重叠 I/O 模型 《TCP/IP网络编程》学习笔记 | Chapter 22:重叠 I/O 模型理解重叠 I/O 模型重叠 I/O本章讨论的重叠 I/O 的重点不在于 I/O 创建重叠 I/O 套接字执行重叠 I/O 的 WSASend 函数进行重叠 I/O 的 WSA…

《TCP/IP网络编程》学习笔记 | Chapter 22:重叠 I/O 模型

  • 《TCP/IP网络编程》学习笔记 | Chapter 22:重叠 I/O 模型
    • 理解重叠 I/O 模型
      • 重叠 I/O
      • 本章讨论的重叠 I/O 的重点不在于 I/O
    • 创建重叠 I/O 套接字
    • 执行重叠 I/O 的 WSASend 函数
    • 进行重叠 I/O 的 WSARecv 函数
    • 重叠 I/O 的 I/O 完成确认
      • 使用事件对象
      • 使用 Completion Routine 函数

《TCP/IP网络编程》学习笔记 | Chapter 22:重叠 I/O 模型

理解重叠 I/O 模型

第 21 章异步处理的并非 I/O,而是“通知”。本章讲解的才是以异步方式处理 I/O 的方法。

重叠 I/O

同一线程内部向多个目标传输数据引起的 I/O 重叠现象称为“重叠I/O”。为了完成这项任务,调用的 I/O 函数应立即返回,只有这样才能发送后续数据。从结果来看,利用上述模型收发数据时,最重要的前提条件就是异步 I/O(调用的 I/O 函数应以非阻塞模式工作)。

在这里插入图片描述

本章讨论的重叠 I/O 的重点不在于 I/O

重叠 I/O 的重点并非 I/O 本身,而是如何确认 I/O 完成时的状态。

非阻塞模式的输入输出需要另外确认执行结果。

Windows 平台下重叠 I/O 模型由非阻塞异步 I/O 函数和确认 I/O 完成状态的方法组成。

创建重叠 I/O 套接字

首先要创建适用于重叠I/O的套接字,可以通过如下函数完成:

#include <winsock2.h>SOCKET WSASocket(int af, int type, int protocol, LPWSAPROTOCOL_INFO loProtocolInfo,GROUP g,DWORD dwFlags
);

参数:

  • af:协议族信息
  • type:套接字数据传输方式
  • protocol:2 个套接字之间使用的协议信息
  • lpProtocolInfo:包含创建的套接字信息的WSAPROTOCOL_INFO结构体变量地址值,不需要时传递 NULL。
  • g:为扩展函数而预约的参数,可以使用 0
  • dwFlags:套接字属性信息

成功时返回套接字句柄,失败时返回 INVALID_SOCKET。

各位对前 3 个参数比较熟悉,第四个和第五个参数与目前的工作无关,可以简单设置为 NULL 和 0。可以向最后一个参数传递 WSA_FLAG_OVERLAPPED,赋予创建出的套接字重叠 I/O 特性。

可以通过如下函数调用创建出可以进行重叠 I/O 的非阻塞模式的套接字。

WSASocket(PF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);

执行重叠 I/O 的 WSASend 函数

创建出具有重叠 I/O 属性的套接字后,接下来 2 个套接字(服务器端/客户端之间的)连接过程与一般的套接字连接过程相同,但 I/O 数据时使用的函数不同。

先介绍重叠 I/O 中使用的数据输出函数:

#include <winsock2.h>int WSASend(SOCKET s,LPWSABUF lpBuffers,DWORD dwBufferCount,LPDWORD lpNumberOfBytesSent,DWORD dwFlags,LPWSAOVERLAPPED lpOverlapped,LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);

参数:

  • s:套接字句柄,传递具有重叠 I/O 属性的套接字句柄时,以重叠 I/O 模型输出。
  • IpBuffers:WSABUF 结构体变量数组的地址值,WSABUF 中存有待传输数据。
  • dwBufferCount:第二个参数中数组的长度。
  • IpNumberOfBytesSent:用于保存实际发送字节数的变量地址值
  • dwFlags:用于便改数据传输特性,如传递 MSG_OOB 时发送 OOB 模式的数据。
  • IpOverlapped:WSAOVERLAPPED 结构体变量的地址值,使用事件对象,用于确认完成数据传输。
  • IpCompletionRoutine:传入 Completion Routine 函数的入口地址值,可以通过该函数确认是否完成数据传输。

成功时返回 0,失败时返回 SOCKET_ERROR。

接下来介绍上述函数的第二个结构体参数类型,该结构体中存有待传输数据的地址和大小等信息。

typedef struct __WSABUF
{u_long len; // 待传输数据的大小char FAR * buf; // 缓冲地址值
} WSABUF, *LPWSABUF;

利用上述函数和结构体,传输数据时可以按如下方式编写代码:

WSAEVENT event;
WSAOVERLAPPED overlapped;
WSABUF dataBuf;
char buf[BUF_SIZE] = {"待传输的数据"};
int revcBytes = 0;
......
event = WSACreateEvent();
memset(&overlapped, 0, sizeof(overlapped));
overlapped.hEvent = event;
dataBuf.len = sizeof(buf);
dataBuf.buf = buf;
WSASend(hSocket, &dataBuf, 1, &recvBytes, 0, &overlapped, NULL);
......

调用 WSASend 函数时将第三个参数设置为 1,因为策二个参数中待传输数据的缓冲个数为 1。另外,多余参数均设置为 NULL 或 0,其中需要注意第六个和第七个参数。

第六个参数中的 WSAOVERLAPPED 结构体定义如下:

typedef struct _WSAOVERLAPPED
{ DWORD Internal;DWORD InternalHigh;DWORD Offset;DWORD OffsetHigh;WSAEVENT hEvent;
} WSAOVERLAPPED, *LPWSAOVERLAPPED;

Internal、InternalHigh 成员是进行重叠 I/O 时操作系统内部使用的成员,而 Offset、OffsetHigh 同样属于具有特殊用途的成员。所以各位实际只需要关注 hEvent 成员。

关于 WSAOVERLAPPED 结构体有 3 点需要注意:

  1. 为了进行重叠 I/O,WSASend 函数的 lpOverlapped 参数中应该传递有效的结构体变量地址值,而不是 NULL。
  2. 若向 lpOverlapped 传递 NULL,WSASend 函数的第一个参数中的句柄所指的套接字将以阻
    塞模式工作。
  3. 利用 WSASend 函教同时向多个目标传输数据时,需要分别构建传入第六个参数的 WSAOVERLAPPED 结构体变量。这是因为,进行重叠 I/O 的过程中,操作系统将使用 WSAOVERLAPPED 结构体变量。

WSASend 函数调用过程中,函数返回时间点和数据传输完成时间点并非总不一致。分为以下两种情况:

  • 如果输出缓冲是空的,且传输的数据并不大,那么函数调用后可以立即完成数据传输。此时,WSASend 函数将返回 0,lpNumberOfBytesSent 中将保存实际传输的数据大小的信息。
  • 反之,WSASend 函数返回后仍需要传输数据时,将返回 SOCKET_ERROR,并将 WSA_IO_PENDING 注册为错误代码,该代码可以通过 WSAGetLastError 函数(稍后再介绍)得到。这时应该通过如下函效获取实际传输的数据大小。
#include <winsock2.h>BOOL WSAGetOverlappedResult(SOCKET s,LPWSAOVERLAPPED lpOverlapped,LPDWORD lpcbTransfer,BOOL fWait,LPDWORD lpdwFlags
);

参数:

  • s:进行重叠 I/O 的套接字句柄。
  • IpOverlapped:进行重叠 I/O 时传递的 WSAOVERLAPPED 结构体变量的地址值。
  • lpcbTransfer:用于保存实际传输的字节数的变量地址值。
  • fWait:如果调用该函数时仍在进行 I/O,fWait 为 TRUE 时等待 I/O 完成,fWait 为 FALSE 时将返回 FALSE 并跳出函数。
  • IpdwFlags:调用 WSARecv 函数时,用于获取附加信息(例如 OOB 消息)。如果不需要,可以传递 NULL。

成功时返回 TRUE,失败时返回 FALSE。

通过此函数不仅可以获取数据传输结果,还可以验证接收数据的状态。

进行重叠 I/O 的 WSARecv 函数

#include <winsock2.h>int WSARecv(SOCKET s,LPWSABUF lpBuffers,DWORD dwBufferCount,LPDWORD lpNumberOfBytesRecvd,LPDWORD lpFlags,LPWSAOVERLAPPED lpOverlapped,LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);

参数:

  • s:具有重叠 I/O 属性套接字句柄。
  • IpBuffers:用于保存接收数据的 WSABUF 结构体变量数组的地址值。
  • dwBufferCount:第二个参数中数组的长度。
  • lpNumberOfBytesRecvd:用于保存接收字节数的变量地址值。
  • lpFlags:用于设置或读取传输特性信息。
  • IpOverlapped:WSAOVERLAPPED 结构体变量地址值。
  • IpCompletionRoutine:Completion Routine 函数地址值。

成功时返回 0,失败时返回 SOCKET_ERROR。

Gather 输出指将多个缓冲中的数据累积到一定程度后一次性输出,Scatter 输入指将接收的数据分批保存。
重叠 I/O 的 WSASend 和 WSARecv 函数可以获得 writev & readv 函数的 Gather/Scatter I/O 功能。

重叠 I/O 的 I/O 完成确认

重叠 I/O 中有 2 种方法确认 I/O 的完成并获取结果。

  • 利用 WSASend、WSARecv 函数的第六个参数,基于事件对象。
  • 利用 WSASend、WSARecv 函数的第七个参数,基于 Completion Routine。

只有理解了这 2 种方法,才能算是掌握了重叠 I/O。首先介绍利用第六个参数的方法。

使用事件对象

直接给出示例。希望各位通过该示例验证如下 2 点:

  • 完成 I/O 时,WSAOVERLAPPED 结构体变量引用的事件对象将变为 signaled 状态。
  • 为了验证 I/O 的完成和完成结果,需要调用 WSAGetOvrlappedResult 函数。

发送端代码:

#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h>void ErrorHandling(char *msg);int main(int argc, char *argv[])
{WSADATA wsaData;SOCKET hSocket;SOCKADDR_IN sendAdr;WSABUF dataBuf;char msg[] = "Network is Computer!";int sendBytes = 0;WSAEVENT evObj;WSAOVERLAPPED overlapped;if (argc != 3){printf("Usage : %s <IP> <port> \n", argv[0]);exit(1);}if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)ErrorHandling("WSAStartup() error");hSocket = WSASocket(PF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);memset(&sendAdr, 0, sizeof(sendAdr));sendAdr.sin_family = AF_INET;sendAdr.sin_addr.s_addr = inet_addr(argv[1]);sendAdr.sin_port = htons(atoi(argv[2]));if (connect(hSocket, (SOCKADDR *)&sendAdr, sizeof(sendAdr)) == SOCKET_ERROR)ErrorHandling("connect() error");evObj = WSACreateEvent();memset(&overlapped, 0, sizeof(overlapped));overlapped.hEvent = evObj;dataBuf.len = strlen(msg) + 1;dataBuf.buf = msg;if (WSASend(hSocket, &dataBuf, 1, &sendBytes, 0, &overlapped, NULL) == SOCKET_ERROR){if (WSAGetLastError() == WSA_IO_PENDING){puts("Background data send");WSAWaitForMultipleEvents(1, &evObj, TRUE, WSA_INFINITE, FALSE);WSAGetOverlappedResult(hSocket, &overlapped, &sendBytes, FALSE, NULL);}else{ErrorHandling("WSASend() error");}}printf("Send data size: %d \n", sendBytes);WSACloseEvent(evObj);closesocket(hSocket);WSACleanup();return 0;
}void ErrorHandling(char *msg)
{fputs(msg, stderr);fputc('\n', stderr);exit(1);
}

上述示例调用的 WSAGetLastError 函数定义如下。调用套接字相关函数后,可以通过该函数获取错误信息。

#include<winsock2.h>int WSAGetLastError(void); // 返回错误代码(表示错误原因)

上述示例中该函数的返回值为 WSA_IO_PENDING,由此可以判断 WSASend 函数的调用结果并非发生了错误,而是尚未完成的状态。

下面介绍与上述示例配套使用的接收端代码:

在这里插入代码片

使用 Completion Routine 函数

http://www.dtcms.com/wzjs/325249.html

相关文章:

  • 中国品牌网是什么网站今天新闻
  • 企业 网站 推广app推广注册从哪里接单
  • 企业网站的基本内容优化器
  • 微网站怎样做seo优化排名是什么
  • 国内做彩票网站违法么武汉seo服务
  • 网站建设优化网站优化是什么
  • 台州网站开发广州网站排名优化公司
  • 给金融的做网站 犯法吗广告联盟赚钱app
  • 黑龙江俄语网站制作seo整站优化更能准确获得客户
  • 物联网系统开发360优化大师安卓下载
  • 中山网站建设 760咸阳seo
  • wordpress更改后台登陆地址南京seo优化培训
  • 英文网站建设公司站长统计app官方网站
  • 四川省建设工程招标网官网搜索引擎优化的各种方法
  • co域名网站祁阳seo
  • 移民网站用什么系统做网站好网站推广经验
  • 做网站方法创意设计
  • asp网站后台源码游戏推广工作好做吗
  • 网站前台模板怎么替换网页制作成品模板网站
  • 建网站和开发app哪个难百度文库首页官网
  • 双鸭山住房和城乡建设局网站网站安全检测平台
  • seo在网站制作培训机构排名
  • 有网站怎么建设手机站百度指数入口
  • 怎么免费做网站视频教学微信营销方式有哪些
  • 东营网站建设推广公司今日国际新闻头条
  • 重庆红旗河沟网站建设可以访问境外的浏览器
  • 个人空间网站建设北京网站优化服务商
  • 南通网站建设top友情链接在线观看
  • 网站开发 适应 手机 电脑每日新闻摘抄10一15字
  • 寻花问柳-专注做一家男人的网站猪2022十大热点事件及评析