1

简单情况:

Socket 上的客户端将格式的文件(数据)的片段(例如,256 字节)发送byte []到服务器。服务器异步接收数据。如何确定文件(数据)何时传输完毕?(服务器端)

这是服务器端负责接收数据的代码

public static void ReadCallback(IAsyncResult ar)
{
        String content = String.Empty;

        // Retrieve the state object and the handler socket
        // from the asynchronous state object.
        StateObject state = (StateObject)ar.AsyncState;
        Socket handler = state.workSocket;


        // Read data from the client socket. 
        int bytesRead = handler.EndReceive(ar);

        if (bytesRead > 0)
        {

            BinaryWriter writer = new BinaryWriter(File.Open(@"D:\test.png", FileMode.Append));

            writer.Write(state.buffer, 0, bytesRead);
            writer.Close();

            // All the data has been read from the 
            // client. Display it on the console.
            Console.WriteLine("Read {0} bytes from socket!",
                bytesRead);

            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                new AsyncCallback(ReadCallback), state);
        }
}

有没有一种方法可以进行以下操作?

if (bytesRead > 0)
{

     ....
     if(state.buffer!=end of receive)
     {
     handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
         new AsyncCallback(ReadCallback), state);
     }

}

或者,我可能会尝试向这个byte[]对象添加一些信息(例如,一些带有标签的字符串<EOF>),但我必须在每个步骤中分析这些信息。我可以更简单地做这个检查吗?如何做?或者使用其他方式...

4

1 回答 1

0

唯一的方法是在每条消息前发送一个标头(特定大小)。因此,每条消息都应该由标题和正文组成。数据流应如下所示:

[HEADER][BODY][HEADER][SOME BIGGER BODY][HEADER][SOME EXTRA BIG BODY]

正如我所说,标头应该具有特定的大小,并且应该包含一些自定义服务字段,包括消息正文的大小(以字节为单位)。在您的情况下,标头只能包含正文大小,即 int 值(4 个字节)。接收过程应如下所示:

  1. 接收 4 个字节(头);
  2. 从标题中检索正文大小(只需将标题转换为 int);
  3. 接收header中指定的字节数(即接收消息体);
  4. 处理消息体;
  5. 转到 1。

我知道,这对您来说可能看起来很复杂,但这是常见的方法。但是您可以使用Rx library来简化代码。在为 socket 实现了一些扩展方法之后(WhenReadExact,实现可以很容易地在 Internet 上找到,例如这里),代码将如下所示:

var whenFileReceived = from header in socket.WhenReadExact(4)
                       let bodySize = BitConverter.ToInt32(header)
                       from body in socket.WhenReadExact(bodySize)
                       select body;

whenFileReceived.Subscribe(
    file =>
    {
        // Handle file here
    });
于 2012-10-17T23:41:08.473 回答