我正在编写一个程序,我在while(1)循环中运行,该循环在select调用时阻塞。我的程序侦听多个客户端连接的服务器套接字。我还连接到不同的服务器套接字。所以,我充当客户端和服务器。
它是一种基于事件的设计,仅对其在套接字上接收的事件/消息起作用。到目前为止一切都很好。
这个设计有效,到目前为止我没有遇到任何问题。
我的问题是,基于我在套接字上收到的一些消息,我调用了一个在for循环中运行的函数foo,并做了一些占用大量时间(例如40-50秒)的工作。现在,当我这样做时,我不会回到while(1)循环,我在选择呼叫时被阻止。在40-50秒的这段时间里,我不会对我在其他插座上收到的任何消息/事件采取行动。
有没有办法打破我的foo函数,以便我只处理它的某些部分,然后返回我的while(1)循环,检查套接字,如果没有任何内容,则继续处理foo()功能。我的问题是,如果套接字上没有任何内容,则套接字调用将被阻止,我将无法处理foo()。
我不能在select中使用time参数,因为我已经将其用于其他功能吗?
编辑:这是一个正常的设计,让主循环在while(1)循环中运行,该循环仅在select调用上被阻塞,并根据它在连接的不同套接字上收到的消息执行不同的操作到?答案 0 :(得分:1)
这里通常的方法是在一个线程中运行foo()
- 这样它就独立于循环。循环开始了。
你应该做的是注意线程当前正在运行的某个地方或有人可能会发送大量“启动”消息,这会导致服务器启动越来越多的线程直到它死亡。
另一种方法是将“等待命令”循环拆分为一个函数,该函数只进行一次选择并处理一个你可能得到的命令加上一个循环,它会无休止地调用这个新函数。
这样,您可以偶尔从foo()
开始新的“一次性”功能。
答案 1 :(得分:1)
你应该创建一个线程来运行你的函数,而select
将继续等待事件。
没有线程,暂停&恢复一个过程但你可以像计算机那样做:当你退出foo
时,保留一些空间来存储处理的上下文。在下一次调用时,它应检查上下文中要处理的数据
此外,也许您应该考虑将套接字信息推送到稍后要处理的消息的管道/队列中。
关于"时间参数"我猜你在谈论select
超时。它可以用于不同的事件,但你必须解决它,即计算你正在监听的所有事件的最小超时(如果你处于无限循环中,你将不得不在每个循环上重新计算它)。
答案 2 :(得分:0)
最好的解决方案是启动一个新线程(甚至是新进程的fork
)。
如果您不想这样做,您可以在工作时将您的选择更改为非阻止。您还需要定期拨打您的选择。
int mySelectHandler(); // Returns false if SELECT would block
// Main loop
while (1) {
mySelectHandler(); // Check for new connections and messages
}
int bigWork() {
int prevStatus = <current select status, blocking or non-blocking>;
setStatus(NONBLOCKING);
for (<some condition)) {
<do some work>
while (mySelectHandler()) // Check for new connections and messages
;
}
setStatus(prevStatus);
}
这种方法有一个警告:如果在第一个呼叫结束之前有第二次呼叫bigWork(),那么第一个呼叫将被延迟,直到第二个呼叫被处理完毕。