0

我不是网络编程方面的专家。我基本上有两种客户,他们有不同的超时时间。我应该使用带有连接套接字的 UDP 进行客户端-服务器通信。

问题是双重的:

a) 我需要将任何客户端(或者套接字)在 t1 秒内没有响应的情况标记为已死亡。如果 read_fd_set 中的任何套接字都没有在超时值内读取任何内容,则使用 select 将超时。那么,如何让任何一个在相当长一段时间内没有数据读取的套接字超时?

  • 目前,每当 select 返回时,我自己都会跟踪哪些套接字正在响应,哪些没有。我将 t1.tu_sec 添加到每个客户端(套接字)的单独经过时间。然后,我手动关闭并从 FD_SET 中排除在 (n) * (t1.tu_sec) 时间内没有响应的套接字。这是一个足够好的方法吗?

b) 主要问题是有两种客户端有不同的超时时间,t1 和 t2。我该如何处理?

  • 我可以在同一个循环中为两种客户端设置两个 select() 吗?没有线程会导致饥饿吗?在这种情况下是否建议(甚至需要)使用线程?

我已经在网上漫游了很多年了!

任何帮助深表感谢。

4

3 回答 3

1

我想到的一个快速解决方案是将集合中的套接字按剩余时间排序,直到最近的超时。

使用select将超时设置为剩余的最小时间,从集合中删除/关闭/删除超时套接字,然后重复。

因此,在伪代码中它可能如下所示:

C = collection of structs ( socket, timeout, time_remaining := timeout )

while (true) {
    sort_the_collection_by_time_remaining
    next_timeout = min(time_remaining in C)
    select ( sockets in C, next_timeout )
    update_all_time_remaining_values
    remove_from_C_if_required  //if timeout occured
}
于 2012-09-26T11:06:37.123 回答
1

这只是一种非常常见的模式的特例,其中选择/轮询循环与计时器集合相关联。

您可以使用任务的优先级队列,按下一个(绝对)触发时间排序;选择超时总是然后只是队列前面的绝对时间。

  • 当 select 超时(就在下一次迭代之前,如果您的任务可能需要很长时间才能完成),获取当前时间,将每个应该已经执行的任务拉出队列,然后执行它
  • (某些)任务需要重新安排,因此请确保它们可以在您执行此操作时改变优先级队列

那么你的逻辑很简单:

  • 在读取时,将套接字标记为忙
  • 在计时器执行时,将套接字标记为空闲
    • 如果它已经空闲,这意味着自上次计时器到期后没有收到任何内容:它已经死了
于 2012-09-26T12:37:26.243 回答
0

只需一个select电话即可轻松解决。对于每个套接字都有两个与超时相关的值:实际超时;以及超时前的时间。然后每 0.1 秒(或类似时间)倒计时一次“超时前的时间”,当它达到零时关闭套接字。如果套接字在超时之前接收到流量,只需将“超时前的时间”重置为超时值并再次开始向下计数。

于 2012-09-26T11:05:27.267 回答