之前《网络编程-TCP or TLS连接断开检测》文章用 C 语言实现判断网络是否断开。
先简单说下什么情况下要做这种断网检测,比如设备端与服务器建立 TCP 长连接后,只存在单向往对端发送数据的情况,并不会判断对方是否真的接收到了。
而如果中间服务器把连接断开了,设备端不知道的情况下继续往对端发送数据,则第一次调用 send 发送接口是会正常返回的,并不会报错,只有下次还继续发送数据才会报错(前一次 send 后会收到对端的 RST 报文),这样就导致前面发送的数据丢失了。
以下通过 python 来判断客户端连接服务器后,不执行任何操作,一段时间后,服务器是否会主动断开客户端连接。具体代码如下:
server.py
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import socket
import sys
import time
def server_accept(serverip, port):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((serverip, int(port)))
s.listen(1)
conn, addr = s.accept()
with conn:
print('Connected by', addr)
time.sleep(10)
conn.close()
while True:
pass
if __name__ == "__main__":
server_accept(sys.argv[1], sys.argv[2])
client.py
#!/usr/bin/python
import socket
import sys
def client_connect(serverip, port):
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
try:
client.connect((serverip, int(port)))
except socket.error as msg:
print(msg)
#socket.close(client.fileno())
client.close()
return -1
print("connect success")
client.settimeout(12)
try:
data = client.recv(1024)
except socket.timeout:
print("time out, the server not close this connect.")
client.close()
return -2
print("the server close this connect.")
return 0
if __name__ == "__main__":
ret = client_connect(sys.argv[1], sys.argv[2])
print(ret)
1、
如果 python 代码中存在中文字符,需要在文件头增加:# -*- coding: UTF-8 -*-
,否则会出现如下报错
SyntaxError: Non-ASCII character ‘\xe7’ in file server.py on line 7, but no encoding declared
2、
with的作用就是异常情况下都会自动做资源清理,为此会检查对象是否有 __exit__
方法,如果用 python2 来执行上面代码,会出现如下报错:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: AttributeError: exit
使用 python3 执行则没有问题。