免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3269 | 回复: 12
打印 上一主题 下一主题

求助:select 问题! [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-04-10 10:20 |只看该作者 |正序浏览
在LINUX下建立一个套接字skfd,然后连接上SERVER,在使用select 等待套接字描述符skfd变为可读时,如果另外一个线程探测配置文件里面SERVER地址有变化,需要立即重新建立连接,我采用立即关闭现有套接字skfd,然后重新建立套接字skfd连接新的地址的方式,我想问的是:在我CLIENT端关闭skfd时,此时select正在skfd上等待,关闭后skfd后,select会立即返回吗?根据我测试的结果,好象select不会立即返回,一直会等待超时的,各位大侠能告诉我其中的原因吗?
如果我设置select的超时时间比较长,在超时之前,新的套接字skfd已经连接上了新的SERVER,此时新的SERVER给我发送信息时,我这边暂时没有反应,在select的超时返回后,居然回返回新的skfd可读,于是又可以正常的收发数据,请问这又是为什么?要知道这可是两个不同的套接字啊,虽然他们的描述符名字都是skfd,这让我想不通,这可能需要知道select()是如何实现的。
第三个问题:需要立即重新连接SERVER时,我采用立即关闭现有套接字skfd,然后重新建立套接字skfd连接新的地址的方式,这样的方法合适吗?因为此时设备最好不要中断,还有其他的模块要运行,有没有其他好的方法?

论坛徽章:
0
13 [报告]
发表于 2008-04-10 22:33 |只看该作者
呵呵,谢谢大家,各位的建议让我也有了点思路,明天上午再仔细的进行测试,来验证一下!
再次表示感谢!

论坛徽章:
0
12 [报告]
发表于 2008-04-10 14:08 |只看该作者
建立楼主改改SERVER端, 在接收到FIN包之后调用close(), 然后select()返回之后的read再检查是否读到了0, 如果是, 则退出这个线程.
试试看.

论坛徽章:
0
11 [报告]
发表于 2008-04-10 14:00 |只看该作者
如果楼主希望select的线程(A)马上返回并select新的skfd, 得设法让检测配置的线程(B)通过某种方式通知线程A.
1. 最简单的是用信号比如SIGHUP或SIGUSR1. 信号会中断select系统调用, 让select返回. 并设置error为EINTR;
2. 也可以用Unix域套接字(管道也可以). 线程B建立好新的skfd后.  用Unix域套接字通知线程A. 当然A要把Unix域套接字加到select的rfdset(FD_SET)里.

论坛徽章:
0
10 [报告]
发表于 2008-04-10 13:47 |只看该作者
原帖由 It'sGifted 于 2008-4-10 11:30 发表


我的看法,有点猜测的意思:

select是不是立即返回取决你的timeout,要是你设置不为0的话,它是要等的。调用select等待时,你已经把文件描述符设定在了三个fd_set中,这样相应位已经被设置了,但你重新连接后的sockfd值已经发生了变化,但select还是在等原来的描述符,所以不会立即返回。当select返回后,用sockfd再发送数据当然是可以的,因为它已经建立好连接了。


赞成这个分析.

论坛徽章:
0
9 [报告]
发表于 2008-04-10 13:05 |只看该作者
原帖由 cookis 于 2008-4-10 13:02 发表


如果是多线程操作一个fd .不会使用fd的计数增加的..除非是多进程

我搞混了,谢谢

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
8 [报告]
发表于 2008-04-10 13:02 |只看该作者
原帖由 net_robber 于 2008-4-10 10:46 发表
select没有检测到fd中有可读入的数据,因此等待超时返回

你关闭一个fd,只是引用数减一,如果这个fd正在被别的线程使用,那么他的引用数不会是0,因此不会真的关闭。
由此可以推断,你新建立的socket链接fd ...


如果是多线程操作一个fd .不会使用fd的计数增加的..除非是多进程

论坛徽章:
0
7 [报告]
发表于 2008-04-10 12:58 |只看该作者

回复 #6 cookis 的帖子

嗯, 我赞成你的解释.

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
6 [报告]
发表于 2008-04-10 12:41 |只看该作者
我也猜猜:

      开始创建的fd = 5. 当你关闭后.当前进程空间的文件描述符的最小可用值就变成5..
      你马上又创建一个socket..此时新建的socket 就是5 ..但select fd_set 里边的fd
      值还是5, 导致后来你说的"居然回返回新的skfd可读,于是又可以正常的收发数据"
如果SERVER也调用了close 那么你这边的可读.或许是新连接的SYS 也或许是SERVER
发过来的FIN

论坛徽章:
0
5 [报告]
发表于 2008-04-10 12:24 |只看该作者
说说我的看法, 你select()在等待的时候, 另外一个线程去关闭了这个套接字, 那么你当前进程执行的是主动关闭, 此时SERVER也只是到了CLOSE_WAIT状态, 此时如果你的SERVER端不调用close, 你的select()就不会检测到读套接口有数据到达.
我认为你应该看看你的SERVER端在接收到了FIN包之后是怎样处理的, 如果立即调用close()完成最后的关闭, 则CLIENT的select()就会返回.
  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP