udp 如何发送较大的数据?

问题描述

我用udpclient发送数据,将数字拆分成若干个数组(每次发送的数据大小为:byte[1470])然后循环发送.发送8次以下没有问题。但是超过8次的数据量就接受不到了。最多只能接收到7个数据包。发送用的是udp.send();此发送没有用异步应该是没有问题的,8个包以下的数据量就没有问题。发送超过7次时接收到最多只有收到7个包。//接收数据的代码用的是udpClient的BeginReceive和EndReceive方法。不知道那里有问题。是不是udp或套接字对发送数据的次数有限制,还是代码不对,请大侠们指点下

解决方案

解决方案二:
该回复于2011-12-15 09:52:20被版主删除
解决方案三:
高手们冒个泡啊
解决方案四:
该回复于2011-12-15 09:53:12被版主删除
解决方案五:
你测试下数据小些,还是8个包看看什么效果
解决方案六:
该回复于2011-12-15 09:08:51被版主删除
解决方案七:
这个,个人感觉没有什么关系,除非是大数据量。调试跟踪一下,看看发送跟接收的数据是否一致,接收后分组操作是否正确,所有组的数据跟发送的作比较...
解决方案八:
引用6楼chenandczh的回复:

这个,个人感觉没有什么关系,除非是大数据量。调试跟踪一下,看看发送跟接收的数据是否一致,接收后分组操作是否正确,所有组的数据跟发送的作比较...

我能够确认发送是正确的,但是在接收的时候就是接收不到第7次和以后发送的数据,当我发送次数7次的总共数据量为:1470*7=10290个字节,此时我就接收不到第七个包了。10290数量很小啊,如果我不分包发送的话好像最多只能更够发送8192个字节吧
解决方案九:
这个是我发送的代码:publicvoidSendBySize(objectobj){lock(sendLock){LIS_Message.LisMessagemessage=(LIS_Message.LisMessage)obj;intPacketSize=1470;longsendSN=GetSendSN();Socketuc=newSocket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);uc.EnableBroadcast=true;uc.Connect("255.255.255.255",3729);MemoryStreamms=newMemoryStream();BinaryFormatterb=newBinaryFormatter();b.Serialize(ms,message);byte[]m_content=ms.ToArray();longMsLength=ms.Length;ms.Close();intsendLength=0;//已发送数据长度intLastPageSize=0;//最后一个包大小byte[]datas=newbyte[PacketSize];//声明字节数组intCurPackSize=0;//当前包大小//计算出总共需要分多少包才可以发送完一个消息intMaxPacketCount=(int)Math.Ceiling(double.Parse(MsLength.ToString())/double.Parse((PacketSize-28).ToString()));LastPageSize=(int)MsLength%(PacketSize-28)+28;//得到最后一个包的长度for(inti=0;i<MaxPacketCount;i++){if(i==MaxPacketCount-1){datas=newbyte[LastPageSize];CurPackSize=LastPageSize;}else{CurPackSize=PacketSize;datas=newbyte[PacketSize];}BitConverter.GetBytes(sendSN).CopyTo(datas,0);//消息编号0-8位BitConverter.GetBytes(i).CopyTo(datas,8);//此包体在消息的位置8-12BitConverter.GetBytes(MaxPacketCount).CopyTo(datas,12);//包个数12-16BitConverter.GetBytes(CurPackSize).CopyTo(datas,16);//当前包大小BitConverter.GetBytes(MsLength).CopyTo(datas,20);//消息总大小20-27if(i==MaxPacketCount-1){Array.Copy(m_content,sendLength,datas,28,CurPackSize-28);}else{Array.Copy(m_content,sendLength,datas,28,CurPackSize-28);}sendLength+=(CurPackSize-28);uc.Send(datas,SocketFlags.None);//发送}uc.Close();Thread.Sleep(5);}}

这个是我接收数据EndReceived的回调方法,这里无法接收到第7个以后的数据包:privatevoidgetMessage(objectobj){byte[]data=(byte[])obj;byte[]headSN=newbyte[8];byte[]sort=newbyte[4];byte[]PacketCount=newbyte[4];byte[]content=newbyte[data.Length-28];//byte[]packSize=newbyte[4];//当前包长度byte[]msLength=newbyte[8];try{Array.Copy(data,0,headSN,0,8);Array.Copy(data,8,sort,0,4);Array.Copy(data,12,PacketCount,0,4);Array.Copy(data,20,msLength,0,8);Array.Copy(data,28,content,0,data.Length-28);}catch(Exceptionex){MessageBox.Show("复制错误:"+ex.Message);}try{lock(thisLock){MessageTemptemp=newMessageTemp();temp.receiveTime=DateTime.Now;//获得包序号temp.SN=BitConverter.ToInt64(headSN,0);temp.sort=BitConverter.ToInt32(sort,0);temp.PacketCount=BitConverter.ToInt32(PacketCount,0);temp.Content=content;temp.messageSize=BitConverter.ToInt64(msLength,0);listTempData.Add(temp);if(temp.PacketCount==temp.sort+1)//最后一包{List<MessageTemp>M_list=listTempData.FindAll(newPredicate<MessageTemp>(delegate(MessageTempm){returnm.SN==temp.SN;}));M_list.Sort(newMessageSort());byte[]MessageContent=newbyte[temp.messageSize];intindex=0;for(inti=0;i<M_list.Count;i++){try{MessageTempt=M_list[i];Array.Copy(t.Content,0,MessageContent,index,t.Content.Length);index+=t.Content.Length;}catch(Exceptionex){stringe=ex.Message;stringa=e+"";}}for(inti=0;i<M_list.Count;i++){listTempData.Remove(M_list[i]);}System.IO.MemoryStreamms=newSystem.IO.MemoryStream(MessageContent,0,MessageContent.Length);BinaryFormatterb=newBinaryFormatter();LisMessagemessage=b.Deserialize(ms)asLisMessage;SOCKETEventArrive2(message);}}}catch(Exceptionex){MessageBox.Show("接收错误:"+ex.Message);}}

解决方案十:
缓存问题造成的,你发送太快,对方来不及接收,网卡缓存了7个包,之后的缓存里放不下就丢了。其实是你没有处理收发同步问题,TCP的三次握手自动处理了收发同步,但是UDP有没自动处理,发送方只管发,不管对方是否来得及收。必须每发送一个包,等待对方UDP返回一个确认包,也就是把三次握手变为了二次,同时不需要保持连接,速度自然比TCP快,但是要处理的细节比TCP多得多。
解决方案十一:
引用9楼qldsrx的回复:

缓存问题造成的,你发送太快,对方来不及接收,网卡缓存了7个包,之后的缓存里放不下就丢了。其实是你没有处理收发同步问题,TCP的三次握手自动处理了收发同步,但是UDP有没自动处理,发送方只管发,不管对方是否来得及收。必须每发送一个包,等待对方UDP返回一个确认包,也就是把三次握手变为了二次,同时不需要保持连接,速度自然比TCP快,但是要处理的细节比TCP多得多。

也就是说我在发送每一个包得时候需要等待对方发一个包回应,然后我再继续发下一个包?
解决方案十二:
当然了,不然你怎么知道对方已经接收?发送的时候不会自动等待对方接收,没这样的信号,只能程序中判断对方发回的响应包(包内数据少的话,基本不占带宽)。
解决方案十三:
引用11楼qldsrx的回复:

当然了,不然你怎么知道对方已经接收?发送的时候不会自动等待对方接收,没这样的信号,只能程序中判断对方发回的响应包(包内数据少的话,基本不占带宽)。

是的啊,我在每次send之后Sleep(50)就好了
解决方案十四:
引用11楼qldsrx的回复:

当然了,不然你怎么知道对方已经接收?发送的时候不会自动等待对方接收,没这样的信号,只能程序中判断对方发回的响应包(包内数据少的话,基本不占带宽)。

我是发送给所有的用户(255.255.255.255),能否发送给指定的几个ip?还是需要循环发送?
解决方案十五:
指定几个IP就需要循环发送了,不过发送所有用户是无法获取确认包,而指定IP就可以获取了另外测算下每个包大小和实际的带宽的话,按照每秒200KB的速度,那么200*1024/1470=139,也就是说,你控制200KB/S的速度发送的话,1秒内只能发送139个包,每个包需要的时间是1/139=0.007,大概每隔7毫秒就可以发送一次了。总之,先计算实际带宽可能的上限,然后推断安全的速度,不然UDP就很容易丢包了。
解决方案:
引用14楼qldsrx的回复:

指定几个IP就需要循环发送了,不过发送所有用户是无法获取确认包,而指定IP就可以获取了另外测算下每个包大小和实际的带宽的话,按照每秒200KB的速度,那么200*1024/1470=139,也就是说,你控制200KB/S的速度发送的话,1秒内只能发送139个包,每个包需要的时间是1/139=0.007,大概每隔7毫秒就可以发送一次了。总之,先计算实际带宽可能的上限,然后推断安全的速度……

对于接收数据我还是有个问题想请教下大哥:发送太快的时候,在接收的时候数据会不会合并到一个byte数组里?丢失包的原因我还是不确定,我接收的时候先处理接收到数据,处理完之后再去接收(beginReceive),类似于递归,如果发送的过快的话我还是接收不到数据。因为在处理接收时需要时间,而这段时间没有调用接收的方法?
解决方案:
这里有个文章很不错,建议你看看。这里面提到了UDP的包最大可以64K字节,如果你直接发送64K字节的UDP数据包,理论上也可以成功,在MTU上会自动拆包,到了接收端自动组装包,但是这个自动组装有个条件,就是要所有的碎片包都能收到才会组装,所以这里不确定因素很大,一旦丢了一个碎片包,整个大包都发送失败。所以一般都是自己拆成小于MTU的大小发送的。引用

EthernetMTUisusually1500bytes,butsomeconnections(suchasdial-upandsometunnelingprotocols)haveanMTUof1280bytes.Practicallyspeaking,itishardtodiscovertheminimumMTUofalink,sochoosingapacketsizeoflessthan1280(or1500)willincreasereliability.

至于你所说的是否会合并,那个答案很清楚了,如果发送方是分成小包发送的,接收方不会自动合并,如果发送方是一个大包,通过MTU自动拆包发送的,那么接收方就会合并。丢包除了发送过快,正常情况下也会出现,所以说UDP不安全,需要自己验证是否丢包,并重发所丢的包,这方面的技术知识,上面贴的链接里有示例代码,请自行研究。

时间: 2024-10-13 08:58:21

udp 如何发送较大的数据?的相关文章

windows socket编程客户端怎么使用recv函数接受服务器发送的大数据

问题描述 windows socket编程客户端怎么使用recv函数接受服务器发送的大数据 我写了个客户端接受服务器的数据,用recv接收,当缓冲区的大小小于发送的数据的大小后 要怎么处理recv函数,本人刚开始学习socket编程,还望大神们赐教啊!!!!! 解决方案 用while循环一直recv就可以了 解决方案二: 一直recv就可以了 解决方案三: 服务器和客户端两边的数据都安固定大小重复发送收取.可以把大小放小一些比较灵活,比如4096个字节

C++ UDP Socket发送速率

问题描述 C++ UDP Socket发送速率 我写了一个UDP发送数据的程序,每个包设置为1024B,如果不控制发送,一直循环sendto,接收端就会丢包,如果一直sendto一次就Sleep(1),发送速度又太慢了,网络发送速率才65KB/s,求大神有没有什么好的解决办法? 解决方案 /***********服务端程序************/#include <Winsock2.h>#include <stdio.h> void main(){ WORD wVersionRe

如何发送HTML表单数据

多数时候,HTML表单的目的只是为了把数据发给服务器,之后服务器再处理这些数据并发送响应给用户.虽然看起来挺简单的,但我们还是得注意一些事情以确保传送的数据不会破坏服务器.或者给你的用户制造麻烦. 数据会到哪里去 关于客户端/服务器架构 整个web都是基于一种基本的客户端/服务器架构,该架构可以归纳如下: 一个客户端(通常是Web浏览器)使用HTTP协议发送一个请求给服务器(通常是web服务器程序,譬如Apache, Nginx, IIS, Tomcat等等),而服务器则以相同的协议响应这个请求

atagram ocket-java udp DatagramSocket 发送接收消息

问题描述 java udp DatagramSocket 发送接收消息 使用如下代码发送并接收消息: SocketClient client = new SocketClient(); String serverHost = ""127.0.0.1""; int serverPort = 3333; client.send(serverHost serverPort (""你好,阿蜜果!"").getBytes()); Str

java以webservice形式向发送远程数据,发送时出现重复数据,如何解决?

问题描述 java以webservice形式向发送远程数据,发送时出现重复数据,如何解决? 我是用java从本地数据库中(oracle)提取数据后,封装,发送给远程服务器,然后远程服务器会返回发送结果代码. 我在主表中的每条数据都有一个字段显示其发送次数,还有一个字段显示发送结果.再有一张结果表,专门存储每条数据每次发送的结果和错误原因等详细信息.两张表是一对多关系.主表对每条数据是唯一的,当发送完,次数字段会增加1,发送结果也会更新 最新一次数据发送的结果.平时数据量小的时候完全没有问题,比如

5大开源数据存储解决方案推荐

文章讲的是5大开源数据存储解决方案推荐,用于存储大数据的解决方案是当今面临的巨大技术挑战.当然,有很多不同的选择,如RDBMS,NoSQL,时间序列数据库等,本文分析了五个数据存储解决方案,这些方案是为不同目的而创建的,但所有方案都可用于保存基于时间的日志. 数据存储仅将事件保存到数据库是不够的,每个数据存储库都必须有一个接口以实时搜索,并具有良好的性能,每天至少能够存储40GB的数据,总数据大小至少约为20TB,搜索日志消息应该实时完成,搜索查询的响应时间小于10秒. 1.ClickHouse

udp获取发送端的发送端口

问题描述 udp获取发送端的发送端口 udp进行数据接收,怎样获取发送方的发送端口,用GetPeerName()函数不行啊!谢谢大家!

JDBC读写MySQL的大字段数据

不管你是新手还是老手,大字段数据的操作常常令你感到很头痛.因为大字段有些特 殊,不同数据库处理的方式不一样,大字段的操作常常是以流的方式来处理的.而非一般 的字段,一次即可读出数据.本人以前用到Spring+iBatis架构来操作大字段,结果以惨 烈失败而告终,在网上寻求解决方案,也没找到答案.最终以JDBC来实现了大字段操作部 分. 本文以MySQL为例,通过最基本的JDBC技术来处理大字段的插入.读取操作. 环境: MySQL5.1 JDK1.5 一.认识MySQL的大字段类型 BLOB是一

html显示长度较大的数据时的处理方法

  在html中显示长度较大的数据时,可以将数据截取显示,当鼠标滑过时再显示完整数据. 例如,下面这种情况. 实现: 代码如下: <a title="${siteBoardInfoList.boardUrl}"> <c:if test="${fn:length(siteBoardInfoList.boardUrl) >= 40}"> ${fn:substring(siteBoardInfoList.boardUrl,0,20)}....