【问题标题】:Android TCP communication with C# Server -> socket.Close与 C# 服务器的 Android TCP 通信 -> socket.Close
【发布时间】:2011-10-25 06:23:54
【问题描述】:

我有一个 Android 客户端和一个 C# 服务器。它们通过套接字进行通信,C# 服务器异步处理接收。

通信本身没有问题。我可以在服务器上验证客户端并互相发送消息。但是如果我尝试通过

关闭客户端上的套接字
socket.close();

服务器被空包“垃圾邮件”。只要 OutputStream 关​​闭,就会发生这种情况。

这是我的 Android 客户端代码:

public void run()
{ 
    try
    {                   
        InetAddress serverAddr = InetAddress.getByName(pServerIp);            
        Socket socket = new Socket(serverAddr, pServerPort);
        try 
        {
            OutputStream socketoutstr = socket.getOutputStream(); 
            OutputStreamWriter osr = new OutputStreamWriter( socketoutstr ); 
            bw = new BufferedWriter( osr ); 

            InputStream socketinstr = socket.getInputStream(); 
            InputStreamReader isr = new InputStreamReader( socketinstr ); 
            br = new BufferedReader( isr );                      

            User tmp = Login("SESAM", "PASSWORD");
            if(tmp != null)
            {
                Log.e("TCP", "Login succeeded!");
                user = tmp;
            }
            else
            {
                Log.e("TCP", "Login failed!");
                socket.close();
            }
        } 
        catch(Exception e) 
        {
            Log.e("TCP", "S: Error", e);
            socket.close();
        } 
        finally 
        {
        }
    } 
}

这是我的服务器代码中处理传入数据的部分:

private void WaitForData()
{
    try
    {
        WorkerCallback = new AsyncCallback(OnDataReceived);

        UndefinedPacket packet = new UndefinedPacket();
        socket.BeginReceive(packet.DataBuffer, 0, packet.DataBuffer.Length, SocketFlags.None, WorkerCallback, packet);
    }
    catch (SocketException se)
    {
        Console.WriteLine(se.Message);
    }
}

private void OnDataReceived(IAsyncResult asyn)
{
    UndefinedPacket socketData = (UndefinedPacket)asyn.AsyncState;
    try
    {
        int CharCount = socket.EndReceive(asyn);
        char[] chars = new char[CharCount];

        System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
        String text = System.Text.Encoding.UTF8.GetString(socketData.DataBuffer);
        int charLen = d.GetChars(socketData.DataBuffer, 0, CharCount, chars, 0);

        String data = new String(chars);
        if (data.Length > 0)
        {
            IClientPacket packet = PacketFactory.GetInstance(data);
            server.PacketManager.AddIncomingPacket(packet, this);
        }
        Console.WriteLine("Received Data!");
        WaitForData();
    }
    catch (ObjectDisposedException)
    {
        Console.WriteLine("OnDataReceived: Socket has been closed");
        server.RemoveWorkerSocket(this);
    }
    catch (SocketException se)
    {
        if (se.ErrorCode == 10054) // Connection reset by peer
        {
            string msg = "Client Disconnected";
            Console.WriteLine(msg);
            server.RemoveWorkerSocket(this);
        }
        else
        {
            Console.WriteLine(se.Message);
            server.RemoveWorkerSocket(this);
        }
    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
        server.RemoveWorkerSocket(this);
    }            
}

当我简单地关闭 Android 模拟器时,我会收到正确的服务器消息:“客户端已断开”。

但是当我关闭 Outputstream 或客户端 OnDataReceived() 上的整个套接字时,会以“0”的 data.length 非常快速地重复调用。

感谢您的帮助!

【问题讨论】:

  • 您是否可以尝试使用真实设备来从可能的原因列表中排除模拟器?
  • 在关闭套接字之前也尝试关闭输入和输出流。

标签: c# java android sockets tcp


【解决方案1】:

它不是空的“数据包”(请注意 TCP 是一个)——从 TCP 套接字读取零字节意味着另一端关闭了连接,所以你也应该关闭你的一端。

这里的“客户端断开连接”可能是模拟器出现RST 的结果,当它出现故障并切断所有连接时。

【讨论】:

  • 好的,但是如果没有数据发送,为什么会调用 'OnDataReceived'?
  • 正好告诉你必须关闭连接。
猜你喜欢
  • 1970-01-01
  • 2021-12-29
  • 2014-10-24
  • 2013-07-01
  • 2013-12-14
  • 2023-03-18
  • 1970-01-01
  • 2011-08-03
  • 1970-01-01
相关资源
最近更新 更多