简体   繁体   English

Python Tcp 断开检测

[英]Python Tcp disconnect detection

I have a simpletcp example:我有一个简单的例子:

import socket
import time


TCP_IP = '127.0.0.1'
TCP_PORT = 81
BUFFER_SIZE = 1024

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))

while True:
    s.send(bytes('hello', 'UTF-8'))
    time.sleep(1)

s.close()

How can I detect, if I lost the connection to the server, and how can I safely reconnect then?如果我失去了与服务器的连接,我该如何检测,然后如何安全地重新连接?

Is it necessary to wait for answer to the server?是否需要等待服务器的响应?

UPDATE:更新:

import socket
import time

TCP_IP = '127.0.0.1'
TCP_PORT = 81
BUFFER_SIZE = 1024

def reconnect():
    toBreak = False
    while True:
        s.close()
        try:
            s.connect((TCP_IP, TCP_PORT))
            toBreak = True
        except:
            print ("except")        
        if toBreak:
            break
        time.sleep(1)


s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))

while True:
    try:    
        s.send(bytes('hello', 'UTF-8'))
        print ("sent hello")
    except socket.error as e:
        reconnect()

    time.sleep(1)

s.close()

If I break the connection, it raises an error (does not really matter what), and goes to the reconnect loop.如果我断开连接,它会引发错误(无关紧要),然后进入重新连接循环。 But after I restore the connection, the connect gives back this error:但是在我恢复连接后,连接返回此错误:

OSError: [WinError 10038] An operation was attempted on something that is not a socket OSError: [WinError 10038] 尝试对非套接字的对象进行操作

If I restart the script, which calls the same s.connect((TCP_IP, TCP_PORT)), it works fine.如果我重新启动调用相同 s.connect((TCP_IP, TCP_PORT)) 的脚本,它工作正常。

You'll get a socket.error : [Errno 104] Connection reset by peer exception (aka ECONNRESET ) on any call to send() or recv() if the connection has been lost or disconnected. 你会得到一个socket.error[Errno 104] Connection reset by peer如果连接丢失或断开,任何对send()recv()调用ECONNRESET [Errno 104] Connection reset by peer异常(也就是ECONNRESET[Errno 104] Connection reset by peer连接。 So to detect that, just catch that exception: 所以为了检测它,只需捕获该异常:

while True:
    try:
        s.send(bytes('hello', 'UTF-8'))
    except socket.error, e:
        if e.errno == errno.ECONNRESET:
            # Handle disconnection -- close & reopen socket etc.
        else:
            # Other error, re-raise
            raise
    time.sleep(1)

Use a new socket when you attempt to reconnect. 尝试重新连接时使用新的套接字。

def connect():
    while True:
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect((host, port))
            return s.makefile('w')
        except socket.error as e:
            log("socket error {} reconnecting".format(e))
            time.sleep(5)

dest = connect()
while True:
    line = p.stdout.readline()
    try:
        dest.write(line)
        dest.flush()
    except socket.error as e:
        log("socket error {} reconnecting".format(e))
        dest = connect()

Can you try that (I think that you does'not try socket.SO_REUSEADDR): 你能试试吗(我认为你不会尝试socket.SO_REUSEADDR):

def open_connection():
    data0=''

    try:
        # Create a TCP/IP socket
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        # Connect the socket to the port where the server is listening
        server_address = ('192.168.0.100', 8000)
        sock.settimeout(10)     # TimeOut 5 secunde

        while True:

            try:
                sock.connect(server_address)
                message = 'new connection'
                sock.sendall(message)

                # Look for the response
                amount_received = 0
                data0=sock.recv(1024)
                amount_received = len(data0)
                return

            finally:
                wNET = 0
                pass

    except:
        sock.close()
        time.sleep(60)
        del data0

This is the code based on thread.这是基于线程的代码。 The main tip is that the received buffer cannot be none, if the socket is connected.主要提示是,如果套接字已连接,则接收缓冲区不能为无。

import time
import socket
import threading

def connect():
    while True:
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect((host, port))
            s.settimeout(60)
            return s
        except socket.error as e:
            print("socket error {} reconnecting".format(e))
            time.sleep(5)

soc = connect()

def runSocket():
    global soc
    while True:
        try:
            recBuf = soc.recv(64)
            if recBuf == b'':    #remote server disconnect
                soc = connect()
            else:
                print(recBuf)
        except socket.timeout:
            print("Timeout")
        except Exception as e:
            print("other socket error {}".format(e))
            soc = connect()

socketThread = threading.Thread(target=runSocket)
socketThread.start()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM