TcpClient已连接但服务器未收到消息

时间:2019-05-14 06:44:39

标签: c# .net sockets asynchronous

服务器:

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 个答案:

答案 0 :(得分:2)

ReadCallback中,您不会开始 next 的读取-是的,您的代码只能读取一次。

添加

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

应位于ReadCallback的底部(当bytesRead > 0时)。然而!您没有实现适当的框架,因此您应该非常谨慎。对于基于文本的协议(像这样),一个基本的框架实现是使用某种行尾标记,并缓冲数据,直到看到行尾,然后然后处理该行。 / p>

在TCP上,只能保证以正确的顺序获得正确的字节(或最终导致失败的套接字)-不能保证 在调用它们方面具有相同的组成根据每个字节中的字节数,Send与对Receive的调用完全匹配。