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收不到服务器端发来的信息?

10 回复

可惜我不懂你的语言,回答不规范,我看着问题像是 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')

另外检查网络是否通畅,用netstattelnet测试连接。还有确认端口没被防火墙挡住。

总结:用明确的消息边界协议。

不知道是不是没收到 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 是全双工的,客户端关闭写端,但是仍然可以读取服务端的响应,我这边测试是没问题的

回到顶部