当线程A关闭套接字对的末尾时,为什么windows select()并不总是通
我在
Windows XP(SP3)下遇到的情况让我疯狂,而且我已经到了我的系绳的末端,所以也许有人可以提供一些灵感.
我有一个C网络程序(非GUI).该程序用于在Windows,MacOS / X和Linux下编译和运行,因此它使用select()和非阻塞I / O作为其事件循环的基础. 除了网络功能外,该程序还需要从stdin读取文本命令,并在stdin关闭时正常退出.在Linux和MacOS / X下,这很容易 – 我只是在我的read fd_set中包含STDIN_FILENO来select(),而select()在stdin关闭时返回.我检查FD_ISSET(STDIN_FILENO,& readSet)是否为真,尝试从stdin读取一些数据,recv()返回0 / EOF,所以我退出进程. 另一方面,在Windows下,您无法选择STDIN_FILE_HANDLE,因为它不是真正的套接字.您也不能对STDIN_FILE_HANDLE执行非阻塞读取.这意味着无法从主线程读取stdin,因为ReadFile()可能无限期地阻塞,导致主线程停止提供其网络功能. 没问题,我说,我只会产生一个线程来处理stdin.该线程将在无限循环中运行,在ReadFile(stdinHandle)中阻塞,并且只要ReadFile()返回数据,stdin线程就会将该数据写入TCP套接字.该套接字的另一端将由主线程选择(),因此主线程将看到通过连接进入的stdin数据,并以与其他任何操作系统相同的方式处理“stdin”.如果ReadFile()返回false以指示stdin已关闭,则stdin-thread仅关闭其套接字对的结尾,以便主线程将通过select()通知,如上所述. 当然,Windows没有一个很好的socketpair()函数,所以我不得不使用listen(),connect()和accept()(如CreateConnectedSocketPair()函数here中所见.)但我做到了一般而言,它似乎有效. 问题是它不能100%工作.特别是,如果stdin在程序启动的几百毫秒内关闭,大约一半时间主线程没有得到任何关于套接字对的stdin-end已经关闭的通知.我的意思是,我可以看到(通过我的printf() – 调试)stdin线程在其套接字上调用closesocket(),我可以看到主线程是select() – 关联socket(即套接字对的另一端),但是select()永远不会返回……如果它确实返回,由于某些其他套接字选择了ready-for-whatever,FD_ISSET(main_thread_socket_for_socket_pair,& readSet) )返回0,好像连接没有关闭. 在这一点上,我唯一的假设是Windows的select()实现中存在一个错误,导致主线程的select()没有注意到套接字对的另一端已被stdin-thread关闭.有另一种解释吗? (请注意,此问题已在Windows 7下报告,尽管我没有在该平台上亲自查看过它) 解决方法
仅仅为了记录,这个问题完全是一个完全不同的问题,与线程,Windows或stdin无关.实际问题是进程间死锁,其中父进程被阻塞,等待子进程退出,但有时子进程会被同时阻塞,等待父进程为它们提供一些数据,所以什么都不会前进.
向所有人道歉,浪费你的时间在红鲱鱼身上;如果有一种标准方法可以将这种情况视为无根据,请告诉我,我会这样做. -Jeremy (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- Windows – 任何人都可以解释为什么“git status”在linux上
- windows – 批处理文件中的“%1”和“%2”是什么?
- Windows – 如何从32位WOW进程中的64位进程中枚举模块
- windows-phone-7 – 新的Windows 7手机平台是否使用Silverl
- .net – EntityFramework.dll与System.Data.Entity.dll –
- 从非交互式进程(Windows服务,计划任务等)在WinServer 2008中
- windows系统以及linux系统的优缺点以及区别
- .net – MEF加载在GAC中需要DLL的DLL
- 部署 – 部署时不加载RazorGenerator.Mvc.dll
- windows-server-2003 – 可以使Robocopy跳过打开的文件吗?