当前位置:编程学习 > C#/ASP.NET >>

Socket的receive(buffer) 大小如何动态设置

我现在用Socket接收客户端发来的对象数据,但是对象的内容是变化的,可大可小,如果超过了我服务端的buffer大小就会处理出错,请问怎样让接收时的buffer大小自己适应发过来的数据? --------------------编程问答--------------------

byte[] recvBytes = new byte[5000000];
int bytes = socket.Receive(recvBytes, recvBytes.Length, 0);//接收时设置
--------------------编程问答-------------------- 我一般是在接收前设一个很大的数组,理论上能接收到客户端可能发来的最大数据。 --------------------编程问答--------------------
引用楼主 xiaogua 的回复:
我现在用Socket接收客户端发来的对象数据,但是对象的内容是变化的,可大可小,如果超过了我服务端的buffer大小就会处理出错,请问怎样让接收时的buffer大小自己适应发过来的数据?

即使1k的buffer也可以接受1G大的一个消息。Receive应该是在一个循环中,一个buffer一个buffer地循环接收数据流。给你一桶水,然后给你一个水杯,你会把桶里的水舀赶紧吗? --------------------编程问答-------------------- 给你一桶水,然后给你一个水杯,你会把桶里的水舀赶紧吗 --> 给你一桶水,然后给你一个水杯,你会把桶里的水舀出来吗 --------------------编程问答--------------------

public int Receive(
    byte[] buffer,
    int offset,
    int size,
    SocketFlags socketFlags
)


size是最多要接收的数量 --------------------编程问答--------------------
引用楼主 xiaogua 的回复:
我现在用Socket接收客户端发来的对象数据,但是对象的内容是变化的,可大可小,如果超过了我服务端的buffer大小就会处理出错,请问怎样让接收时的buffer大小自己适应发过来的数据?

你所看到的服务器千千万万,比如我们现在用到的web服务器。它的buffer能有多大?服务器端还是真正当作一个产品去设计、搞清其内部机制为好。 --------------------编程问答--------------------
引用 6 楼 sp1234 的回复:
引用楼主 xiaogua 的回复:
我现在用Socket接收客户端发来的对象数据,但是对象的内容是变化的,可大可小,如果超过了我服务端的buffer大小就会处理出错,请问怎样让接收时的buffer大小自己适应发过来的数据?

你所看到的服务器千千万万,比如我们现在用到的web服务器。它的buffer能有多大?服务器端还是真正当作一个产品去设计、搞清其内部机制为好。
同意,高手 --------------------编程问答--------------------
引用 4 楼 sp1234 的回复:
给你一桶水,然后给你一个水杯,你会把桶里的水舀赶紧吗 --> 给你一桶水,然后给你一个水杯,你会把桶里的水舀出来吗


我也是希望是这样的方式,但是用SocketAsyncEventArgs有没有可能实现这个方式? --------------------编程问答-------------------- 这个问题要根据实际情况确定了,数据量小的话可以保存在内存中处理,如果数据量大,比如网络电视、网上高清电影的话,可能就要在磁盘上虚拟一块存储区了,都有不同的处理方法 --------------------编程问答-------------------- 发送数据的时候,可以先发送8个字节,表示你的数据块的大小,然后再发送真实的数据
接收的时候,先接收8个字节,然后再定义,就好办了!
--------------------编程问答--------------------
引用楼主 xiaogua 的回复:
我现在用Socket接收客户端发来的对象数据,但是对象的内容是变化的,可大可小,如果超过了我服务端的buffer大小就会处理出错,请问怎样让接收时的buffer大小自己适应发过来的数据?



你的想法就不对。。。。。。。。。。。。。
有些东西是socket必须面对的,不是能逃避掉的。。。
很多方法都可以很好的处理你说的问题。。。。。合适的发送数据量、合适的间隔时间、数据的自我容错能力等等。。。 --------------------编程问答-------------------- 说这么多,没有一个是实质性的可以帮我解决这个问题的,可能我的问题不够明确,
我就是想用SocketAsyncEventArgs来解决这个传输中Buffer容量大小不一致而导致数据被截断的问题,
我是通过Socket来传递序列化成二进制的对象,对象的数据量是变化的,序列化的大小也会不同,如何保证我的对象数据传递正确?
最好有源码,例子.. --------------------编程问答-------------------- 初始化一个buffer的大小,因为socket数据包每次发送的数据量是有大小限制的,64k大小就ok了 --------------------编程问答-------------------- Code please --------------------编程问答--------------------
引用 8 楼 xiaogua 的回复:
引用 4 楼 sp1234 的回复:
给你一桶水,然后给你一个水杯,你会把桶里的水舀赶紧吗 --> 给你一桶水,然后给你一个水杯,你会把桶里的水舀出来吗


我也是希望是这样的方式,但是用SocketAsyncEventArgs有没有可能实现这个方式?


机制就是这样的 当有数据的时候通知你, 并告诉你本次接收到多少数据. 这个数据可能不是一个包.

有可能是2个包 或者半个包.

必须自己写一个类来处理这些包,进行拆分和组合工作.

tcp如果使用断开式,则不需要太过考虑客户端和服务器的数据传输问题.
如果是连接式 就必须考虑了.
--------------------编程问答-------------------- 如果要动态接收数据的话可以考虑不要用Receive,改用NetworkStream来接收

            NetworkStream stream = new NetworkStream(client);
            byte[] send = Encoding.UTF8.GetBytes("客户端==>流测试");
            stream.Write(send, 0, send.Length);
            List<byte> receive = new List<byte>();
            while (true)
            {
                int oneByte = stream.ReadByte();
                if (oneByte == -1)
                    break;
                receive.Add(Convert.ToByte(oneByte));
            }
            string text = Encoding.UTF8.GetString(receive.ToArray());
            this.Text = text; --------------------编程问答-------------------- 直接调用SendPackets --------------------编程问答-------------------- 整个文件可以一下子全部发送出去,而且不需要自己管理。。。 --------------------编程问答--------------------
引用 1 楼 zerodegrees 的回复:

byte[] recvBytes = new byte[5000000];
int bytes = socket.Receive(recvBytes, recvBytes.Length, 0);//接收时设置

这个应该能解决你的问题了吧
--------------------编程问答-------------------- 你不可能预测到接收数据的长度,因此你不必初始化一个很大的数组。
无论数组有多小,你只需要循环的读,就可以取得所有数据:

Byte[] bytesReceived = new Byte[256];
int bytes = 0;
string msg = string.Empty;

// The following will block until te page is transmitted.
do {
    bytes = s.Receive(bytesReceived, bytesReceived.Length, 0);  
    msg = msg + Encoding.ASCII.GetString(bytesReceived, 0, bytes); 
}
while (bytes > 0);
--------------------编程问答-------------------- 先接受长度,可以new一个适当的数组。
也可以输出到某个Stream中。 --------------------编程问答--------------------
引用 20 楼 Susiria 的回复:
你不可能预测到接收数据的长度,因此你不必初始化一个很大的数组。
无论数组有多小,你只需要循环的读,就可以取得所有数据:

Byte[] bytesReceived = new Byte[256];
int bytes = 0;
string msg = string.Empty;

// The following will block until te page is transmitted.
do {
    bytes = s.Receive(bytesReceived, bytesReceived.Length, 0);  
    msg = msg + Encoding.ASCII.GetString(bytesReceived, 0, bytes); 
}
while (bytes > 0);


这种方法遇到中文的情况就有可能发生截断产生乱码把 --------------------编程问答--------------------
引用 22 楼 y1018799688 的回复:
Quote: 引用 20 楼 Susiria 的回复:

你不可能预测到接收数据的长度,因此你不必初始化一个很大的数组。
无论数组有多小,你只需要循环的读,就可以取得所有数据:

Byte[] bytesReceived = new Byte[256];
int bytes = 0;
string msg = string.Empty;

// The following will block until te page is transmitted.
do {
    bytes = s.Receive(bytesReceived, bytesReceived.Length, 0);  
    msg = msg + Encoding.ASCII.GetString(bytesReceived, 0, bytes); 
}
while (bytes > 0);


这种方法遇到中文的情况就有可能发生截断产生乱码把


这倒是。可以换成List<byte>,循环结束后再转码成字符串。 --------------------编程问答-------------------- 楼主应该是用 tcp 接收数据的吧,那我描述一下正确的处理方法:
1 receive 的时候 buffer 的大小无所谓,另外新建一个 memorystream,接收了放里面。
   如果接收异常,或者接收到0长度的数据,关闭连接并退出。
2 必须有一个方法判断 memorystream 里面是否有完整的数据包,如果没有则回 1 继续接收。
3 如果已经有完整的数据包,进行处理,并记下数据包的大小
4 重新新建 memorystream,如果接收的数据大于数据包的大小,
  将剩余未处理的数据放入,回到 1 继续接收。 --------------------编程问答-------------------- receive是需要循环接收的,buff设置太大没用处,因为有MTU存在,一般MTU是在1.5K左右,超过1.5K的包会被自动分包发送的,我之前测试的,超过1.5K的包发到接收端,基本就会被拆成2个包,2次receive才能接收全部数据。 --------------------编程问答-------------------- 1)循环接受
2)通讯双方定义包协议,把数据的总大小发过来
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,