如何对一个无类型的数据报进行分组与重组(200分)

  • 主题发起人 主题发起人 eire
  • 开始时间 开始时间
E

eire

Unregistered / Unconfirmed
GUEST, unregistred user!
例:<br> &nbsp;接收到一个pointer 类型数据报(const pData:pointer;cbDatasize:integer)<br> &nbsp;分割成自定义大小的包并在包中加入自定义信息例顺序号ID,在收到这些包后根据加入的ID进行重组.
 
record型达不到你的要求吗?<br>type<br> &nbsp;ptest = ^ttest;<br> &nbsp;Ttest = record<br> &nbsp; &nbsp;id: integer;<br> &nbsp; &nbsp;data: string[233];<br> &nbsp;end;<br> &nbsp;pTestList = array of ptest;
 
hsgrass多谢你的回答,这个pData是从VC调用方传来的数据,类型未知,pData 如何转到record类型,并可成功的组包呢.<br> ptest = ^ttest;<br> &nbsp;Ttest = record<br> &nbsp; &nbsp;id: integer;<br> &nbsp; &nbsp;data:
pointer;
<br> &nbsp;end;
 
知道长度就可以啦,你认为它是什么类型就是什么类型,如char, byte, integer....<br><br>var<br> rdata: integer;<br> rchar: char;<br> rArrChar: array[0..9] of char;<br> s: string;<br><br> data: pointer; // 如果是字数(integer),那么这就指向整数,字符就指向字符。<br>begin<br> &nbsp;rdata := 12345678;<br> &nbsp;data := @rdata;<br> &nbsp;showmessage(inttostr(pinteger(data)^));<br><br> &nbsp;rchar := 'A';<br> &nbsp;data := @rchar;<br> &nbsp;showmessage(pchar(data)^);<br><br> &nbsp;StrCopy(rArrChar, 'abcdefghi');<br> &nbsp;data := @rArrChar;<br> &nbsp;s := pchar(data);<br> &nbsp;showmessage(s);<br>end;
 
&quot;你可以自己定义一个协议呀. 用个池做等待 给每个协议一个握手. 如果太长就重发. 收到后进行合并. 根据一组ID进行合并. 就行了呀. &quot;<br>上面是一个叫微程的朋友说的,觉得很有道理,有做过的朋友吗?给点资料?(我才接触网络编程是新手)
 
分包就得得组包<br>网络数据有可能分包到达<br>所以最好加上包长度等标识<br>这样包的出错机率才会减小
 
太多东西要学了 。。。。有点乱。。。。。
 
tcp要分可以理解,udp需要分吗?
 
to baiduan,那如何避免UDP传送中丢包以及接收包顺序问题呢?
 
要学习,收藏
 
Java数据报之失序和丢包 <br>--------------------------------------------------------------------------------<br> <br>2005-08-29 &nbsp;点击:564 &nbsp;来源:CSDN &nbsp;作者:keepeye <br> &nbsp;<br>习惯了TCP编程,认为UDP可以包办这些问题是错误的。一个UDP应用程序要承担可靠性方面的全部工作,包括报文的丢失、重复、时延、乱序以及连接失效等问题。<br><br>通常我们在可靠性好,传输时延小的局域网上开发测试,一些问题不容易暴露,但在大型互联网上却会出现错误。<br><br>UDP协议把递送的可靠性责任推到了上层即应用层,下面简单编写了几个类来专门处理两个问题:乱序和丢包。
 
udp协议是1种无连接的协议,他和tcp协议比较有传输速度快,占用资源少的问题。<br>但是由于udp协议本身没有自动找包的功能,因此经常会出现丢包的现象,会造成传送的文件丢包的现象<br>因为时间匆忙和水平有限,本人在效率上没有作优化,只是简单的实现,请大家自己看源码吧<br>注释:<br>主要功能:把文件猜成4k大小的包 在包头+上包的长度 接受了1个包判断长度是否和接受的长度相符如果<br><br>符合那么就继续发,如果出现丢包那么就从发<br>希望大家有什么好的建议通知我,我会尽量完善的<br>Option Explicit<br>''''==============================================<br>''''===============================<br>''''udp传文件<br>''''客户端<br>''''作者: 影子<br>''''================================<br>''''==============================================<br>Dim FileNumber As Integer ''''用来存文件的句柄<br>Dim LenFile As Long ''''文件的长度<br>Private Sub Command2_Click()<br>closefile<br>End Sub<br><br>Private Sub Form_Load()<br>Winsock0.LocalPort = 5698<br>Winsock0.Bind<br>beginfile<br>End Sub<br>Private Sub Winsock0_DataArrival(ByVal bytesTotal As Long)<br>Dim FileByte() As Byte<br>Winsock0.GetData FileByte, vbArray + vbByte ''''接收类型为:字节数组<br>Dim mendByte() As Byte, i As Long, j As Long<br>Dim temp As String, temp1 As String<br>''''获得包长<br>j = UBound(FileByte)<br>''''合并包头<br> &nbsp;For i = 0 To 7 Step 2<br> &nbsp; &nbsp; &nbsp; &nbsp;temp = temp & Chr(FileByte(i))<br> &nbsp;Next<br>''''比较长度看丢包没有<br>If Val(temp) = j Then<br><br> &nbsp; &nbsp;ReDim mendByte(j - 8)<br>'''' &nbsp; &nbsp;提出包头<br> &nbsp; &nbsp; &nbsp; &nbsp;For i = 0 To j - 8<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mendByte(i) = FileByte(i + 7)<br> &nbsp; &nbsp; &nbsp; &nbsp;Next<br>'''' &nbsp; &nbsp; &nbsp; &nbsp;写文件<br> &nbsp; &nbsp;Put #FileNumber, , mendByte<br>'''' &nbsp; &nbsp;发送继续发送的请求<br> &nbsp; &nbsp;frmmain.Winsock0.SendData &quot;ok&quot;<br>Else<br>''''出现丢包,请求重发<br> &nbsp; &nbsp;frmmain.Winsock0.SendData &quot;no&quot;<br>End If<br>End Sub<br><br>Public Sub beginfile()<br> FileNumber = FreeFile ''''取得未使用的文件号<br>Open &quot;c:/aaa.exe&quot; For Binary As #FileNumber ''''打开文件<br>End Sub<br><br>Public Sub closefile() ''''关闭文件句柄<br> &nbsp; &nbsp; Close #FileNumber<br>End Sub<br><br>Option Explicit<br>Dim GetFileNum As Integer<br>Dim LenFile As Long<br>Dim Sendbaye() As Byte ''''发送的包<br>''''===============================<br>''''udp传文件<br>''''作者: 影子<br>''''服务器端<br>''''================================<br><br><br>Private Sub Command1_Click()<br> &nbsp; &nbsp; &nbsp; &nbsp;GetFileNum = FreeFile ''''取得未使用的文件号<br> &nbsp; &nbsp; &nbsp; &nbsp;LenFile = FileLen(&quot;d:/aa.rar&quot;) ''''获得需传送的文件的长度<br> &nbsp; &nbsp; &nbsp; &nbsp;Open &quot;d:/aa.rar&quot; For Binary As #GetFileNum ''''打开需传送的文件<br> &nbsp; &nbsp; &nbsp; &nbsp;Command1.Enabled = False<br>'''' &nbsp; &nbsp; &nbsp; &nbsp;传送文件<br> &nbsp; &nbsp; &nbsp; &nbsp;Call TCPSendFile(frmmain.Winsock0, GetFileNum, SplitFile)<br> &nbsp; &nbsp; &nbsp; &nbsp;Text1.Text = Now<br>End Sub<br><br>Private Sub Form_Load()<br>frmmain.Winsock0.RemoteHost = &quot;192.168.0.12&quot; ''''服务器ip<br>frmmain.Winsock0.RemotePort = 5698<br><br>End Sub<br>''''=========================================================================<br>''''为了清晰,下面分别用两个子过程来完成计算这次还可以传多少个字节的数据和传送数据<br>''''==========================================================================<br>Private Function SplitFile() As Long ''''拆包<br> &nbsp; &nbsp; &nbsp; &nbsp;On Error Resume Next<br> &nbsp; &nbsp; &nbsp; &nbsp;Dim GetCount As Long<br> &nbsp; &nbsp; &nbsp; &nbsp;''''计算出这次可发送的字节数<br> &nbsp; &nbsp; &nbsp; &nbsp;If LenFile &gt;= 4000 Then<br> &nbsp; &nbsp; &nbsp; &nbsp;GetCount = 4000<br> &nbsp; &nbsp; &nbsp; &nbsp;LenFile = LenFile - GetCount<br> &nbsp; &nbsp; &nbsp; &nbsp;Else<br> &nbsp; &nbsp; &nbsp; &nbsp;GetCount = LenFile<br> &nbsp; &nbsp; &nbsp; &nbsp;LenFile = LenFile - GetCount<br> &nbsp; &nbsp; &nbsp; &nbsp;End If<br> &nbsp; &nbsp; &nbsp; &nbsp;SplitFile = GetCount<br><br>End Function<br>Private Sub TCPSendFile(objWinSock As Winsock, FileNumber As Integer, SendLen As Long)<br> &nbsp; &nbsp; &nbsp; &nbsp;Dim FileByte() As Byte, i As Long, j As Long<br> &nbsp; &nbsp; &nbsp; &nbsp;Dim temp As String<br> &nbsp; &nbsp; &nbsp; &nbsp;ReDim Sendbaye(0)<br> &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp;Dim tempa As String * 4<br> &nbsp; &nbsp; &nbsp; &nbsp;ReDim FileByte(SendLen - 1)<br> &nbsp; &nbsp; &nbsp; &nbsp;tempa = SendLen + 7<br> &nbsp; &nbsp; &nbsp; &nbsp;Sendbaye = tempa '''' 把长度负值给包头<br> &nbsp; &nbsp; &nbsp; &nbsp;Get #FileNumber, , FileByte ''''读取文件<br> &nbsp; &nbsp; &nbsp; &nbsp;ReDim Preserve Sendbaye(SendLen + 7) ''''把包头+到文件头<br> &nbsp; &nbsp; &nbsp; &nbsp;For i = 0 To UBound(FileByte)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Sendbaye(i + 7) = FileByte(i)<br> &nbsp; &nbsp; &nbsp; &nbsp;Next<br> &nbsp; &nbsp; &nbsp; &nbsp;frmmain.Winsock0.SendData Sendbaye<br>End Sub<br><br>Private Sub Winsock0_DataArrival(ByVal bytesTotal As Long)<br>Dim str As String<br>frmmain.Winsock0.GetData str<br>Select Case str<br>Case &quot;ok&quot;<br>''''成功继续发送<br> &nbsp; &nbsp; &nbsp; &nbsp;If LenFile = 0 Then ''''发送完成<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MsgBox &quot;成功&quot;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Exit Sub<br> &nbsp; &nbsp; &nbsp; &nbsp;End If<br> &nbsp; &nbsp; &nbsp; Call TCPSendFile(frmmain.Winsock0, GetFileNum, SplitFile)<br>Case &quot;no&quot;<br>''''不成功重发上一个包<br> &nbsp; &nbsp; &nbsp; &nbsp;frmmain.Winsock0.SendData Sendbaye<br>End Select<br>End Sub
 
上面VB对包的无序没作处理
 
我觉得用UDP协议做软件有可能需要自己增加安全性,但是TCP应该是不需要的,因为在其它层(不记得了,好象是IP层)已经做了这部分的工作。不知道你的软件是使用的什么协议?网络编程其实还是有一些难度的,一些细节,如果你不清楚会有很多问题。期待高手的做答!
 
你管它是什么类型的<br>它就是二进制流<br>把它分成块<br>放进你自己定义的机构体里面好了
 
如果是TCP协议的话,看是什么层了.<br>如果物理帧,需要自己写TCP协议栈.不过WINSOCK.PAS有个地方定义有错误<br>ntohl函数定义错误<br>解决:在单元里面自己重新定义<br>const<br> &nbsp;winsocket = 'wsock32.dll';<br>function ntohl(netlong: DWORD): DWORD; stdcall; external winsocket name 'ntohl'; //注意:Delphi本身的定义错误<br><br>不要小看这个定义.有一次做Tcp协议栈的时候:<br><br>if TcpCache.affirm &gt; ntohl(pTcpPacket^.tcphdr.th_seq) then<br>begin<br>//确认过了,表示是重发数据包<br>StrPCopy(cTemp,Format('%s重发数据包(%s),No=%d,seq=%u,ack=%u',HeadMsg,FlagName,i,ntohl(pTcpPacket^.tcphdr.th_ack),ntohl(pTcpPacket^.tcphdr.th_seq)]));<br>就是因为这个定义让我调试了差不多一天时间.从头到尾检查了几次那庞大的代码,<br>逻辑都是正确的,最后才发现是这里出问题了.
 
不过TCP包只会存在重发包和乱序包,不会存在丢弃包.
 
jingtao大侠:<br> &nbsp; 如何在接收方请求重发未收到的包,在发送方如何接收,定位,并重发?
 

Similar threads

S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
900
SUNSTONE的Delphi笔记
S
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
后退
顶部