相关文章推荐
没读研的消炎药  ·  module ...·  1 年前    · 
直爽的跑步机  ·  embedded - How do I ...·  2 年前    · 

如何检测UDP套接字的关闭客户端?

3 人关注

我正在通过以太网将摄像机的一些实时数据传输到客户端,我使用python socket和opencv来传输图像。它运行良好,我可以在客户端读取视频。

问题是,当我启动监听用户的服务器并启动一个套接字流时,在我关闭客户端的连接后,服务器端继续传输数据。此外,在关闭客户端的连接后,我只能通过重新启动服务器来重新连接。

我曾考虑过实现一种心跳协议,每收到100张图片就从客户端向服务器发送一条消息,告诉我还在听,如果没有收到,就回到循环中去听新的连接。唯一的问题是,recvfrom是非阻塞的,所以直接在while循环中实现可能是不行的。

我怎样才能检测到客户端不再读取数据了?

Here is my server side:

import cv2, imutils, socket 
import numpy as np
import time 
import base64 
BUFF_SIZE = 65536
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, BUFF_SIZE)
host_name = socket.gethostname()
host_ip = 'xxx.xxx.xxx.xxx'
port = 4001
socket_address = (host_ip, port)
server_socket.bind(socket_address)
print("listening at", socket_address)
vid = cv2.VideoCapture(0)    
WIDTH=480
while True:
    msg,client_addr = server_socket.recvfrom(BUFF_SIZE)
    print(client_addr)
    while (vid.isOpened()):
        print("sending img")
        _,frame = vid.read()
        frame = imutils.resize(frame,width=WIDTH)
        encoded,buffer = cv2.imencode(".jpg",frame,[cv2.IMWRITE_JPEG_QUALITY,80])
        message = base64.b64encode(buffer)
        print(len(message))
        server_socket.sendto(message,client_addr)
        key = cv2.waitKey(1) & 0xFF
        if key == ord('q'):
                server_socket.close()

Here is my client side:

def video_socket_stream_client():
    BUFF_SIZE = 65536
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    client_socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, BUFF_SIZE)
    host_name = socket.gethostname()
    host_ip = 'xxx.xxx.xxx.xxx'
    port = 4001
    client_socket.sendto("connect".encode(),(host_ip, port)) # send signal
    while True:
        packet,_ = client_socket.recvfrom(BUFF_SIZE)
        data = base64.b64decode(packet,' /')
        npdata = np.frombuffer(data,dtype=np.uint8)
        frame = cv2.imdecode(npdata,1)
        time.sleep(0.016)
        yield(b'--frame\r\n'b'Content-Type: image/jpeg\r\n\r\n' + data + b'\r\n')
    
python
sockets
wsb memes
wsb memes
发布于 2021-12-27
3 个回答
Tim Roberts
Tim Roberts
发布于 2021-12-27
已采纳
0 人赞同

这是UDP与TCP的权衡之一。 在UDP中,没有长期连接。 发送者只需发送数据,并希望有人在听。 听者只是拿起电话,希望有人在说话。 没有持久的状态。 如果发送方停止发送,监听方也不会听到任何声音。 如果你需要维持一个连接,那么你就需要使用TCP。

你不应该再去重启服务器了。 双方都不知道对方在做什么。 我想知道你是不是因为没有使用SO_REUSEADDR而被咬了。

是的。明天将尝试设置SO_REUSEADDR选项--并希望标记为答案:)
只是在这里使用TCP而不是UDP似乎是在浪费带宽。
这就是权衡的结果。 如果你想进行广播,你要么匿名工作(用UDP),要么可靠地复制输出(用TCP)。
Conjure.Li
Conjure.Li
发布于 2021-12-27
0 人赞同

服务器的运行状态可以通过下面的返回值来判断 getattr(socket,'_closed') .True是关闭状态,False是运行状态。

import socket
ip = 'localhost'
port = 5003
ws = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ws.bind((ip, port))
ws.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
ws.listen()
# 关闭服务
# ws.close()
print("The status is as follows:")
if(getattr(ws, '_closed') == False):
    print("Running")
elif(getattr(ws, '_closed') == True):
    print("closed")