如何启动连接到您正在监听的套接字的进程?

2024-10-01 15:29:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个进程,我的代码正从subprocess.Popen()启动,它试图连接到我的代码也在监听的套接字。问题是如果代码首先开始监听这个套接字,它就不能启动子进程。它被sock.accept()阻塞,当sock.accept()超时时,它显然没有在{}运行时进行监听。如果代码首先启动子进程,它将尝试连接到套接字,但在任何代码都能够侦听它之前失败。在

现在。。你觉得我该怎么做吗?似乎我需要以非阻塞的方式开始监听,然后启动进程,但我有点困惑,因为即使我使用select()来处理队列,最终还是会这样袜子。接受因此,块和代码被称为。。。我想。在

无论如何,找个方向会很方便的!我不喜欢,但如果这让生活更轻松,我也不赞成使用Twisted。在

编辑1: 我将尝试在代码方面做些什么,我必须查看我以前的提交,以找到一个有效的版本。基本上,我不认为我的代码是问题所在。我想我只是执行错了。在

例如,如果我启动我的套接字侦听器并在shell中手动启动子流程.Popen()过程它连接得很好。这是因为外壳已经在监听。我相信我的问题只是鸡和蛋的问题。在我的代码中,在一个代码路径中,如果我先启动进程,它会立即失败,因为还没有套接字服务器在侦听。但是,如果我先启动socket服务器,它会超时,因为它正在阻塞,在完成阻塞之前,不会启动任何子进程。我相信,我的解决方案在于非阻塞代码,但我对如何正确实现这一点非常陌生。我看到很多人提到select(),但它们看起来似乎它们会在同一点上阻塞sock.accept()。我说“look like”是因为我还没有实现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()

错误就在这里。。在

^{pr2}$

子进程启动代码在不同的模块中(特别是单元测试),但在这里这是一个很好的衡量标准。注意,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:我将accept函数改为下面的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..?'

Tags: 代码debugself编辑进程addresssocketconnection
3条回答

有很多方法可以解决这个问题。最简单的方法是子进程在连接之前等待几秒钟。在

不清楚你为什么这么做,你能告诉我们你的目标吗?在

您是否在侦听代码中设置socket.setblocking(0)?在

生成侦听服务器后,您应该能够通过select()调用读取状态。。。在DebianLenny和Python2.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()

当我运行它的时候。。。在

^{2}$

doughellman的Python Module of the Week是一个很好的地方,可以找到对模块基本用法的介绍,比如subprocess。在

否则,一些导致问题的代码将帮助我们回答您的问题。在

相关问题 更多 >

    热门问题