【问题标题】:TcpClient connected but server not receiving messageTcpClient 已连接但服务器未收到消息
【发布时间】:2019-05-14 06:44:39
【问题描述】:

服务器:

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 已连接,但服务器未收到任何消息。谁能建议我的代码有什么问题?

【问题讨论】:

  • 服务器在if (bytesRead &gt; 0)块中收到消息后你没有调用handler.BeginReceive,所以服务器在第一条消息之后停止等待下一条消息。

标签: c# .net sockets asynchronous


【解决方案1】:

ReadCallback 中,您不会开始下一个 读取 - 所以是的,您的代码只读取一次。

添加

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

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

在 TCP 上,您只能保证以正确的顺序获得正确的字节(或最终失败的套接字) - 您保证在调用Send 在每个字节数方面与对 Receive 的调用完全匹配。

【讨论】:

    猜你喜欢
    • 2012-10-11
    • 2014-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-13
    • 1970-01-01
    • 2019-09-22
    相关资源
    最近更新 更多