【发布时间】:2017-08-06 21:17:17
【问题描述】:
我有一个套接字列表。(打开的连接)
我有 n 个工作线程。
线程循环:
while (1)
{
_this.result = GetQueuedCompletionStatus(a_server.server_iocp, &_this.numberOfBytesTransfered,
&_this.completionKey, (OVERLAPPED**)&_this.iocp_task, INFINITE);
...
}
我有这个简单的结构:
struct iocp_send_global :public iocp_task<IOCP_SEND_GLOBAL> {
OVERLLAPED ov; //overlapped struct at top
std::atomic_uint32_t ref;
bool decr_ref(){ return ref.fetch_sub(1, std::memory_order_acq_rel) == 1;}
//packet data here
}
...
这是“广播”功能:
iocp_send_global * packet = new iocp_send_global;
[set packet data here]
for(int i=0;i<connectionsCount;++i){
WSASend(connections[i],...,&packet,...); //posting same packet to all connections
}
我想在 GetQueuedCompletionStatus 调用返回重叠结果后在工作循环中执行此操作;
if (_this.iocp_task->type == IOCP_SEND_GLOBAL) {
auto* task = (iocp_send_global*)_this.iocp_task;
if (!task->decr_ref()) {
_this.iocp_task = nullptr;
//dont delete the task yet,
//all send post must finish first
//[all posts share the same buffer]
}
else {
//delete the task containing the send data after all send posts finished
delete _this.iocp_task;
_this.iocp_task = nullptr;
}
}
根据我在 Microsoft WSASend 文档中阅读的内容,每个 WSASend 重叠调用都传递了自己的 OVERLAPPED 结构,但是当我 WSASend 相同的缓冲区时这是否有效?
谢谢!
【问题讨论】:
-
只有当您不关心返回状态和 numberOfBytesTransfered(并且确切地知道哪个套接字 io 完成)时,您才能在多个请求中使用相同的
OVERLAPPED缓冲区)。如果在这个结构上正确实现 addref/release 逻辑 -
老兄,谢谢,我不在乎这些东西。只有它的 decr_ref,当我发布发送时,我将 ref 设置为 no。连接数
-
请将其发布为 Answare,以便我接受!
-
您需要清楚了解
OVERLAPPED的用途。这是IO_STATUS_BLOCK的存储空间,其中存储了操作结果和附加信息(通常是 numberOfBytesTransfered)。如果在多个 IO 请求中使用相同的OVERLAPPED- 此信息将未定义(多次覆盖)。所以通常它必须是每个操作唯一的。它还允许指向附加信息的指针(比如指向套接字)但是如果你不关心并且不需要所有这些 - 可以使用正式的和相同的OVERLAPPED- 最低要求 - 内存桅杆在最后一次操作完成之前一直有效 -
并且在您的代码中不可见您如何在
WSASend之前增加(addref)对结构的引用而不检查它的结果。