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

Xamarin Android TCP客户端无法接收C# WinForm TCP服务器消息

问题分析与修复方案

你的Xamarin Android TCP客户端能连接服务器并发送消息,但无法接收服务器返回内容,核心问题出在clientReceive方法的实现逻辑上,以下是具体问题和修复步骤:

存在的问题

  1. 未初始化datalength变量:代码直接调用BitConverter.ToInt32(datalength, 0),但datalength从未赋值或初始化,会导致获取错误的数据长度,甚至抛出异常。
  2. 错误的循环判断条件:while(client.Connected)不可靠,TcpClient.Connected仅反映上一次操作的连接状态,即使服务器已断开,该属性可能仍返回true,导致循环无法正确终止或读取失败。
  3. 缺失消息长度读取逻辑:从注释的代码能看出,服务器应该是先发送4字节的消息长度,再发送内容(WinForm客户端正常通信也验证了这一点),但当前代码跳过了读取长度的步骤,无法正确解析服务器消息。
  4. 子线程UI操作不规范:子线程中直接调用Toast.MakeText会触发跨线程UI操作异常,必须切换到主线程执行。

修复后的代码

修正clientReceive方法

private void clientReceive()
{
    try
    {
        var stream = client.GetStream();
        new Thread(() =>
        {
            byte[] datalength = new byte[4];
            int bytesRead;
            // 以流读取结果作为循环终止条件,返回0表示连接关闭
            while ((bytesRead = stream.Read(datalength, 0, 4)) > 0)
            {
                if (bytesRead != 4)
                {
                    // 未完整读取长度,连接异常,退出循环
                    break;
                }
                int dataLength = BitConverter.ToInt32(datalength, 0);
                byte[] data = new byte[dataLength];
                int totalBytesReceived = 0;
                // 循环读取,确保获取完整的消息内容
                while (totalBytesReceived < dataLength)
                {
                    int received = stream.Read(data, totalBytesReceived, dataLength - totalBytesReceived);
                    if (received == 0)
                    {
                        // 连接中断,退出循环
                        break;
                    }
                    totalBytesReceived += received;
                }
                if (totalBytesReceived == dataLength)
                {
                    string receivedText = Encoding.ASCII.GetString(data);
                    this.RunOnUiThread(() =>
                    {
                        textReceive.Text = textReceive.Text + receivedText + System.Environment.NewLine;
                    });
                }
            }
            // 连接关闭后,主线程更新UI状态
            this.RunOnUiThread(() =>
            {
                buttonConnect.Text = "Connect";
                buttonSend.Enabled = false;
                Toast.MakeText(this, "Connection closed", ToastLength.Short).Show();
            });
        }).Start();
    }
    catch (Exception ex)
    {
        this.RunOnUiThread(() =>
        {
            Toast.MakeText(this, ex.Message, ToastLength.Short).Show();
        });
    }
}

断开连接逻辑优化

else
{
    buttonConnect.Text = "Connect";
    buttonSend.Enabled = false;
    try
    {
        stream?.Close();
        client?.Close();
    }
    catch { }
    Toast.MakeText(this, "Dis-Connected", ToastLength.Short).Show();
}

关键修复点说明

  • 匹配服务器通信协议:先读取4字节的消息长度,再根据长度读取对应内容,和WinForm客户端的逻辑保持一致。
  • 可靠的循环终止:用stream.Read的返回值判断连接状态,返回0时直接终止循环,避免无效等待。
  • 完整读取消息:通过循环读取确保获取全部消息内容,避免因单次读取不完整导致的内容丢失。
  • 规范UI操作:所有更新UI的操作都通过RunOnUiThread切换到主线程,避免跨线程异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 05:12:22