【问题标题】:Receiving and sending, a TcpListener story接收和发送,一个 TcpListener 的故事
【发布时间】:2015-01-29 15:54:49
【问题描述】:

我正在尝试建立一个 tcp 连接,它将从外部用户接收一些 xml 格式的数据,将其解析为数据表,对数据表进行一些繁重的操作,然后转身发送一个 xml根据修改回复。

从外观上看,它似乎工作得很好,但随后进行了测试,发现了一些主要问题。如果多个项目同时进入,有时会返回错误的数据(如第三个 in 发送第四个 ins 数据回复),并且有可能在极长的 xml 输入上无法正确接收所有数据。

接收端

此代码用于接收传入的传输,将它们解析为 xml 文档,然后将它们发送到相应的部分进行处理。有一些全局声明(如_TcpClient我没有显示初始化,因为我认为它们的数据类型等可能很明显。

private void ReceivePortMessages()
{
    int requestCount = 0;
    _TcpListener.Start();
    Debug.Print(" >> Server Started");
    _TcpClient = _TcpListener.AcceptTcpClient();
    Debug.Print(" >> Accept connection from client");

    while (true)
    {
        try
        {
            requestCount = requestCount++;
            NetworkStream networkStream = _TcpClient.GetStream();
            byte[] bytesFrom = new byte[10025];
            networkStream.Read(bytesFrom, 0, (int)_TcpClient.ReceiveBufferSize);
            string dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
            dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("\0"));

            XmlDocument xm = new XmlDocument();
            xm.LoadXml(string.Format("<root>{0}</root>", dataFromClient));
            XmlElement root = xm.DocumentElement;
            string rootName = root.FirstChild.Name;

            // Sends the data to an appropriate parser operation.
            RouteInboundXML(rootName, dataFromClient);
        }
        catch (ArgumentOutOfRangeException ex)
        {
            Debug.Print("ReceivePortMessages: Remote client disconnected. " + ex.ToString());
            _TcpClient.Close();
            _TcpListener.Stop();
            ReceivePortMessages();
            return;
        }
        catch (Exception ex)
        {
            Debug.Print("ReceivePortMessages: " + ex.ToString());
            _TcpClient.Close();
            _TcpListener.Stop();
            ReceivePortMessages();
            return;
        }
    }
}

正在发送的传输

收到此数据后,通过一系列操作路由 xml 文档,包括插入数据库,处理插入数据库的数据,然后通过 SQL 服务代理依赖项,选择备份数据并将其转换为 xml回复文件。服务代理的依赖然后调用SendReply 方法向我们的用户返回回复。该代码可以在下面找到:

private void SendReply(string reply)
{
    try
    {
        NetworkStream networkStream = _TcpClient.GetStream();
        string serverResponse = reply;
        Byte[] sendBytes = Encoding.ASCII.GetBytes(serverResponse);
        networkStream.Write(sendBytes, 0, sendBytes.Length);
        networkStream.Flush();
        Debug.Print(" >> " + serverResponse);
    }
    catch (ArgumentOutOfRangeException ex)
    {
        Debug.Print("SendReply: Remote client disconnected. " + ex.ToString());
        _TcpClient.Close();
        _TcpListener.Stop();
        ReceivePortMessages();
        return;
    }
}

弄清楚这一点对我来说将是一个巨大的胜利,因为我在网络编程领域相当缺乏(你可能会说)。我已经在这个程序上工作了将近 5 个月,并且真的只剩下这一部分有待解开。任何能帮助我解决这个问题的编码建议、阅读材料等都将不胜感激。提前致谢。

【问题讨论】:

  • 您是否尝试过在 Debug/Console 中单独查看输入流,或者使用断点来跟踪您的代码?你在使用任务和 BackgroundWorkers 吗?
  • 我已经完成了一切,当我走那条路时,一切总是正确的。它似乎在 90% 的时间里都走在正确的道路上,而当它不是时,我永远无法抓住它。我没有使用后台工作人员,如果有帮助,我可以实施它们。老实说,我只是希望我在网络代码部分的某个地方搞砸了,考虑到这些都是通过各种模棱两可的谷歌代码 sn-ps 拼凑而成的。
  • 我会坚持你当前的构建,暂时不使用后台工作人员,这只是乱序执行的一种方式。我试着想一个可能的原因。我认为,这只是一个想法,问题在于您如何阅读网络流。它可能不会引发异常,但我认为您的代码不会在执行之前等待接收所有数据。我的猜测是,这对于小数据来说不是问题,因为您在 LAN 上并且网络连接是高速/几乎即时的。我认为您需要“收到的所有数据”?检查点。
  • @RagingCain 好的,你有没有机会举例说明我是如何做到这一点的?链接,代码等?我还没有完全了解网络代码。从来都不是我的强项。
  • 当然,我会尝试在下面的答案中处理您的代码,请稍等。

标签: c# sockets network-programming tcpclient tcplistener


【解决方案1】:

您的字节缓冲区是静态的,我会从以下位置切换它:

byte[] bytesFrom = new byte[10025];

到:

byte[] bytesFrom = new byte[tcpClient.ReceiveBufferSize];

另外,我会从以下位置切换到 Unicode 编码:

string dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);

到:

string dataFromClient = Encoding.UTF8.GetString(bytesFrom);

还要在.Read()前加一个读超时,从10开始稍微增加看看有没有改变生效:

networkStream.ReadTimeout = 10;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-05
    • 1970-01-01
    • 1970-01-01
    • 2020-04-14
    • 1970-01-01
    相关资源
    最近更新 更多