TcpClient подключен, но сервер не получает сообщение - PullRequest
1 голос
/ 14 мая 2019

Сервер:

public class TcpServer
{
    private TcpListener tcpListener;
    private static ManualResetEvent allDone = new ManualResetEvent(false);

    public TcpServer(string url, int port)
    {
        tcpListener = new TcpListener(IPAddress.Parse(url), port);
        pingMapper = new LightPingMapper();
    }


    public void Run()
    {
        tcpListener.Start();

        Console.WriteLine("Server running");
        while (true)
        {
            allDone.Reset();
            tcpListener.BeginAcceptSocket(AcceptCallback, tcpListener);
            Console.WriteLine("Accepting socket");
            allDone.WaitOne();
        }

        Console.ReadLine();
    }

    private void AcceptCallback(IAsyncResult result)
    {
        try
        {
            allDone.Set();

            var listener = (TcpListener) result.AsyncState;
            var handler = listener.EndAcceptSocket(result);

            StateObject state = new StateObject();
            state.workSocket = handler;
            handler.BeginReceive(state.buffer, 0, state.buffer.Length, 0, ReadCallback, state);
        }
        catch (Exception e)
        {
            Console.WriteLine($"Error accepting callback. {e.Message}");
        }
    }

    private void ReadCallback(IAsyncResult asyncResult)
    {
        try
        {
            string content = string.Empty;
            Console.WriteLine("Read data from socket");

            StateObject state = (StateObject) asyncResult.AsyncState;
            Socket handler = state.workSocket;

            int bytesRead = handler.EndReceive(asyncResult);
            if (bytesRead > 0)
            {
                state.sb.Append(Encoding.UTF8.GetString(state.buffer));
                content = state.sb.ToString();
                Console.WriteLine(content + " "  + DateTime.Now);                    
            }
        }
        catch (Exception e)
        {
            Console.WriteLine($"Error reading socket. {e.Message}");
        }
    }
}

class StateObject
{
    // Client  socket.  
    public Socket workSocket = null;
    // Size of receive buffer.  
    public const int BufferSize = 256;
    // Receive buffer.  
    public byte[] buffer = new byte[BufferSize];
    // Received data string.  
    public StringBuilder sb = new StringBuilder();
}

Клиент:

public class TCPClientWrapper
{
    private TcpClient tcpClient;
    private readonly string address;
    private readonly int port;

    public TCPClientWrapper(string address, int port)
    {
        InitTcpClient();
        this.address = address;
        this.port = port;
    }

    public void SendMessage()
    {
        for(int i=0; i < 10; i++)
        {
            if (!SocketConnected())
            {
                TryConnect();
            }               

            byte[] buffer = Encoding.UTF8.GetBytes("Hello");
            tcpClient.Client.Send(buffer);
            Thread.Sleep(60000);
        }
    }

    private void TryConnect()
    {
        bool isConnected = false;
        while (true)
        {
            try
            {
                InitTcpClient();

                tcpClient.Connect(IPAddress.Parse(address), port);
                if (SocketConnected())
                {
                    Console.WriteLine("TcpClient, Connected");
                    isConnected = true;
                    break;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("TcpClient, connection failed. Try to reconnect after 30 seconds, {0}", e.Message);
            }
            finally
            {
                if (!isConnected)
                {
                    tcpClient.Close();
                    Thread.Sleep(30000);
                }
            }
        }
    }

    private void InitTcpClient()
    {            
        tcpClient = new TcpClient();
        tcpClient.SendTimeout = 15;
    }

    private bool SocketConnected()
    {
        var s = tcpClient.Client;

        if (!s.Connected)
            return false;

        bool part1 = s.Poll(1000, SelectMode.SelectRead);
        bool part2 = s.Available == 0;
        return !(part1 && part2);
    }

}

Проблема в том, что сервер читает только первое сообщение, каждое следующее сообщение не получено сервером.TcpClient подключен, но сервер не получает никаких сообщений.Кто-нибудь может подсказать, что не так с моим кодом?

1 Ответ

2 голосов
/ 14 мая 2019

В ReadCallback вы не начинаете чтение next - так что да, ваш код читает только один раз.

Добавление

handler.BeginReceive(state.buffer, 0, state.buffer.Length, 0, ReadCallback, state);

книжняя часть ReadCallback (когда bytesRead > 0) должна работать.Тем не мение!Вы не осуществляете правильное кадрирование, поэтому вы должны быть очень осторожны с этим.Базовая реализация кадрирования для текстового протокола (подобного этому) будет заключаться в использовании какого-либо сторожевого устройства конца строки и буферизации данных до тех пор, пока вы не увидите конец строки, затем обрабатывают строку.

В TCP вы гарантированно получите правильные байты только в правильном порядке (или, в конце концов, в случае неудачного сокета) - вы не гарантированно получите их в той же композиции с точки зрения обращений кSend точно соответствует вызовам Receive с точки зрения количества байтов в каждом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...