[英]Python accepted socket connection not closing
我編寫了一個 Pi 硬件接口服務器 (phis),它使用 http 協議來控制連接到我的 Raspberry Pi 的硬件(繼電器、模擬測量等)。 它處理簡單的請求並以純文本響應。 多年來它一直在完美運行,我已經為系統編寫了廣泛的基於瀏覽器的界面。 這是基本結構:
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 時會出現問題。 stream 啟動得很好,響應已發送,我可以建立更多連接並發出新命令,但 client_connection.close() 從未真正關閉連接,瀏覽器只是坐在那里等待更多永遠不會出現的東西。 phis 仍在接受新連接並為這些連接提供服務,但如果我使用請求“http://pi:4000/exit”退出服務器,它會干凈利落地執行,但除非我先啟動,否則它不會再次啟動(正在使用套接字)發出停止 mjpg_streams 的請求(也可以正常工作)。
mjpg_streamer 已經在(似乎是)守護進程后台模式下啟動,但在我嘗試讓它工作時,我已經發出命令在每個 python“啟動你的背景孩子並讓它運行”方法中啟動它我能找到( os.system()、subprocess.Popen()、os.fork() 和 os.fork() 兩次,os.setsid() 介於兩者之間)。 沒有任何效果。
If it matters, I'm actually calling a perl script from the phis that starts mjpg_steamer with command line arguments based on arguments passed to the perl script.
我對此進行了很多搜索,發現其他連接不會關閉,但連接不會完美關閉,除非在連接處於活動狀態時生成了一些基於套接字的后台應用程序。 有人知道出了什么問題嗎?
在這篇文章中找到了答案(我看到它的那一刻“Duh”!)
我忘記關閉分叉子進程中連接和監聽的 sockets,這些子進程由衍生的守護進程繼承,只要它運行就保持打開狀態。 這是我用來生成將繼續運行(守護進程)的進程的代碼:
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()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.