- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
文档清楚地表明,如果 WSASend 立即完成,您将获得 WSA_IO_PENDING,但这从未发生过。我总是得到 0,并且 dwBytesTransferred 总是匹配我发送的字节。但是,似乎有时会调用我的完成例程,有时却不会。我为发送分配了缓冲区,因此如果不调用完成例程,我需要释放缓冲区。
我有三个临时计数器,m_dwAsyncSend、m_dwSyncSend 和 m_dwCompletions。 m_dwAsycSend 始终为零,并且 m_dwSyncSend 和 m_dwCompletions 始终相距很远,因为一个 m_dwSyncSend 可能是 750,而 m_dwCompletions 是 2。有很多次线程是可警报的,所以我认为我不会那样饿死它。
这让我发疯了!现在是午夜过后,我整天都在做这个。如果其中任何一个不连贯,我都会责怪它!
这是代码,我认为您不需要类文件就可以看到我在做什么。
void
CALLBACK
SendCompletion(
DWORD dwError,
DWORD cbTransferred,
LPOVERLAPPED pOvl,
DWORD dwFlags
)
{
LPWSABUF pBuffer = (LPWSABUF)((DWORD_PTR)pOvl + sizeof(OVERLAPPED));
CNetAsyncSocket *pSock = (CNetAsyncSocket *)pOvl->hEvent;
pSock->m_dwCompletions++;
if(dwError != NO_ERROR)
{
// If things didn't go as planned, ring the bell and disconnect.
pSock->Disconnect();
tracef(TT_REGULAR, 1,
"SOCKET_ERROR in CNetAsyncSocket::Send(), disconnecting, error code: %ld, on socket: %s:%ld",
dwError, pSock->GetIP(), pSock->GetPort());
free(pOvl);
}
else
{
// If we sent less than we meant to, queue up the rest.
if(cbTransferred < pBuffer->len)
{
DWORD dwRemaining = pBuffer->len - cbTransferred;
memmove(pBuffer->buf, (PVOID)((DWORD_PTR)pBuffer->buf + dwRemaining), dwRemaining);
pBuffer->len = dwRemaining;
}
else
{
free(pOvl);
}
}
}
void CNetAsyncSocket::SendAsync(PBYTE pData, DWORD dwLength)
{
// We want to minimize heap churn, so let's do this in one allocation.
// Also, having this in one chunk of memory makes it easier to interpret
// it on the other side.
DWORD dwAllocSize =
sizeof(OVERLAPPED) + // The OVERLAPPED struct.
sizeof(WSABUF) + // The buffer info.
dwLength; // The actual buffer we're copying.
LPOVERLAPPED pOvl = (LPOVERLAPPED)malloc(dwAllocSize);
if(pOvl == NULL)
{
// Out of memory.
}
// Initialize the allocation.
ZeroMemory(pOvl, dwAllocSize);
// Build the pointers.
LPWSABUF pBuffer = (LPWSABUF)((DWORD_PTR)pOvl + sizeof(OVERLAPPED));
pBuffer->len = dwLength;
assert(pBuffer->len < 1000000);
pBuffer->buf = (PCHAR)((DWORD_PTR)pBuffer + sizeof(WSABUF));
// When you have a completion routine, the hEvent member is ignored, so we
// can use it to pass our this pointer to the completion routine.
pOvl->hEvent = (PVOID)this;
// Copy the data to the buffer.
CopyMemory(pBuffer->buf, pData, dwLength);
// Send the data.
DWORD dwSent = 0;
int iResult = WSASend(
m_hSocket, // The socket.
pBuffer, // The WSABUF struct.
1, // Number of structs (1).
&dwSent, // Bytes sent. Updated if it happens synchronously.
0, // No flags.
pOvl, // The overlapped struct.
SendCompletion); // Completion routine.
if(iResult == NO_ERROR)
{
// If the send happened synchronously, we can go ahead and delete the
// memory that we allocated.
// TODO: look at bytes transferred, and if they're less than the total
// then issue another send with the remainder.
if(HasOverlappedIoCompleted(pOvl))
{
// If I actually free this here, the completion routine gets garbage.
//free(pOvl);
m_dwSyncSend++;
}
else
{
m_dwAsyncSend++;
}
}
else
{
// If we got WSA_IO_PENDING, then that just means the completion routine
// will take care of it.
if(iResult != WSA_IO_PENDING)
{
Disconnect();
tracef(TT_REGULAR, 1,
"SOCKET_ERROR in CNetAsyncSocket::Send(), disconnecting, error code: %ld, on socket: %s:%ld",
iResult, GetIP(), GetPort());
// Don't need the payload anymore.
free(pOvl);
}
else
{
m_dwAsyncSend++;
}
}
}
最佳答案
文档说,如果操作可以立即完成,您将得到 0,如果不能立即完成,您将得到 SOCKET_ERROR(最后一个错误代码为 WSA_IO_PENDING)。无论哪种方式,对完成例程的调用都将排队。
因此,您所描述的行为符合预期,并且您应该释放缓冲区的唯一情况是发生 WSA_IO_PENDING 以外的错误。
关于c++ - 为什么 WSASend 返回 0 但仍调用完成例程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22434024/
我正在实现一个客户端/服务器对,通过重叠的IO和Windows中的完成例程,通过TCP/IP套接字进行通信。调试是使用两个VirtualBox虚拟机(一个客户端,另一个服务器)完成的。 CPU是四核。
抱歉,我的问题描述不当。 我的程序所做的是连接服务器、发送一些数据并关闭连接。我简化了我的代码如下: WSAStartup(MAKEWORD(2, 2), &wsaData); SOCKET s =
(问题是从msdn论坛复制过来的) MSDN 是这样说的: If you are using I/O completion ports, be aware that the order of call
我现在正在测试大缓冲区,我在 WSABUF 中设置它,然后调用 WSASend()。 不过,WSARecv() 只是一次性将它交回了那个大缓冲区。 这有意义吗? 对于大缓冲区,WSASend() 和
如果有人有时间,我需要一点帮助。我已经使用 IO 完成端口编写了一个 Web 服务器,但是我在发送大文件时遇到了一些问题。网页似乎加载正常,但在大文件传输期间,WSASend() 会在几分钟后失败并出
你们中的许多人都知道原始的“send()”不会将您要求的字节数写入线路。您可以轻松地使用指针和循环来确保您的数据已全部发送。 但是,在这种情况下,我看不到 WSASend() 和完成端口是如何工作的。
我发现 WSASend() 可能不会发送所有数据,例如,如果我要求它发送 800 字节,它可能只发送 600 字节。 现在我的问题是:发生这种情况的情况是否极其罕见,我不应该费心处理这种事件。还是我必
当使用 IOCP 时,如果我调用 WSASend(),我是否必须等待通知到达才能再次调用它,或者我可以多次调用它才能收到任何通知,例如,是否允许这样的事情: WSASend(); // Call it
我知道为了同时调用 WSASend(),我需要为每个调用提供一个唯一的 WSAOVERLAPPED 和 WSABUF 实例。但这意味着我必须为每次调用跟踪这些实例,这会使事情变得复杂。 我认为,如果我
我正在研究 Overlapped IO,突然发现似乎我是唯一一个不能鼓励 Completion callback 工作的人(所有声明都是关于:它工作但我不喜欢它) . 我的应用程序的想法是:客户端(t
如果我在调用它时不提供重叠结构或完成例程,我可以在阻塞模式下使用 WSASend()。但我的问题是:阻塞 WSASend() 调用是否会导致将通知数据包放入完成端口? 最佳答案 问题的格式不正确。我们
我无法找到 TCP WSASend 调用完成意味着什么的规范。 WSASend 操作的完成是否需要接收到 ACK 响应? 此问题与具有 200 毫秒 - 2 秒 ping 超时的较慢网络相关。调用 W
http://prntscr.com/2ctnoz 我正在 Hook WSAsend 函数并转储数据包。 ASCII 转储有效,但 HEX 转储有时会显示您在屏幕上看到的内容(FFFFFFDD),知道
如标题所示,在与 I/O 完成端口关联的套接字上的成功 WSASend 调用是否有可能由于任何其他原因不发布完成比线程结束? 我有一个奇怪的情况,它看起来没有为 WSASend 发布完成,这会导致套接
这是关于正在 Windows 上开发的 TCP 服务器。服务器将连接数千个客户端。服务器将持续以非阻塞异步方式向客户端发送随机大小的字节(可以说是 1 到 64KB 之间的任何字节)。 目前我在调用W
WSASend() 会立即返回是否发送数据。但是如何确保数据将被发送,例如我的 UI 中有一个按钮,按下时将发送 "Hello World!"。现在我想确保当用户点击这个按钮时,“Hello Worl
MSDN 声明“对于 Winsock 应用程序,一旦调用 WSASend 函数,系统就拥有这些缓冲区,应用程序可能无法访问它们。” 在服务器应用程序中,这是否意味着如果我想向多个客户端广播一条消息,我
希望你能帮帮我。 我正在尝试通过 TCP/IP 通过网络发送 1000 位的数据包,我希望也能够在 Cygwin 和 Windows 中使用重叠 I/O 技术。 在 Cygwin 中,我尝试使用“re
我目前正在用托管 C++ 编写一个 winsock 服务器端套接字。创建 LPWSAOVERLAPPED 对象并将其传递给 WSASend 函数后,我看不到在非阻塞操作完成时将其删除的位置(WSASe
我在 C++ 中挂接 WSASend 和 WSARecv,使用的方法与我用来挂接客户端的 WSASend 和 WSARecv 函数的方法相同。在客户端中,我能够从 WSASend/WSARecv 传递
我是一名优秀的程序员,十分优秀!