python学习-网络连接断开判断

Posted by 周思进 on January 24, 2021

之前《网络编程-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 执行则没有问题。