You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin客户端与Linux Python3 Socket服务器图片收发问题解决

图片Socket收发问题解决

现有代码的核心问题

  • Kotlin客户端直接发送图片字节数组,但未告知服务器数据总长度,服务器仅固定接收1024字节,无法获取完整图片数据
  • Python服务器仅单次调用recv,无法接收超过1024字节的图片数据
  • Python代码缺少numpy导入,且未处理图片接收后的验证与保存逻辑

修正后的Kotlin客户端代码

确保先发送图片字节数组的长度,再发送图片数据(示例中直接从资源读取Bitmap转换为字节流):

class MainActivity : AppCompatActivity() {
    lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        Client().start()
    }

    class Client : Thread() {
        override fun run() {
            try {
                val socket = Socket("35.216.104.58", 3000)
                val dos = DataOutputStream(socket.getOutputStream())

                // 从资源读取图片并转换为字节数组
                val bitmap = BitmapFactory.decodeResource(applicationContext.resources, R.drawable.your_image)
                val byteArrayOutputStream = ByteArrayOutputStream()
                bitmap.compress(Bitmap.CompressFormat.JPEG, 80, byteArrayOutputStream)
                val imageBytes = byteArrayOutputStream.toByteArray()

                // 先发送图片字节数组的长度(4字节整数)
                dos.writeInt(imageBytes.size)
                // 再发送完整的图片数据
                dos.write(imageBytes)

                dos.flush()
                dos.close()
                socket.close()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }
}

修正后的Python服务器代码

先接收数据长度,再循环接收所有图片字节,最后解码保存:

import socket
import cv2
import numpy as np

ip = ''
port = 3000

server_socket = socket.socket(socket.AF_INET)
server_socket.bind((ip, port))
server_socket.listen(1)

print('Waiting Client...')
client_socket, addr = server_socket.accept()
print('Connect Client!!')

# 先接收4字节的长度数据(对应Kotlin的writeInt)
length_data = client_socket.recv(4)
if not length_data:
    print("未收到数据长度")
    client_socket.close()
    server_socket.close()
    exit()

image_length = int.from_bytes(length_data, byteorder='big')
print(f"图片数据长度: {image_length}")

# 循环接收所有图片数据,每次最多收4096字节
received_data = b''
while len(received_data) < image_length:
    chunk = client_socket.recv(min(image_length - len(received_data), 4096))
    if not chunk:
        break
    received_data += chunk

# 验证并处理图片
if len(received_data) == image_length:
    encoded_img = np.frombuffer(received_data, dtype=np.uint8)
    image = cv2.imdecode(encoded_img, cv2.IMREAD_COLOR)
    if image is not None:
        cv2.imwrite("received_image.jpg", image)
        print("图片接收并保存成功")
        cv2.imshow("Received Image", image)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    else:
        print("图片解码失败")
else:
    print("图片数据接收不完整")

client_socket.close()
server_socket.close()

关键注意事项

  • 必须先发送数据长度,让服务器明确需要接收的总字节数,避免数据截断
  • 服务器需循环接收数据,直到获取到所有长度的字节,不能单次固定接收小容量数据
  • 客户端与服务器的图片压缩格式要统一(示例用JPEG)
  • 增加异常处理,覆盖连接中断、数据接收不全、解码失败等场景

内容的提问来源于stack exchange,提问作者김현종

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 21:31:09