我有一个进程,我的代码从subprocess.Popen()
启动,尝试连接到我的代码也正在侦听的套接字。问题是如果代码首先开始侦听此套接字,则无法启动子进程。它已被sock.accept()
阻止,当sock.accept()
超时时,显然没有在subprocess.Popen()
运行时收听。如果代码首先启动子进程,它会尝试连接到套接字,但在任何代码能够侦听之前都会失败。
现在..有关我如何做到这一点的任何想法?看起来我需要以非阻塞的方式开始监听,然后启动进程,但我有点困惑,因为即使我使用select()来处理队列,最终调用sock.accept()并且因此阻止代码......我想。
无论如何,某个方向会非常方便!我宁愿不这样做,但如果它让生活更轻松,我也不会觉得使用Twisted。
编辑1: 我会尝试以代码的方式获得一些东西,我必须查看我的旧提交以找到工作版本。基本上,我不认为我的代码是问题。我想我只是错误地实施它。
例如,如果我启动我的套接字侦听器并手动在shell中启动这个subprocess.Popen()进程就可以了。这是因为shell已经在监听。我相信我的问题只是鸡和鸡蛋问题。在我的代码中,在单个代码路径中,如果我首先启动该进程,它会立即失败,因为没有套接字服务器正在侦听 。但是,如果我首先启动套接字服务器,它会超时,因为它阻塞并且没有子进程在完成阻止之前启动。我相信,我的解决方案在于非阻塞代码,但我对如何正确实现这一点非常不熟悉。我看到很多提及select()
但他们看起来像他们会在同一点阻止sock.accept()
。我说“看起来像”因为我还没有实现select()
版本。我可能在这里错了,如果我,请告诉我。
编辑2: 这是代码的套接字部分。请注意,目前设置为非阻塞..
90 # Create our socket stream to listen on.
91 serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
92
93 #serv.settimeout(5)
94 serv.setblocking(0)
95
96 # Bind the address.
97 serv.bind(('', self.PORT))
98 serv.listen(5)
99
100 try:
101 # Now start listening for a connection!
102 (self._sock, remote_address) = serv.accept()
103 except socket.timeout:
104 logger.debug('Socket connection failed!')
105 raise DBGPServerNotFoundError(
106 'No connection was established coming from '
107 '"%(address)s:%(port)i".' % {
108 'address':self.ADDRESS,
109 'port':self.PORT,
110 })
111 else:
112 logger.debug('Socket connection established! The other end of '
113 'the connection is at "%s:%i".' % remote_address)
114 finally:
115 serv.close()
这是错误..
File "/home/lee/projects/vim-debug/repo/vimbug/dbgp.py", line 100, in connect
(self._sock, remote_address) = serv.accept()
File "/usr/lib/python2.6/socket.py", line 197, in accept
sock, addr = self._sock.accept()
error: [Errno 11] Resource temporarily unavailable
子进程启动代码在一个不同的模块中(具体是一个单元测试),但这里有很好的衡量标准。请注意,con
是容器对象,con.connect()
是上述代码的函数。
56 con.connect()
57 pydbgp_proc = subprocess.Popen(
58 ('pydbgp.py', '-d', 'localhost:%i' % OPTIONS['pydbgp_port'],
59 OPTIONS['debug_file']),
60 stdout=subprocess.PIPE,
61 stderr=subprocess.PIPE,)
编辑3:在调用 sock.accept()
之前,尝试重新编写代码以尝试连接到套接字。我们会看看它是否失败了:))
编辑4: 好的。重写了一下代码..仍然有同样的错误。思考? (另外..这个编辑垃圾变得越来越大..在stackoverflow中有一些首选的方式来进行这些大的更新/编辑吗?
代码:
77 def listen(self):
78 # Create our socket stream to listen on.
79 serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
80
81 #serv.settimeout(5)
82 serv.setblocking(0)
83
84 # Bind the address.
85 serv.bind(('', self.PORT))
86 serv.listen(5)
87 self.serv = serv
88
89 def accept(self):
90 (newsock, newaddr) = self.serv.accept()
致电代码:
57 con.listen()
58 pydbgp_proc = subprocess.Popen(
59 ('pydbgp.py', '-d', 'localhost:%i' % OPTIONS['pydbgp_port'],
60 OPTIONS['debug_file']),
61 stdout=subprocess.PIPE,
62 stderr=subprocess.PIPE,)
63 con.accept()
错误:
File "/home/lee/projects/vim-debug/repo/vimbug/dbgp.py", line 90, in accept
(newsock, newaddr) = self.serv.accept()
File "/usr/lib/python2.6/socket.py", line 197, in accept
sock, addr = self._sock.accept()
error: [Errno 11] Resource temporarily unavailable
思想?
编辑5:我将接受功能更改为以下select()
实施,导致'Not ready..?'
被打印。
89 def accept(self):
90 rfds, wfds, xfds = select.select([self.serv], [], [], 1)
91
92 if self.serv in rfds:
93 print 'Read ready..?'
94 (newsock, newaddr) = self.serv.accept()
95 else:
96 print 'Not ready..?'
答案 0 :(得分:1)
Doug Hellman的Python Module of the Week是一个很好的地方,可以找到模块基本用法的介绍,例如subprocess。
如果做不到这一点,导致问题的一些代码将帮助我们回答您的问题。
答案 1 :(得分:1)
您是否在监听代码中设置了socket.setblocking(0)
?
在您生成监听服务器之后,您应该能够通过select()
调用来读取状态...在debian lenny和python 2.5下运行正常的示例...
import socket
import select
SERVER_SOCKADDR = ("", 424242)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setblocking(0) # <------------------
server.bind(SERVER_SOCKADDR)
server.listen(5)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.setblocking(0)
result = client.connect_ex(SERVER_SOCKADDR)
rfds, wfds, xfds = select.select([server], [client], [], 1)
if server in rfds:
print "Server socket: accept does not block"
sockfd, addr = server.accept() # sockfd.send() and sockfd.recv() to
# write and read the stream...
sockfd.setblocking(0)
print sockfd, addr
else:
print "Server socket: accept blocks"
if client in wfds:
print "Client socket: write does not block"
else:
print "Client socket: write blocks"
server.close()
client.close()
当我跑那个......
[mpenning@Bucksnort ~]$ python socket_test.py
Server socket: accept does not block
<socket._socketobject object at 0xb75764c4> ('127.0.0.1', 35810)
Client socket: write does not block
[mpenning@Bucksnort ~]$
答案 2 :(得分:0)
有很多方法可以解决这个问题。最简单的是子进程在连接之前等待几秒钟。
目前还不清楚为什么要这样做,你能否填写我们的目标?