首页 > 解决方案 > 套接字在 VSCode 中按预期运行,但在终端发送后关闭

问题描述

我正在开发一个命令行聊天程序,我遇到了一个奇怪的问题,在 VSCode 调试器中运行客户端软件时,一切都按预期工作,但是当我在终端中运行代码时,套接字在单次后关闭信息。服务器代码工作正常,问题似乎只发生在客户端。终端是我的常规 PopOS Gnome 终端,没有什么花哨的,没有自定义。Python 版本 3.8.6,PopOS 20.10,内核是 Linux 5.11.0-7612-generic,VSCode 1.56.1。VSCode 将 /usr/bin/python3 作为默认解释器,这是在 VMWare Workstation 16 下的 VM 中全新安装的 PopOS。

在终端中运行服务器,它正在愉快地收听:

tcp        0      0 127.0.0.1:33333         0.0.0.0:*               LISTEN      3360/python3   

我运行客户端,服务器注册它。Socket 舒服地建立起来了,等我给它发个用户名:

服务器文本:

[WAITING FOR USERNAME] Awaiting username from ('127.0.0.1', 48280) 

网络统计:

tcp        0      0 127.0.0.1:33333         0.0.0.0:*               LISTEN      3360/python3
tcp        0      0 127.0.0.1:33333         127.0.0.1:48280         ESTABLISHED 3360/python3        
tcp        0      0 127.0.0.1:48280         127.0.0.1:33333         ESTABLISHED 4596/python3        

我将我的用户名提交给服务器,它会记录下来:

[NEW USERNAME] Username 'Jim' belongs to ('127.0.0.1', 48280) 

但是这是什么?!?Netstat 马上给我带来了一些坏消息:

tcp        0      0 127.0.0.1:33333         127.0.0.1:48280         CLOSE_WAIT  3360/python3  
tcp        0      0 127.0.0.1:48280         127.0.0.1:33333         FIN_WAIT2   -      

 

这仅发生在客户端,并且仅在终端中运行时发生。如果我在 VSCode 调试器中运行客户端,它会很乐意整天发送文本。服务器文本:

[WAITING FOR USERNAME] Awaiting username from ('127.0.0.1', 48328)
[NEW USERNAME] Username 'Jenny' belongs to ('127.0.0.1', 48328)
[NEW MESSAGE] Jenny: Heya
[NEW MESSAGE] Jenny: Hi there
[NEW MESSAGE] Jenny: How's it going
[NEW MESSAGE] Jenny: hey   

Netstat 也在报告所有的事情:

tcp        0      0 127.0.0.1:33333         127.0.0.1:48328         ESTABLISHED 3360/python3 
tcp        0      0 127.0.0.1:48328         127.0.0.1:33333         ESTABLISHED 4780/python3

我不知道为什么会这样。无论哪种方式,VSCode 或终端,它都是系统的 Python 解释器运行代码,所以它的行为应该相同,对吧?但事实并非如此。任何帮助表示赞赏!

这是客户端代码:

import socket
import threading
import sys

HEADER = 64
PORT = 33333
SERVER = '127.0.0.1'
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "#!@!DISCONNECT!@!#"

def send_msg(msg):
    message = msg.encode(FORMAT)
    msg_length = len(message)
    send_length = str(msg_length).encode(FORMAT)
    send_length += b' ' * (HEADER - len(send_length))
    client.sendall(send_length)
    client.sendall(message)
    return True

def receive_messages(conn):
    while True:
        msg_length = conn.recv(HEADER).decode(FORMAT)
        if msg_length == '':
            continue
        msg_length = int(msg_length)
        msg = conn.recv(msg_length).decode(FORMAT)
        print(msg)
        if msg[1:15] == "[DISCONNECTED]":
            return False
        if conn.fileno() <4:
            disconnected.set()
            return False

disconnected = threading.Event()

def got_disco():
    while True:
        if disconnected.is_set():
            client.shutdown(2) # Removes the socket's read/write ability
            client.close() # Closes the socket
            sys.exit()
        else:
            continue

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(ADDR)

# Receive login prompt
msg_length = client.recv(HEADER).decode(FORMAT)
if msg_length == '':
    msg_length = 0
msg_length = int(msg_length)
msg = client.recv(msg_length).decode(FORMAT)
print(msg)

# Input username and send it to server
client.sendall(input().encode(FORMAT))


#<<<>>>--> This is where the socket closes, right after the client.sendall() <--<<<>>>


# Creates a thread to listen for and print messages from the server
server_listen = threading.Thread(name="listen",target=receive_messages, args=(client,))
server_listen.start()

am_I_disco = threading.Thread(name='disco', target=got_disco)
am_I_disco.start()

while True:
    speak = input("\nSpeak: ")
    if speak == "q":
        send_msg(DISCONNECT_MESSAGE)
        print("\nDisconnecting. Goodbye!")
        disconnected.set()
    else:
        send_msg(speak)
        continue

标签: pythonlinuxsocketsvisual-studio-codeterminal

解决方案


推荐阅读