我打算编写一个程序来处理来自TCP / IP连接和来自共享内存队列的请求。这意味着程序应该阻塞,直到队列中有请求或套接字上有输入。然后它将处理请求并继续。有没有办法在单个线程中执行此操作?我的意思是某种select
同时使用信号量和套接字。在我的情况下,延迟很重要,我也不想做一个忙碌的等待。该程序将在Windows上运行。感谢。
答案 0 :(得分:3)
一种方法是使用重叠I / O并使用hEvent
机制来发出I / O完成信号。然后,您可以使用hEvent
API等待队列信号量和WaitForMultipleObjects()
/ s。
另一种方法是使用重叠的I / O和完成例程。然后,您可以在WaitForSingleObectEx()
API的循环中等待信号量,并将bAlertable
参数设置为true,以便线程可以处理排队的完成例程,例如:
while(WAIT_IO_COMPLETION!=WaitForSingleObjectEx(queueSema,INFINITE,true)){
[deque object and handle it];
};
这两种方案都允许您设置超时以轮询服务器以保持连接打开和/或检查它是否已关闭。
答案 1 :(得分:2)
Libevent是一种抽象I / O事件的方法,它有一种手动触发事件的方法。
使用libevents设置基于文件的事件如下所示(从文档中复制):
void callback_func(evutil_socket_t fd, short what, void *arg) { ... }
struct event *ev1, *ev2;
struct event_base *base = event_base_new();
/* The caller has already set up fd1, fd2 somehow, and make them
nonblocking. */
ev1 = event_new(base, fd1, EV_TIMEOUT|EV_READ|EV_PERSIST, callback_func,
(char*)"Reading event");
ev2 = event_new(base, fd2, EV_WRITE|EV_PERSIST, callback_func,
(char*)"Writing event");
event_add(ev1, NULL);
event_add(ev2, NULL);
如果要创建与任何文件描述符无关的事件,请传递fd的-1
符号:
ev = event_new(base, -1, EV_PERSIST | EV_READ, callback_func, NULL);
event_add(ev, NULL);
现在,不是提高信号量,而是触发事件:
event_active(ev, EV_WRITE, 0);
答案 2 :(得分:1)
Windows等待几种可能发生的事情之一的方式是WaitForMultipleObjectsEx
。你给它一组Windows"处理"这可以成为"发出信号" (这些类型的句柄称为同步对象),当它们中的任何一个被发出信号时,该函数返回并告诉你它是哪一个。
问题是,在WinSock库中实现的套接字不是Windows句柄。您无法将其放入WaitForMultipleObjectsEx
数组中。
幸运的是,WinSock提供了一个函数WSAEventSelect
,它可以将套接字链接到Windows事件对象。事件对象是最简单的同步对象类型。在这种情况下,当套接字准备好被读取时,你会要求它发出事件对象的信号(FD_READ
)。然后你将事件对象放在信号量旁边的数组中。
Windows信号量已经是同步对象 - 请参阅MSDN中的CreateSemaphore
。当计数大于0时,它会发出信号。(这是您对信号量的期望。)
如果您不了解同步对象的全部概念并且阅读MSDN没有帮助,我建议Jim Beveridge的书 Win32中的多线程应用程序。它是一本旧书,因此它没有套接字或信号量,但它解释了如何使用事件对象,互斥体和WaitForMultipleObjects
。那么套接字和信号量很容易理解。