Python 接受的套接字连接未关闭
Python accepted socket connection not closing
我编写了一个 Pi 硬件接口服务器 (phis),它使用 http 协议来控制连接到我的 Raspberry Pi 的硬件(继电器、模拟测量等)。它处理简单的请求并以纯文本响应。它多年来一直完美无缺地工作,我已经为系统编写了广泛的 browser-based 接口。这是基本结构:
listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
listen_socket.bind((HOST, PORT))
listen_socket.listen(1)
read_list = [listen_socket]
while True:
readable, writeable, errored = select.select(read_list,[], [], 2)
if len(readable) == 0: # select timed out
continue
client_connection, client_address = listen_socket.accept()
try:
request = client_connection.recv(1024)
except Exception:
print "Exception trying to recv, %s" % time.strftime(date_format)
sys.exc_clear()
client_connection.close()
continue
words = request.split()
http_response = """\
HTTP/1.1 200 OK
"""
try:
client_connection.sendall(http_response)
except Exception:
print "Exception trying to send 1, %s" % time.strftime(date_format)
sys.exc_clear()
client_connection.close()
continue
http_response = """\
Content-Type: text/plain; charset=utf-8
"""
# perform some action and add text to the http_response (like current CPU temperature, etc)
try:
client_connection.sendall(http_response)
except Exception:
# log the error, then...
sys.exc_clear()
client_connection.close()
continue
client_connection.close()
if words[1] == '/exit':
sys.exit(0)
命令启动时出现问题mjpg_streamer。流开始很好,响应已发送,我可以建立更多连接并发出新命令,但 client_connection.close() 从未真正关闭连接,浏览器只是坐在那里等待更多永远不会到来的东西。 phis 仍在接受新连接并为这些连接提供服务,但是如果我使用请求“http://pi:4000/exit”退出服务器,它会干净利落,但它不会再次启动(正在使用套接字),除非我先发出停止请求 mjpg_streams(也可以正常工作)。
mjpg_streamer 已经在(似乎是)守护进程后台模式下启动,但在我尝试让它工作的过程中,我已经发出命令在每个 python 启动它你的背景 child 并保留它 运行” 我可以找到的方法 (os.system(), subprocess.Popen(), os.fork() 和 os.fork () 两次,中间有 os.setsid())。没有任何效果。
如果重要的话,我实际上是从 mjpg_steamer 开始的 phis 调用一个 perl 脚本,命令行参数基于传递给 perl 脚本的参数。
我在谷歌上搜索了很多,发现其他人的连接不会关闭,但连接不会完全关闭,除非在连接处于活动状态时生成一些后台 socket-based 应用程序。任何人都知道出了什么问题吗?
在 中找到了答案(我看到它的那一刻就“呸”了一声!)
我忘记关闭分叉子进程中的已连接和正在侦听的套接字,这些套接字由生成的守护进程继承并在运行期间一直保持打开状态。这是我用来生成一个进程的代码,该进程将被保留 运行(守护进程):
def spawnDaemon(syscmd):
# do the UNIX double-fork magic, see Stevens' "Advanced
# Programming in the UNIX Environment" for details (ISBN 0201563177)
try:
pid = os.fork()
if pid > 0:
# parent process, wait for first child, then return and keep running
os.wait()
#print "first parent returning"
return
except OSError, e:
print >>sys.stderr, "fork #1 failed: %d (%s)" % (e.errno, e.strerror)
sys.exit(1)
# close the copy of the socket the request came in on
client_connection.close()
# close the copy of the server's main listening socket
listen_socket.close()
# change process group to detach the child (mjpeg_streamer) from the parent phis
os.setsid()
# do second fork
#print "trying second fork"
try:
pid = os.fork()
if pid > 0:
# exit from second parent
#print "second parent exiting"
sys.exit(0)
except OSError, e:
print >>sys.stderr, "fork #2 failed: %d (%s)" % (e.errno, e.strerror)
sys.exit(1)
# execute the command
os.system(syscmd)
# all done, exit 2nd child
#print "exiting after executing syscmd"
sys.exit(0)
# spawnDaemon()
我编写了一个 Pi 硬件接口服务器 (phis),它使用 http 协议来控制连接到我的 Raspberry Pi 的硬件(继电器、模拟测量等)。它处理简单的请求并以纯文本响应。它多年来一直完美无缺地工作,我已经为系统编写了广泛的 browser-based 接口。这是基本结构:
listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
listen_socket.bind((HOST, PORT))
listen_socket.listen(1)
read_list = [listen_socket]
while True:
readable, writeable, errored = select.select(read_list,[], [], 2)
if len(readable) == 0: # select timed out
continue
client_connection, client_address = listen_socket.accept()
try:
request = client_connection.recv(1024)
except Exception:
print "Exception trying to recv, %s" % time.strftime(date_format)
sys.exc_clear()
client_connection.close()
continue
words = request.split()
http_response = """\
HTTP/1.1 200 OK
"""
try:
client_connection.sendall(http_response)
except Exception:
print "Exception trying to send 1, %s" % time.strftime(date_format)
sys.exc_clear()
client_connection.close()
continue
http_response = """\
Content-Type: text/plain; charset=utf-8
"""
# perform some action and add text to the http_response (like current CPU temperature, etc)
try:
client_connection.sendall(http_response)
except Exception:
# log the error, then...
sys.exc_clear()
client_connection.close()
continue
client_connection.close()
if words[1] == '/exit':
sys.exit(0)
命令启动时出现问题mjpg_streamer。流开始很好,响应已发送,我可以建立更多连接并发出新命令,但 client_connection.close() 从未真正关闭连接,浏览器只是坐在那里等待更多永远不会到来的东西。 phis 仍在接受新连接并为这些连接提供服务,但是如果我使用请求“http://pi:4000/exit”退出服务器,它会干净利落,但它不会再次启动(正在使用套接字),除非我先发出停止请求 mjpg_streams(也可以正常工作)。
mjpg_streamer 已经在(似乎是)守护进程后台模式下启动,但在我尝试让它工作的过程中,我已经发出命令在每个 python 启动它你的背景 child 并保留它 运行” 我可以找到的方法 (os.system(), subprocess.Popen(), os.fork() 和 os.fork () 两次,中间有 os.setsid())。没有任何效果。
如果重要的话,我实际上是从 mjpg_steamer 开始的 phis 调用一个 perl 脚本,命令行参数基于传递给 perl 脚本的参数。
我在谷歌上搜索了很多,发现其他人的连接不会关闭,但连接不会完全关闭,除非在连接处于活动状态时生成一些后台 socket-based 应用程序。任何人都知道出了什么问题吗?
在
我忘记关闭分叉子进程中的已连接和正在侦听的套接字,这些套接字由生成的守护进程继承并在运行期间一直保持打开状态。这是我用来生成一个进程的代码,该进程将被保留 运行(守护进程):
def spawnDaemon(syscmd):
# do the UNIX double-fork magic, see Stevens' "Advanced
# Programming in the UNIX Environment" for details (ISBN 0201563177)
try:
pid = os.fork()
if pid > 0:
# parent process, wait for first child, then return and keep running
os.wait()
#print "first parent returning"
return
except OSError, e:
print >>sys.stderr, "fork #1 failed: %d (%s)" % (e.errno, e.strerror)
sys.exit(1)
# close the copy of the socket the request came in on
client_connection.close()
# close the copy of the server's main listening socket
listen_socket.close()
# change process group to detach the child (mjpeg_streamer) from the parent phis
os.setsid()
# do second fork
#print "trying second fork"
try:
pid = os.fork()
if pid > 0:
# exit from second parent
#print "second parent exiting"
sys.exit(0)
except OSError, e:
print >>sys.stderr, "fork #2 failed: %d (%s)" % (e.errno, e.strerror)
sys.exit(1)
# execute the command
os.system(syscmd)
# all done, exit 2nd child
#print "exiting after executing syscmd"
sys.exit(0)
# spawnDaemon()