【问题标题】:Sending multiple data in TCPSocket在 TCPSocket 中发送多个数据
【发布时间】:2011-12-19 05:16:30
【问题描述】:

我正在尝试使用 TCPSocket 创建与文件传输应用程序的聊天,这是我的代码..

发件人:

public void sendData(string message)
{
    StreamWriter streamWriter = new StreamWriter(netStream); // netStream is 
                                                             // connected   
    streamWriter.WriteLine(message);
    streamWriter.WriteLine(message);
    logs.Add(string.Format("Message Sent! :{0}", message));
    //netStream.Flush();
    streamWriter.Flush();
}

接收者:

private void ReceiveData()
{
    StreamReader streamReader = new StreamReader(ChatNetStream);

    StringBuilder dataAppends = new StringBuilder();
    bool doneTransfer = false;
    string data;
    while (!doneTransfer)
    {
        while ((data = streamReader.ReadLine()) != null)
        {
            dataAppends.Append(data);
        }
        doneTransfer = true;
        //ChatNetStream.Close();
        //streamReader
    }

    //do whatever i want with dataAppends.ToString() here..
   ReceiveData()
}

问题是我总是在这个语句中变成无限循环

while ((data = streamReader.ReadLine()) != null)
{
    dataAppends.Append(data);
}

即使我将 streamWriter.Flush() 放在我的发件人上..

我需要关闭/处置 netStream/NetworkStream 吗?

无论如何,我可以只使用 1 个套接字或连接来发送文件并同时发送聊天..吗?还是我每次发送文件时都需要使用新的套接字连接..

【问题讨论】:

  • 您应该使用 2 个套接字,如果您发送一个大文件,它将阻止聊天,除非您在每个数据包上提供一个标头来检测它是对话还是文件的另一部分。

标签: c# network-programming tcpclient


【解决方案1】:

你会得到一个无限循环,因为StreamReader.ReadLine 只会在到达流的末尾时返回null。对于网络流,“流结束”意味着“另一端已经关闭了它的一半连接”。由于另一端是你的客户端,它在等待用户输入更多数据的同时保持连接打开,你最终会陷入无限循环。

您想要做的是触发仅在有更多数据要读取时完成的操作。有两种方法可以解决这个问题:使用阻塞读取操作(在专用线程上,这样您在等待消息时不会阻塞应用程序的其他处理),或者使用异步(基于事件或回调)接近。

对于同步(阻塞)方法,请参阅NetworkStream.Read 上的文档,其中包含显示如何检查是否有传入数据以及如何读取数据的示例代码。这里你绝对需要知道的一点是,当Read 返回零时,这意味着所有数据都已被读取并且连接已从另一侧关闭(所以你也应该关闭你的一端而不是循环;客户端已断开连接)。

对于低级异步网络读取,相关操作为NetworkStream.BeginRead,自带示例。

这两种方法都比您目前拥有的方法低级,并且需要您在缓冲区内手动组装数据,并决定何时积累了“足够的数据”(即整行)供您处理。然后,您必须小心地将数据从缓冲区中拉出并继续。

对于仍然允许您在一定程度上协调事物的更高级别的方法,请查看using client sockets(尤其是那里的两个同步和异步选项)。此功能由TcpClient(和服务器端对应的TcpListener)类引入。

最后,正如 jValdron 的评论所说,您将需要一个单独的连接来传输文件数据设计一些自定义协议,允许您在同一网络流上交错多种数据。第二种解决方案通常具有更多技术优势,但您也更难正确实施。

【讨论】:

    【解决方案2】:

    查看networkComms.net 中的 BasicSend 示例,该示例演示了一个使用开源库的简单聊天应用程序。

    【讨论】: