【问题标题】:How can I read socket stream until newline?如何读取套接字流直到换行?
【发布时间】:2018-11-05 21:42:01
【问题描述】:

我有一个 Node.js 服务器 + Unity (.NET 3.5) 应用程序,我确保通过套接字进行通信。我在从 Node.js 服务器接收数据到 C# 套接字客户端时遇到问题。

我希望我的 C# 客户端读取套接字流,直到找到换行符 (/n)。这就是我确保数据从 C# 流向 Node.js 服务器的方式,因为有一个名为 split 的 NPM 模块可以确保逐行读取缓冲区。

以下是我的代码,如果您能提出解决方案以实现上述接收数据的方式,我将不胜感激:

在这里,我毫无问题地连接到 Node.js 服务器:

private Socket ClientSocket;
private byte[] _receiveBuffer = new byte[8142];

public string hostname;
public int port;

public void onnectClient()
{
    ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    ClientSocket.Connect(hostname, port);
    ClientSocket.BeginReceive(_receiveBuffer, 0, _receiveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
}

以下是当前ReceiveCallback,:

private void ReceiveCallback(IAsyncResult AR)
{
    int received = ClientSocket.EndReceive(AR);
    byte[] recData = new byte[received];
    Buffer.BlockCopy(_receiveBuffer, 0, recData, 0, received);

    string resultString = System.Text.Encoding.UTF8.GetString(recData);

    currentlyReceivedData = JsonUtility.FromJson<ReceivedData>(resultString);

    ClientSocket.BeginReceive(_receiveBuffer, 0, _receiveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
}

更新 1:

现在我使用 TcpClient 和 StreamReader 代替上面的代码,但是由于某种原因,while 循环没有继续:

    private void ListenForData()
{
    try
    {
        socketConnection = new TcpClient("localhost", 6670);
        Byte[] bytes = new Byte[1024];
        while (true)
        {

            using (StreamReader sr = new StreamReader(socketConnection.GetStream()))
            {
                string line;
                // Read and display lines from the file until the end of 
                // the file is reached.
                while ((line = sr.ReadLine()) != null)
                {
                    Debug.Log("line");
                }
            }
        }
    }
    catch (SocketException socketException)
    {
        Debug.Log("Socket exception: " + socketException);
    }
}

【问题讨论】:

  • 只是想指出,当您拨打EndReceive 时,不能保证您会一次性收到完整的数据。当完整数据的大小大于缓冲区时,您必须处理 senario,或者由于网络缓慢而仅获取部分数据。
  • SwiftingDuster,这实际上是我猜我的问题!在某些时候,来自 Node.js 服务器的流程只是阻塞,我不再收到任何数据:/

标签: c# .net sockets


【解决方案1】:

如果您不需要使用Socket 的所有可用选项,我建议您改用TcpClient 类。连接后,您可以调用GetStream() 以接收NetworkStream1,您可以将其传递给StreamReader

到达那里后,您只需致电ReadLine()(或道德等价物)即可检索每个完整的行。这使您可以忽略使用“原始” TCP 的许多现实情况,例如必须重建/保存缓冲区以反映它不是消息传递而是字节流的现实。

ReadLine 可以处理任何正常形式的行尾,包括\n\r\r\n


1请注意,您可以从现有的Socket 构建一个作为替代方案。但我会尝试使用更简单的选项,除非我需要更复杂的选项。

【讨论】:

  • 您好 Damien_The_Unbeliever,感谢您的回复!你能检查一下我上面的更新版本吗?由于某种原因,while(true) 循环不会继续...
【解决方案2】:

我建议你看看这个:https://blogs.msdn.microsoft.com/dotnet/2018/07/09/system-io-pipelines-high-performance-io-in-net/

这可以为你省去不少麻烦!

如果您不能使用 System.IO.Pipelines,您仍然可以学习示例如何从套接字读取,直到您到达新行!

【讨论】:

  • 你好尼克!非常感谢您的回答,这看起来确实像我正在寻找的。我应该说我对 .NET 框架还很陌生,在 Node 之后的思维方式方面这是一个巨大的变化。您能否还建议我如何使用此解决方案启动读取套接字缓冲区?你认为 BeginReceive 是正确的方式吗?
  • 查看@Damien_The_Unbeliever 的回答 - 在您的情况下使用 TcpClient 是一个更好的主意。
猜你喜欢
  • 1970-01-01
  • 2011-05-13
  • 1970-01-01
  • 1970-01-01
  • 2016-06-28
  • 1970-01-01
  • 2022-06-16
  • 1970-01-01
  • 2016-02-11
相关资源
最近更新 更多