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

Android Socket客户端无法完整读取字节数组,接收图片异常

解决Android Socket接收C#服务器图片仅显示顶部白线的问题

我帮你排查下这个问题——你遇到的情况很典型,核心原因是C#和Java默认的字节序不匹配,再加上长度读取环节的小疏漏,导致接收的图片数据不完整,最终解码后只显示顶部白线。下面一步步拆解问题和给出修复方案:

问题根源

C#的BinaryWriter默认用**小端字节序(Little-Endian)写入int类型数据(也就是低位字节排在前面),但你Android代码里解析图片长度时,用的是大端字节序(Big-Endian)**的逻辑(readMsgLen[0]<<24 | ...),这会让解析出来的长度完全错误。比如实际图片长度是1024,解析后可能变成一个超大或超小的数,导致readFully读取的字节数不对,图片数据残缺,解码后自然只显示顶部一小条白线。

另外,你用dis.read(readMsgLen,0,4)读取长度时,这个方法不一定能一次性读满4个字节,也可能导致长度解析出错。

修复步骤

1. 修正长度解析的字节序(关键!)

把解析长度的逻辑改成小端字节序,匹配C#的默认行为:

// 先确保完整读取4个字节的长度数据,用readFully代替read
dis.readFully(readMsgLen, 0, 4);
// 小端解析:低位字节在前,所以从readMsgLen[0]开始对应int的低位
final int length = (readMsgLen[3] & 0xFF) << 24 | 
                   (readMsgLen[2] & 0xFF) << 16 | 
                   (readMsgLen[1] & 0xFF) << 8 | 
                   (readMsgLen[0] & 0xFF);

2. 简化Bitmap加载流程(可选但推荐)

你现在把Bitmap转成Uri再用Picasso加载的流程有点绕,直接把解码后的Bitmap设置到ImageView就行,减少中间环节的潜在问题:

mn.iv.setImageBitmap(bitmap);

3. 完善异常提示

在catch块里加上UI线程的错误提示,方便你排查问题:

mn.runOnUiThread(() -> Toast.makeText(mn.getApplicationContext(), "接收图片出错:" + e.getMessage(), Toast.LENGTH_SHORT).show());

完整修正后的代码

class imageReceiver implements Runnable {
    Bitmap bitmap;
    MainActivity mn;
    DataInputStream dis;
    byte[] data;

    public imageReceiver(MainActivity mn) {
        this.mn = mn;
    }

    @Override
    public void run() {
        if (s.isConnected()) {
            try {
                final InputStream in = s.getInputStream();
                dis = new DataInputStream(in);
                byte[] readMsgLen = new byte[4];
                
                // 确保完整读取4个字节的长度数据
                dis.readFully(readMsgLen, 0, 4);
                
                // 小端字节序解析长度,匹配C# BinaryWriter的默认输出
                final int length = (readMsgLen[3] & 0xFF) << 24 |
                        (readMsgLen[2] & 0xFF) << 16 |
                        (readMsgLen[1] & 0xFF) << 8 |
                        (readMsgLen[0] & 0xFF);

                data = new byte[length];
                dis.readFully(data, 0, data.length);
                bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);

                mn.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(mn.getApplicationContext(), "图片长度:" + length, Toast.LENGTH_SHORT).show();
                        if (bitmap == null) {
                            Toast.makeText(mn.getApplicationContext(), "图片解码失败", Toast.LENGTH_SHORT).show();
                        } else {
                            Toast.makeText(mn.getApplicationContext(), "图片接收成功", Toast.LENGTH_SHORT).show();
                            // 直接设置Bitmap到ImageView
                            mn.iv.setImageBitmap(bitmap);
                        }
                    }
                });
            } catch (IOException e) {
                e.printStackTrace();
                mn.runOnUiThread(() -> Toast.makeText(mn.getApplicationContext(), "接收出错:" + e.getMessage(), Toast.LENGTH_SHORT).show());
            }
        }
    }
}

额外验证建议

  • 打印Android端解析后的length值,和C#服务器发送的实际图片字节长度对比,如果一致,说明长度解析没问题;如果不一致,那就是字节序的问题还没解决。
  • 确认C#服务器是用BinaryWriter.Write(int)发送长度的,没有手动修改字节序——如果服务器是手动构造字节数组发送长度,那需要两边的字节序逻辑完全一致。

内容的提问来源于stack exchange,提问作者Bilal Hassan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:42:18