Python中为什么客户端socket收不到服务器端发来的信息?
下面是代码, server 端会在 recv 上挂住 这个是为什么?
server:
# -*- coding: UTF-8 -*-
导入库
import socket, threading, os, uuid, sys
SIZE = 1024 * 1024 * 5
filename = str(uuid.uuid4()) + ‘.jpg’
检查当前目录下是否有等下要命名的图片,有的话删除之
def checkFile():
list = os.listdir(’.’)
for iterm in list:
if iterm == filename:
os.remove(iterm)
print(‘remove’)
else:
pass
接受数据线程
def tcplink(sock, addr):
def tcplink():
print('Accept new connection from %s:%s...' % addr)
# sock.send(b'Welcome from server!')
print('receiving, please wait for a second ...')
while True:
try:
data = sock.recv(SIZE)
if not data :
print('reach the end of file')
break
elif data == 'begin to send':
print('create file')
checkFile()
with open(filename, 'wb') as f:
pass
else:
with open(filename, 'ab') as f:
f.write(data)
except:
print("Unexpected error:", sys.exc_info()[0])
break
print('msg send')
sock.send(b'Welcome from server!')
sock.close()
print('receive finished')
print('Connection from %s:%s closed.' % addr)
创建一个 socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
监听端口(这里的 ip 要在不同的情况下更改)
s.bind((‘127.0.0.1’, 9999))
每次只允许一个客户端接入
s.listen(2)
print(‘Waiting for connection…’)
while True:
# 建立一个线程用来监听收到的数据
sock, addr = s.accept()
t = threading.Thread(target = tcplink, args = (sock, addr))
# 线程运行
t.start()
client:
# -*- coding: UTF-8 -*-
import socket
SIZE = 1024 * 1024 * 5
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
建立连接:
s.connect((‘127.0.0.1’, 9999))
接收欢迎消息:
with open(’./image.png’, ‘rb’) as f:
data = f.read()
s.sendall(data)
print(‘sended !’)
data = s.recv(SIZE)
print(data)
s.close()
print(‘connection closed’)
Python中为什么客户端socket收不到服务器端发来的信息?
可惜我不懂你的语言,回答不规范,我看着问题像是 while True 内部那里,没有启用单独的线程处理啊,这样的话,你服务端没法接收并发消息的
这个问题通常是因为TCP的流式传输特性。服务器发来的数据可能被缓冲,或者客户端读取方式不对。最常见的原因是recv()调用一次只读取了部分数据。
看个例子,假设服务器发送了"Hello World",客户端可能这样收不全:
# 客户端错误示例
client_socket.recv(1024) # 可能只收到"Hello"
正确的做法是循环读取,直到收到完整消息。服务器端也需要明确消息边界:
# 服务器端 - 发送带长度的消息
def send_message(sock, message):
message = message.encode('utf-8')
sock.sendall(len(message).to_bytes(4, 'big')) # 先发长度
sock.sendall(message) # 再发数据
# 客户端 - 按长度接收
def recv_message(sock):
# 先接收4字节的长度头
length_bytes = sock.recv(4)
if not length_bytes:
return None
msg_length = int.from_bytes(length_bytes, 'big')
# 按长度接收完整数据
chunks = []
bytes_received = 0
while bytes_received < msg_length:
chunk = sock.recv(min(msg_length - bytes_received, 4096))
if not chunk:
raise ConnectionError("连接中断")
chunks.append(chunk)
bytes_received += len(chunk)
return b''.join(chunks).decode('utf-8')
另外检查网络是否通畅,用netstat或telnet测试连接。还有确认端口没被防火墙挡住。
总结:用明确的消息边界协议。
不知道是不是没收到 welcome,你仔细看看 server 在 send welcome 之前就 while True 了
客户端 sendall 之后就把 socket shutdown 吧,这样服务端的 recv 才会收到 EOF 返回,不然就卡住了。或者也可以像 HTTP 一样加一个 content-length 字段
具体一下就是客户端在 sendall 之后应该 s.shutdown(socket.SHUT_WR) 关闭自己的写端
这边有几个问题:
( 1 )首先检查./image.png 文件是否存在(文件大小,是否是空文件);
( 2 )
data = sock.recv(SIZE)
if not data :
print(‘reach the end of file’)
这不是文件发送完的意思,是代表对方关闭了 socket,你不能这样写;
( 3 ) TCP 流你无法确定应用层报文是否发送完整,你需要定义一套应用层协议,比如定义头两个字节表示文件长度,服务端先读两个字节判断应用层报文大小,然后读完整个报文~~
你好 确实是 break 哪里的问题加上就好了, 能简单解释下为什么吗? 谢谢~
不 break 循环不会中断,一直卡在 receive
shutdown 之后后面的 server 要发的东西就发不出去了。
#9 TCP 是全双工的,客户端关闭写端,但是仍然可以读取服务端的响应,我这边测试是没问题的

