python - 套接字在 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
解决方案
推荐阅读
- azure - 向 100 万最终用户应用程序发送字符串的最佳 azure 服务 - 事件网格仍处于预览状态?
- arrays - LSTM Keras ValueError: setting an array element with a sequence.and Expected to see 1 array(s)
- websocket - 如何对 Spring WebSocketStompClient 进行单元测试
- javascript - 在 Javascript 端工作时的 RSA 或其他信息加密方法
- c# - Windows 窗体应用程序中基于属性的异常日志记录
- android - 菜单不显示在点击
- c# - C# WEBApi MVC 帮助页面
- javascript - 尝试将堆栈导航器注入组件并收到错误消息“您应该只渲染一个导航器”
- laravel - Laravel 在 Blade 中使用 S3/CloudFront 资源
- excel - 在 [VBA 宏] 中聚合具有两个主要 ID 的记录