简体   繁体   English

NamedPipeServerStream接收MAX = 1024字节,为什么?

[英]NamedPipeServerStream receive MAX=1024 bytes, why?

I'm using a NamedPipeStream, client and server, I'm sending data from client to server, the data is a serialize object which include binary data. 我正在使用NamedPipeStream,客户端和服务器,我正在从客户端向服务器发送数据,数据是包含二进制数据的序列化对象。

When the server side receive the data, it always have MAX 1024 size while client send much more!! 当服务器端接收数据时,它总是具有MAX 1024大小,而客户端发送更多!! so when try to serialize the data, this cause the following exception: "Unterminated string. Expected delimiter: ". 因此,当尝试序列化数据时,会导致以下异常:“未终止的字符串。预期的分隔符:”。 Path 'Data', line 1, position 1024." 路径'数据',第1行,位置1024.“

the server buffer size defined as: 服务器缓冲区大小定义为:

protected const int BUFFER_SIZE = 4096*4;
var stream = new NamedPipeServerStream(PipeName,
                                                   PipeDirection.InOut,
                                                   1,
                                                   PipeTransmissionMode.Message,
                                                   PipeOptions.Asynchronous,
                                                   BUFFER_SIZE,
                                                   BUFFER_SIZE,
                                                   pipeSecurity);


        stream.ReadMode = PipeTransmissionMode.Message;

I'm using : 我正在使用 :

    /// <summary>
    /// StreamWriter for writing messages to the pipe.
    /// </summary>
    protected StreamWriter PipeWriter { get; set; }

The read function: 读取功能:

/// <summary>
/// Reads a message from the pipe.
/// </summary>
/// <param name="stream"></param>
/// <returns></returns>
protected static byte[] ReadMessage(PipeStream stream)
{
    MemoryStream memoryStream = new MemoryStream();

    byte[] buffer = new byte[BUFFER_SIZE];

    try
    {
        do
        {
            if (stream != null)
            {
                memoryStream.Write(buffer, 0, stream.Read(buffer, 0, buffer.Length));
            }

        } while ((m_stopRequested != false) && (stream != null) && (stream.IsMessageComplete == false));
    }
    catch
    {
        return null;
    }
    return memoryStream.ToArray();
}


protected override void ReadFromPipe(object state)
{
    //int i = 0;
    try
    {
        while (Pipe != null && m_stopRequested == false)
        {
            PipeConnectedSignal.Reset();

            if (Pipe.IsConnected == false)
            {//Pipe.WaitForConnection();
                var asyncResult = Pipe.BeginWaitForConnection(PipeConnected, this);

                if (asyncResult.AsyncWaitHandle.WaitOne(5000))
                {
                    if (Pipe != null)
                    {
                        Pipe.EndWaitForConnection(asyncResult);
                        // ...
                        //success;
                    }
                }
                else
                {
                    continue;
                }
            }
            if (Pipe != null && Pipe.CanRead)
            {
                byte[] msg = ReadMessage(Pipe);

                if (msg != null)
                {
                    ThrowOnReceivedMessage(msg);
                }
            }
        }
    }
    catch (System.Exception ex)
    {
        System.Diagnostics.Debug.WriteLine(" PipeName.ReadFromPipe Ex:" + ex.Message);
    }
}

I don't see in the client side where I can define or change the buffer size! 我没有在客户端看到我可以定义或更改缓冲区大小!

Any idea?! 任何的想法?!

The basic problem is that you didn't read enough. 基本问题是你读得不够。 You need to repeat the read operation if PipeStream.IsMessageComplete is false, and keep doing that until it returns true - that tells you the whole message has been read. 如果PipeStream.IsMessageComplete为false,则需要重复读取操作,并继续执行该操作,直到它返回true - 这告诉您已读取整个消息。 Depending on your deserializer, you might need to store the data in a buffer of your own, or create some wrapper stream to handle this for you. 根据您的反序列化程序,您可能需要将数据存储在您自己的缓冲区中,或者创建一些包装器流来为您处理此问题。

A simple example of how this could work for simple string deserialization: 一个简单的例子,说明这可以用于简单的字符串反序列化:

void Main()
{
  var serverTask = Task.Run(() => Server()); // Just to keep this simple and stupid

  using (var client = new NamedPipeClientStream(".", "Pipe", PipeDirection.InOut))
  {
    client.Connect();
    client.ReadMode = PipeTransmissionMode.Message;

    var buffer = new byte[1024];
    var sb = new StringBuilder();

    int read;
    // Reading the stream as usual, but only the first message
    while ((read = client.Read(buffer, 0, buffer.Length)) > 0 && !client.IsMessageComplete)
    {
      sb.Append(Encoding.ASCII.GetString(buffer, 0, read));
    }

    Console.WriteLine(sb.ToString());
  }
}

void Server()
{
  using (var server
    = new NamedPipeServerStream("Pipe", PipeDirection.InOut, 1, 
                                PipeTransmissionMode.Message, PipeOptions.Asynchronous)) 
  {
    server.ReadMode = PipeTransmissionMode.Message;      
    server.WaitForConnection();

    // On the server side, we need to send it all as one byte[]
    var buffer = Encoding.ASCII.GetBytes(File.ReadAllText(@"D:\Data.txt"));
    server.Write(buffer, 0, buffer.Length); 
  }
}

Just as a side-note - I can easily read or write as much data as I want at once - the limiting factor is the buffer I use, not the one the pipes use; 就像旁注一样 - 我可以轻松读取或写入我想要的数据 - 限制因素是使用的缓冲区,而不是管道使用的缓冲区; although I'm using a local named pipe, it might be different for a TCP pipe (though it'd be a bit annoying - it's supposed to be abstracted away from you). 虽然我使用的是本地命名管道,但TCP管道可能有所不同(尽管它有点烦人 - 它应该被抽象出来)。

EDIT: 编辑:

Okay, now it's finally obvious what your problem is. 好的,现在终于可以明白你的问题了。 You can't use a StreamWriter - when sending a message long enough, it will result in multiple Write calls on the pipe stream, resulting in multiple separate message for your data. 不能使用StreamWriter - 当发送消息足够长时,它将导致管道流上的多个Write调用,从而导致数据的多个单独消息。 If you want the whole message as a single message, you must use a single Write call. 如果要将整个消息作为单个消息,则必须使用单个Write调用。 For example: 例如:

var data = Encoding.ASCII.GetBytes(yourJsonString);
Write(data, 0, data.Length);

The 1024-long buffer is StreamWriter s, it has nothing to do with the named pipes. 1024长的缓冲区是StreamWriter ,它与命名管道无关。 Using StreamWriter / StreamReader is a bad idea in any networking scenario, even when working with raw TCP streams. 在任何网络方案中使用StreamWriter / StreamReader都是一个坏主意,即使使用原始TCP流也是如此。 It just isn't what it's designed for. 它不是它的设计目标。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM