Android TCP связь с сервером C # -> socket.Close - PullRequest
4 голосов
/ 11 августа 2011

У меня есть клиент 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 (*).

Спасибо за вашу помощь!

1 Ответ

5 голосов
/ 11 августа 2011

Это не пустые "пакеты" (учтите, что TCP - это поток ) - чтение нулевых байтов из сокета TCP означает, что другой конец закрыл соединение, поэтому вам также следует закрыть свой конец.

"клиент отключен" здесь, вероятно, является результатом RST из эмулятора, когда он отключается и обрывает все соединения.

...