菜鸟 关于WSASend 函数,IO完成端口模型

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了菜鸟 关于WSASend 函数,IO完成端口模型相关的知识,希望对你有一定的参考价值。

WSABUF myWSABUF;
myWSABUF.buf = "love you";
myWSABUF.len = 1024;

DWORD myReceive;
PPER_IO_DATA mypPerIO = (PPER_IO_DATA)GlobalAlloc(GPTR, sizeof(PER_IO_DATA));

WSASend(pPerHandle->s,&myWSABUF,1,&myReceive,0,&mypPerIO->ol,NULL);

1.如上代码的功能是向客户端发送一个“love you ” 字符串。我是在别人写的一段 IOCP socket 模型 上改的, 我用 WSASend 函数向客户端发送信息, 客户端能正常收到 “love you”,但是, 除了 能 收到 “love you” 外, 还收到了很多很多空格,这是为什么?
2. 把 myWSABUF.len = 1024; 改为 myWSABUF.len = sizeof(myWSABUF.buf) 为什么 客户端 就收不到任何信息了?
myWSABUF.len 代表的难道不是我发送的love you 这个字符串的长度吗?

3.我在书上看到:WSASend 倒数第二个参数,即: &mypPerIO->ol 即代表了 WSAOVERLAPPED 的结构的指针, 那么,我自己写一个OVERLAPPED结构,如下
OVERLAPPED myOVERLAPPED
WSASend(pPerHandle->s,&myWSABUF,1,&myReceive,0,&myOVERLAPPED,NULL);
为什么客户端 就 收不到 任何 内容了呢? OVERLAPPED为什么必须放在一个 PER_IO 结构体里面呢?

我是菜鸟中的菜鸟,刚开始学套接字的异步IO , 很多很多 的地方 都很迷惑。 IOCP模型的原理我基本了解了, 但是就是很疑惑他们传值的方法, 又是什么 OVERLAPPED结构, 又是 PER_HANDLE的,真的很晕。

请各位给我理下思路啊,谢谢

百度知道有问题,回答的内容一天也无法显示。1 你将BUF的大小设置为1024,但是你的BUF内容为“love you”,只有8个长度,当然会出现很多空格了。
2 你将sizeof(myWSABUF.buf)输入看看长度为多少?如果长度为8之对了一半,别忘了,字符结尾应该加上"\0"哦。
3 你只贴出了代码片段,无法判断错与对,建议你发送数据的时候先发送包头,如:建立一个结构体,
struct head_info

int head_type;//包体内容
int head_len;//包体长度
;
这个结构体长度的大小为为8,里面有包体的内容和包体的长度,接收时先接受包头的8字节长度,然后进行分析,再根据分析的接头接受包体就行了。追问

感觉您比较专业,麻烦再帮我看看这个问题,感谢!http://zhidao.baidu.com/question/261665634.html?fr=middle_ask

追答

WSABUF buf; //定义一个WSABUF,名称叫buf
PPER_IO_DATA pPerIO = (PPER_IO_DATA)::GlobalAlloc(GPTR,sizeof(PER_IO_DATA));
//定义并初始一个PPER_IO_DATA,名称叫pPerIO
buf.buf = pPerIO->buf;//将buf的buf指向pPerlO的buf中,也就是将buf的缓冲区指向了pPerIO的缓冲区。
对于你的疑惑:
1我没有完整的代码,你要弄明白buf.buf使用的缓冲区究竟是在接收前还是接收数据后,也就是指向pPerIO->buf是接收之前还是数据接收之后.
2 buf.buf的缓冲区指向了struct _PER_IO_DATA结构体的buf中,并不表示数据的转移,而是buf的缓冲区就是使用struct _PER_IO_DATA的缓冲区,而避免数据的拷贝,这样接受的数据就直接接收到了struct _PER_IO_DATA的BUF中了。

参考技术A sizeof(myWSABUF.buf)在windows 32位里面返回值应该是4,因为buf是一个指针,sizeof 指针都是4,
如果想获取长度应该是strlen((char*)myWSABUF.buf)吧?!!
参考技术B fdgdfgfdgdfg

IOCP:内核如何决定同步或异步完成 WSASend?

【中文标题】IOCP:内核如何决定同步或异步完成 WSASend?【英文标题】:IOCP: how does the kernel decide to complete WSASend synchronously or asynchronously? 【发布时间】:2014-11-03 02:44:29 【问题描述】:

我们编写了利用 I/O 完成端口的软件,并在 SOCKET 对象上使用 WSASend,在命名管道上使用 WriteFile。

在这两种情况下,我们发现这些 API 返回 SOCKET_ERROR / WAS_IO_PENDING [1] 的时间比我们预期的要快得多(或命名管道 WriteFile 操作的等价物)。

似乎我们错误地假设如果我们填满发送缓冲区(CreateNamedPipe 中的 nInBufferSize)会触发异步完成,相反它似乎更具侵略性并且与发送缓冲区的大小无关。对于套接字和命名管道,如果足够快,大发送缓冲区(100k+)和小消息(几个字节)总是会在第二次写入时异步完成。

谁能证实这一点?有没有人知道 Windows 实现在决定何时异步完成 I/O 操作时遵循的启发式信息,而不是同步完成?

[1] "如果重叠操作成功启动并稍后完成,WSASend 返回 SOCKET_ERROR 并指示错误代码 WSA_IO_PENDING。" - http://msdn.microsoft.com/en-us/library/windows/desktop/ms742203(v=vs.85).aspx

【问题讨论】:

此类实施细节可能会发生变化。您需要确保您的代码不包含任何关于它们的假设。 【参考方案1】:

为什么你认为你需要知道或关心。它不是 API 的记录部分,它可能受到当时堆栈中的驱动程序和任何分层服务提供程序的影响。

您必须编写正确的代码来处理成功的“同步”发送或待处理的“异步”发送,那么这对您获得这两种结果的频率有何影响?

此外,除非您使用 SetFileCompletionNotificationModes() 启用 FILE_SKIP_COMPLETION_PORT_ON_SUCCESS,否则同步和待处理结果使用相同的代码路径。

【讨论】:

以上是关于菜鸟 关于WSASend 函数,IO完成端口模型的主要内容,如果未能解决你的问题,请参考以下文章

io 完成端口问题,每个 GetQueuedCompletionStatus 调用多个 wsarecv 或 wsasend

如果在 IOCP 模型中指定了 WSASend 的 lpCompletionRoutine 怎么办?

IOCP:内核如何决定同步或异步完成 WSASend?

具有多个缓冲区的 WSASend() - 可以完成不完整吗?

阻塞模式下的 WSASend() 是不是会导致将通知数据包放置在完成端口中?

是否有可能不会收到 WSASend 调用的完成?