学到了Python的网络编程,练习socket的使用,用它编写一个简单的服务监听程序。
用套接字监听TCP请求的程序
"""
2020-11-18 16:54:08+0800 chenxizhan new
"""
import os.path
import socket
print('pid:', os.getpid())
def task(host, port):
s = socket.socket()
print('监听:{}:{}'.format(host, port))
s.bind((host, port))
s.listen()
while True:
s2, (host, port) = s.accept()
print('收到连接请求', host, port)
s2.close()
def main():
host, port = ('127.0.0.1', 9090)
task(host, port)
if __name__ == "__main__":
main()
print('done')
但Ctrl-C无法终止程序,只能通过命令行窗口的方式(或者使用kill命令)它。
ps:Python socket有非阻塞模式、超时模式、阻塞模式三种,这种情况是阻塞模式下发生的。
原因
socket.accept() 的文档中有如下描述:
Changed in version 3.5: If the system call is interrupted and the signal handler does not raise an exception, the method now retries the system call instead of raising an InterruptedError exception (see PEP 475 for the rationale).
就是说套接字的accept()方法等待连接的时候,键盘中断信号被Python“吃掉“了。
解决方法
把socket放到守护线程中执行,主线程捕捉到信号后退出,程序就会随之退出。
The entire Python program exits when no alive non-daemon threads are left.
""" 一个简单的HTTP服务器
2020-11-18 16:54:08+0800 chenxizhan new
"""
import os.path
import socket
import threading
import time
print('pid:', os.getpid())
def task(host, port):
s = socket.socket()
print('监听:{}:{}'.format(host, port))
s.bind((host, port))
s.listen()
while True:
s2, (host, port) = s.accept()
print('收到连接请求', host, port)
s2.close()
def main():
host, port = ('127.0.0.1', 9090)
t = threading.Thread(target=task, args=(host, port))
t.daemon = True
t.start()
while True:
try:
time.sleep(10)
except KeyboardInterrupt:
print('收到键盘信号 Ctrl-C,Bye!')
exit(0)
if __name__ == "__main__":
main()
print('done')
在学习Python网络编程时,遇到一个问题:使用socket的accept方法监听TCP请求时,程序在阻塞模式下无法通过Ctrl-C正常退出。原因是Python 3.5及以上版本中,socket.accept在被中断时会重试系统调用,而不是抛出异常。为了解决这个问题,可以将socket放入守护线程执行,主线程捕获到信号后退出,从而实现程序的正常退出。
2468

被折叠的 条评论
为什么被折叠?



