VB.NET关于Socket分包发送的原理分析

关于Socket编程,我之前一直处于小数据传输的阶段,就像什么多人聊天之类的,这几天项目碰到了要做在线更新,就想着肯定要静静的写一个非文字信息传输的Socket程序

 

难点在于:

1、Socket编程中,发送数据和接受数据都需要声明一个缓冲区来存放数据,这个缓冲区的大小设置有讲究,大了可以提高数据传输效率,但是会增加丢包、粘包等现象,小了数据传输效率低,速度减慢并且程序计算量增大

2、一个大的文件不可能直接声明和他大小一样的缓冲区,必须要分包发送,这样字节数据的分割有讲究,最少效率不能拖后腿,影响全局传输速度

3、对于一个大的数据来说,分割成小的数据包后,对于服务器或者客户端来说都是零散的数据,并不知道当前传来的包是干嘛的,这时候每个数据包里应该都设计好数据协议,用来保证每个包正确的完成他的功能

 

首先解决第一个问题

缓冲区大小的设定,在我的程序里我是根据TCP协议(毕竟我的通信协议是TCP)的数据包大小来设定的,虽然不知道这样会不会对传输速度有实质性的改变,但总比猜出一个数字来要好一点,TCP数据包的最大容量是1492 - IP(20) - TCP(20) = 1452(BYTES),我的代码里减掉两个字节当做后面提到的协议位,剩下1450B来当数据位,这样程序的头就出来了(当然我这里直接封装成类了)

[vb]  view plain  copy
 print ?
  1. Dim Sockets As Socket  
  2. '用来存储要发送的数据包的大小,不包含指令位,TCP协议数据包的Data区域大小为1452  
  3. Dim _DataLength As Integer = 1450  
  4.   
  5. '--------------------------------协议--------------------------------  
  6. '所有数据按照DataLength的长度来分割,第一位和第二位为指令位  
  7. '第一位表明这个包的状态,具体说明在PackageState枚举内  
  8. '第二位表明这个包作用,具体说明在PackageAction枚举内  
  9. '--------------------------------------------------------------------  
  10.   
  11. ''' <summary>  
  12. ''' 构造函数  
  13. ''' </summary>  
  14. ''' <param name="S">传入一个Socket对象,用来接受和发送数据</param>  
  15. ''' <remarks></remarks>  
  16. Public Sub New(ByVal S As Socket)  
  17.     Sockets = S  
  18. End Sub  
  19.   
  20. ''' <summary>  
  21. ''' 构造函数  
  22. ''' </summary>  
  23. ''' <remarks></remarks>  
  24. Public Sub New()  
  25.   
  26. End Sub  

 

之后再来解决第二个问题,关于字节数据的分割,看上面的代码我们知道每个包已经定为1450B,也就是说当传入一个数据时,要根据这个数为单位分割成多个小数据包(比如10M的文件,就会分成7232个包,最后一个包肯定不是满的),这里直接上代码,原本以为用For还是会影响效率,但运行起来还是挺不错的,For循环里用Array类去操作字节数组保证了效率

[vb]  view plain  copy
 print ?
  1. ''' <summary>  
  2. ''' 分割字节数组,将一个长的字节数组分成指定元素长度的数组集合  
  3. ''' </summary>  
  4. ''' <param name="data">源字节数组</param>  
  5. ''' <returns></returns>  
  6. ''' <remarks></remarks>  
  7. Public Function SplitByteArray(ByVal data As Byte()) As List(Of Byte())  
  8.     Dim list As New List(Of Byte())  
  9.     For i = 0 To data.Length - 1 Step _DataLength  
  10.         Dim tmp() As Byte  
  11.         If data.Length - i < _DataLength Then  
  12.             ReDim tmp(data.Length - i - 1)  
  13.             Array.ConstrainedCopy(data, i, tmp, 0, data.Length - i)  
  14.         Else  
  15.             ReDim tmp(_DataLength - 1)  
  16.             Array.ConstrainedCopy(data, i, tmp, 0, _DataLength)  
  17.         End If  
  18.         list.Add(tmp)  
  19.     Next  
  20.     Return list  
  21. End Function  

 

最后就要解决最难的一个问题了,协议

在我的这个类里,我把协议分成两个字节放在了数据包的前两位,第一位表明这个包的状态,具体说明在PackageState枚举内,第二位表明这个包作用,具体说明在PackageAction枚举内,然后我就直接上枚举,这个枚举可以根据具体使用情况来定制

[vb]  view plain  copy
 print ?
  1. ''' <summary>  
  2. ''' 枚举此数据包的用途  
  3. ''' </summary>  
  4. ''' <remarks></remarks>  
  5. Enum PackageAction  
  6.     下载 = CByte(1)  
  7.     获取所有项目 = CByte(2)  
  8.     获取指定项目 = CByte(3)  
  9.     废包 = CByte(4)  
  10. End Enum  
  11.   
  12. ''' <summary>  
  13. ''' 枚举此数据包的状态  
  14. ''' </summary>  
  15. ''' <remarks></remarks>  
  16. Enum PackageState  
  17.     后续还有包 = CByte(1)  
  18.     后续没有包 = CByte(2)  
  19.     请求下一个包 = CByte(3)  
  20.     心跳包 = CByte(4)  
  21. End Enum  


好了,基本到这里的话Socket分包的核心问题都已经解决了,接下来就是该怎么发怎么收了,这个类的完整代码在下一篇文章发出

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
VB.NET是一种流行的编程语言,它可以通过使用Socket类来实现字符串发送和接收程序。首先,我们需要创建一个Socket对象,并指定要连接的主机和端口号。然后,我们可以使用该Socket对象的Send方法来发送字符串数据,并使用Receive方法来接收字符串数据。 在发送字符串时,我们首先需要将要发送的字符串转换为字节数组,然后再通过Send方法发送。在接收字符串时,我们需要先创建一个足够大的缓冲区来存储接收到的数据,然后通过Receive方法将接收到的字节数组转换为字符串。 接下来是一个简单的示例代码,展示了如何在VB.NET中使用Socket类来实现字符串发送和接收程序: ```vb.net Imports System.Net.Sockets Imports System.Text Module Program Sub Main() Dim clientSocket As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) ' Connect to the server clientSocket.Connect("127.0.0.1", 8888) ' Send data to the server Dim data As Byte() = Encoding.ASCII.GetBytes("Hello server!") clientSocket.Send(data) ' Receive data from the server Dim buffer As Byte() = New Byte(1024) {} Dim bytesReceived As Integer = clientSocket.Receive(buffer) Dim responseData As String = Encoding.ASCII.GetString(buffer, 0, bytesReceived) Console.WriteLine("Received from server: " & responseData) ' Close the socket clientSocket.Close() End Sub End Module ``` 在这个示例中,我们首先创建了一个Socket对象clientSocket,并连接到了本地主机的8888端口。然后,我们使用Send方法发送了一个字符串"Hello server!"到服务器端,并通过Receive方法接收了服务器返回的数据。最后,我们关闭了Socket对象。 这就是如何使用VB.NET中的Socket类来实现简单的字符串发送和接收程序。通过这种方式,我们可以轻松地实现网络通信,并在应用程序之间传递数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值