C#中开始/ EndReceive - 如何阅读大量数据? [英] C# Begin/EndReceive - how do I read large data?

查看:632
本文介绍了C#中开始/ EndReceive - 如何阅读大量数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在说,1024块读取数据时,我该如何继续有没有留下任何数据,直到从接收的消息大于1024字节读取套接字?如果我只是用BeginReceive读取数据包的长度preFIX只,然后一旦被检索,使用接收()(在异步线程)读取数据包的其余部分?或有另一种方式?

When reading data in chunks of say, 1024, how do I continue to read from a socket that receives a message bigger than 1024 bytes until there is no data left? Should I just use BeginReceive to read a packet's length prefix only, and then once that is retrieved, use Receive() (in the async thread) to read the rest of the packet? Or is there another way?

我想乔恩斯基特的链接有解决方案,但有一点与code一speedbump的。在code我用的是:

I thought Jon Skeet's link had the solution, but there is a bit of a speedbump with that code. The code I used is:

public class StateObject
{
    public Socket workSocket = null;
    public const int BUFFER_SIZE = 1024;
    public byte[] buffer = new byte[BUFFER_SIZE];
    public StringBuilder sb = new StringBuilder();
}

public static void Read_Callback(IAsyncResult ar)
{
    StateObject so = (StateObject) ar.AsyncState;
    Socket s = so.workSocket;

    int read = s.EndReceive(ar);

    if (read > 0) 
    {
    	so.sb.Append(Encoding.ASCII.GetString(so.buffer, 0, read));

    	if (read == StateObject.BUFFER_SIZE)
    	{
    		s.BeginReceive(so.buffer, 0, StateObject.BUFFER_SIZE, 0, 
    				new AyncCallback(Async_Send_Receive.Read_Callback), so);
    		return;
    	}
    }

    if (so.sb.Length > 0)
    {
    	//All of the data has been read, so displays it to the console
    	string strContent;
    	strContent = so.sb.ToString();
    	Console.WriteLine(String.Format("Read {0} byte from socket" + 
    	"data = {1} ", strContent.Length, strContent));
    }
    s.Close();
}

现在这个纠正工作正常的大部分时间,但是当的数据包的大小是缓冲区的多个失败。这样做的原因是,如果缓冲器被填充上,假定有更多的数据读操作;但同样的问题发生前。 A 2字节的缓冲区,为〔实施例,大干快上一个4字节的数据包充满了两次,并假定有更多的数据。然后,它阻止,因为没有什么留下来阅读​​。 的问题是,接收函数不知道什么时候该数据包的到底是什么。

Now this corrected works fine most of the time, but it fails when the packet's size is a multiple of the buffer. The reason for this is if the buffer gets filled on a read it is assumed there is more data; but the same problem happens as before. A 2 byte buffer, for exmaple, gets filled twice on a 4 byte packet, and assumes there is more data. It then blocks because there is nothing left to read. The problem is that the receive function doesn't know when the end of the packet is.


这让我思考两个可能的解决方案:我可以要么结束包的分隔符或者我可以读取数据包报头找到的长度,然后准确地收到金额(如我原来的建议)

This got me thinking to two possible solutions: I could either have an end-of-packet delimiter or I could read the packet header to find the length and then receive exactly that amount (as I originally suggested).

有与每个问题,但。我不喜欢使用的分隔符,作为一个用户可以在某种程度上的工作,成为一个数据包从应用程序的输入字符串和螺钉它的想法。它也似乎只是有点儿马虎给我。

There's problems with each of these, though. I don't like the idea of using a delimiter, as a user could somehow work that into a packet in an input string from the app and screw it up. It also just seems kinda sloppy to me.

长度头听起来不错,但我打算使用协议缓冲区 - 我不知道数据的格式。是否有一个长头?多少个字节是什么呢?请问这是什么我实现自己?等等。

The length header sounds ok, but I'm planning on using protocol buffers - I don't know the format of the data. Is there a length header? How many bytes is it? Would this be something I implement myself? Etc..

我应该怎么办?

推荐答案

没有 - 电话 BeginReceive 再次从回调处理程序,直到 EndReceive 返回0。基本上,你应该继续接收异步,假设你要异步IO的最大利益。

No - call BeginReceive again from the callback handler, until EndReceive returns 0. Basically, you should keep on receiving asynchronously, assuming you want the fullest benefit of asynchronous IO.

如果你看一下MSDN页面 Socket.BeginReceive 你会看到这样的一个例子。 (诚​​然,它不是那么容易遵循,因为它可能是。)

If you look at the MSDN page for Socket.BeginReceive you'll see an example of this. (Admittedly it's not as easy to follow as it might be.)

这篇关于C#中开始/ EndReceive - 如何阅读大量数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆