总结一下.NEt Socket UDP异步通讯心得
1:发送字节数组
Private Sub SendInternal(ByVal buffer() As Byte, ByVal remoteIP As IPEndPoint)
If _started = False Then
Throw New Exception("UDP Closed.")
End If
Try
UdpClient.BeginSend(buffer, buffer.Length, remoteIP, New AsyncCallback(AddressOf SendCallback), remoteIP)
Catch ex As Exception
End Try
End Sub
2:发送回调
Private Sub SendCallback(ByVal result As IAsyncResult)
Try
UdpClient.EndSend(result)
Dim IPE As IPEndPoint = CType(result.AsyncState, IPEndPoint)
RaiseEvent OnSendSuccess(IPE)
Catch ex As Exception
Throw ex
End Try
End Sub
3:接收
Private Sub ReceiveInternal()
If _started = False Then Return
Try
UdpClient.BeginReceive(New AsyncCallback(AddressOf OnRecvive), Nothing)
Catch ex As Exception
Throw ex
End Try
End Sub
4:接收回调
Private Sub OnRecvive(ByVal result As IAsyncResult)
RaiseEvent dllLog("收到包,现在尝试解包!")
If _started = False Then Return
Dim remoteIP As New IPEndPoint(IPAddress.Any, 0)
Dim buffer() As Byte = Nothing
Try
buffer = UdpClient.EndReceive(result, remoteIP)
Catch ex As Exception
Throw ex
Finally
ReceiveInternal()
End Try
If Not _SecurityClient.ContainsKey(remoteIP.Address.ToString + ":" + remoteIP.Port.ToString) Then
'用户未受信任。不处理任何消息。直接返回消息给调用者处理。
RaiseEvent OnRecviveData(buffer, remoteIP, False)
Exit Sub
End If
'尝试对收到的数据包做解析
Dim cell As New SendCell
cell.FromBuffer(buffer)
Select Case cell.MessageID
Case Commands.RequestSendFile '对方要向我发送文件
RaiseEvent dllLog("收到消息:RequestSendFile")
RaiseEvent OnRequestSendFile(CType(cell.Data, FransfersFileStart), remoteIP)
Case Commands.ResponseSendFile '对方回应了我发送文件的请求
RaiseEvent dllLog("收到消息:ResponseSendFile")
Dim fs As FransfersFileStart = CType(cell.Data, FransfersFileStart)
RaiseEvent OnResponseSendFile(fs, remoteIP)
If fs.RequestSendFileStatus = True Then
'对方同意接收我的文件。这里开始发送文件,以及将文件加到发送列表
Dim sf As New SendFileManager(fs.FileName, fs.PartSize, remoteIP)
Dim key As String = sf.Md5 + sf.remoteIP.Address.ToString + sf.remoteIP.Port.ToString
AddHandler sf.ReadFileBufferEvent, AddressOf ReadFileBufferEvent
_SendFileManagerList.Add(key, sf)
RaiseEvent dllLog("对方同意接收文件,发送列表key:" + key)
'回发一个通知。
Dim ce As New SendCell(Commands.ResponseSendFile2, fs)
Send(ce, remoteIP)
Else
'对方拒收
RaiseEvent dllLog("对方拒收我要发送的文件!" + fs.FileName)
End If
Case Commands.RequestSendFilePack '对方请求我发送某个文件片段
'读取文件片段
Dim sp As SendFilePack = CType(cell.Data, SendFilePack)
RaiseEvent dllLog("收到消息:RequestSendFilePack 索引:" + sp.Index.ToString)
Dim key As String = sp.Md5 + remoteIP.Address.ToString + remoteIP.Port.ToString
If _SendFileManagerList.ContainsKey(key) Then
_SendFileManagerList(key).Read(sp.Index)
Else
RaiseEvent dllLog("找不到该key:" + key)
End If
Case Commands.ResponseSendFilePack '对方回应了我发送某个文件片段的请求
Dim sp As SendFilePack = CType(cell.Data, SendFilePack)
RaiseEvent dllLog("收到消息:ResponseSendFilePack 收到的索引:" + sp.Index.ToString)
Dim key As String = sp.Md5 + remoteIP.Address.ToString + remoteIP.Port.ToString
If _RecviveFileManagerList.ContainsKey(key) Then
_RecviveFileManagerList(key).ReceiveBuffer(sp.Index, sp.Buffer)
Else
RaiseEvent dllLog("未找到此索引!" + key)
End If
Case Commands.FileRecviveSuccess
'接收方通知我文件接收成功
Dim Md5 As String = CType(cell.Data, String)
'移除掉该文件
Dim key As String = Md5 + remoteIP.Address.ToString + remoteIP.Port.ToString
If _SendFileManagerList.ContainsKey(key) Then
RaiseEvent OnFileSendSuccess(_SendFileManagerList(key), remoteIP)
_SendFileManagerList(key).Dispose()
_SendFileManagerList.Remove(key)
End If
Case Commands.ResponseSendFile2 '对方通知我可以开始读取文件包
Dim fs As FransfersFileStart = CType(cell.Data, FransfersFileStart)
RaiseEvent dllLog("对方通知我开始接收文件" + New FileInfo(fs.FileName).Name)
_RecviveFileManagerList(fs.MD5 + remoteIP.Address.ToString + remoteIP.Port.ToString).Start()
Case Else '无法解析此消息,抛出消息给外部解析
RaiseEvent OnRecviveData(buffer, remoteIP, True)
End Select
End Sub
commands是一个Enum类型的枚举列表,用于定义命令列表。命令列表的命令类型等同于Int类型。占用4个字节。
2 Imports System.Text
3 Imports System.IO
4 Imports System.Collections.Generic
5 Imports System.Security.Cryptography
6 Imports System.Runtime.Serialization.Formatters.Binary
7
8 ''' <summary>
9 ''' 数据接口
10 ''' </summary>
11 ''' <remarks></remarks>
12 Public Interface IDataCell
13
14 Function ToBuffer() As Byte()
15
16 Sub FromBuffer(ByVal buffer() As Byte)
17
18 End Interface
19
20 ''' <summary>
21 ''' 内部命令常量(系统碰到无法解析的外部常量将直接返回事件供外部处理)
22 ''' </summary>
23 ''' <remarks></remarks>
24 Public Enum Commands
25
26 RequestSendFile = &H101
27 ResponseSendFile = &H100001
28 ResponseSendFile2 = &H110001
29
30 RequestSendFilePack = &H102
31 ResponseSendFilePack = &H100002
32
33 FileRecviveSuccess = &H103
34
35 End Enum
36
37 ''' <summary>
38 ''' 保存接收到的数据解码及对要发送的数据编码的类
39 ''' </summary>
40 ''' <remarks></remarks>
41 Public Class SendCell
42 Implements IDataCell
43
44 Private _MessageID As Integer = 0
45 Private _data As Object
46
47 Property MessageID() As Integer
48 Get
49 Return _MessageID
50 End Get
51 Set(ByVal value As Integer)
52 _MessageID = value
53 End Set
54 End Property
55
56 Property Data() As Object
57 Get
58 Return _data
59 End Get
60 Set(ByVal value As Object)
61 _data = value
62 End Set
63 End Property
64
65 Public Sub New()
66
67 End Sub
68
69 Public Sub New(ByVal messageid As Integer, ByVal data As Object)
70 _MessageID = messageid
71 _data = data
72 End Sub
73
74 ''' <summary>
75 ''' 一个对像,对收到的UDP包做解析
76 ''' </summary>
77 ''' <param name="buffer"></param>
78 ''' <remarks></remarks>
79 Public Sub FromBuffer(ByVal buffer() As Byte) Implements IDataCell.FromBuffer
80 Try
81 _MessageID = BitConverter.ToInt32(buffer, 0)
82 _data = BufferHelper.DeSerialize(buffer, 4)
83 Catch ex As Exception
84 _MessageID = 0
85 End Try
86 End Sub
87
88 ''' <summary>
89 ''' 转换为要发送的数据包
90 ''' </summary>
91 ''' <returns></returns>
92 ''' <remarks></remarks>
93 Public Function ToBuffer() As Byte() Implements IDataCell.ToBuffer
94 Dim dt() As Byte = BufferHelper.Serialize(_data)
95 Dim id() As Byte = BitConverter.GetBytes(_MessageID)
96 Dim buffer(dt.Length + id.Length) As Byte
97 System.Buffer.BlockCopy(id, 0, buffer, 0, id.Length)
98 System.Buffer.BlockCopy(dt, 0, buffer, id.Length, dt.Length)
99 Return buffer
100 End Function
101 End Class
102
103 ''' <summary>
104 ''' MD5计算助手
105 ''' </summary>
106 ''' <remarks></remarks>
107 Public Class Md5helper
108
109 Private Shared md5 As New MD5CryptoServiceProvider
110
111 Public Shared Function CreateTxt(ByVal md5KeyString As String) As String
112 Return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(md5KeyString, "MD5")
113 End Function
114
115 ''' <summary>
116 ''' 根据文件名生成MD5校验码。请注意该文件必须存在,否则将会抛出错误。
117 ''' </summary>
118 ''' <param name="fileName"></param>
119 ''' <returns></returns>
120 ''' <remarks></remarks>
121 Public Shared Function Create(ByVal fileName As String) As String
122 Dim hashstr As String = String.Empty
123 Try
124 Dim fs As New FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
125 Dim hash() As Byte = md5.ComputeHash(fs)
126 hashstr = ByteArrayToHexString(hash)
127 fs.Close()
128 fs.Dispose()
129 Catch ex As Exception
130 Throw New Exception(ex.Message)
131 End Try
132 Return hashstr
133 End Function
134
135 ''' <summary>
136 ''' 根据要发送的文件流来生成MD5校验码。
137 ''' </summary>
138 ''' <param name="s"></param>
139 ''' <returns></returns>
140 ''' <remarks></remarks>
141 Public Shared Function Create(ByVal s As Stream) As String
142 While True
143 Try
144 Dim hash() As Byte = md5.ComputeHash(s)
145 Return ByteArrayToHexString(hash)
146 Catch ex As Exception
147
148 End Try
149 System.Threading.Thread.Sleep(10)
150 End While
151 Return ""
152 End Function
153
154 ''' <summary>
155 ''' 根据字节数组生成MD5校验码。
156 ''' </summary>
157 ''' <param name="buffer"></param>
158 ''' <param name="offset"></param>
159 ''' <param name="count"></param>
160 ''' <returns></returns>
161 ''' <remarks></remarks>
162 Public Shared Function Create(ByVal buffer() As Byte, ByVal offset As Long, ByVal count As Long) As String
163 Dim hash() As Byte = md5.ComputeHash(buffer, offset, count)
164 Return ByteArrayToHexString(hash)
165 End Function
166
167 Private Shared Function ByteArrayToHexString(ByVal values() As Byte) As String
168 Dim sb As New System.Text.StringBuilder
169 For Each value As Byte In values
170 sb.AppendFormat("{0:X2}", value)
171 Next
172 Return sb.ToString
173 End Function
174 End Class
175
176 ''' <summary>
177 ''' 对接收到或待发送数组做序列化与反序列化的类
178 ''' </summary>
179 ''' <remarks></remarks>
180 Public Class BufferHelper
181
182 ''' <summary>
183 ''' 对一个传入的对象序列化为数组
184 ''' </summary>
185 ''' <param name="obj"></param>
186 ''' <returns></returns>
187 ''' <remarks></remarks>
188 Public Shared Function Serialize(ByVal obj As Object) As Byte()
189 Dim bf As New BinaryFormatter
190 Dim ms As New MemoryStream
191 bf.Serialize(ms, obj)
192 Dim datas() As Byte = ms.ToArray()
193 ms.Dispose()
194 Return datas
195 End Function
196
197 ''' <summary>
198 ''' 将一个字节数组反序列化为一个对象
199 ''' </summary>
200 ''' <param name="data"></param>
201 ''' <param name="index"></param>
202 ''' <returns></returns>
203 ''' <remarks></remarks>
204 Public Shared Function DeSerialize(ByVal data() As Byte, ByVal index As Integer) As Object
205 Dim bf As New BinaryFormatter
206 Dim ms As New MemoryStream(data, index, data.Length - index)
207 Dim obj As Object = bf.Deserialize(ms)
208 ms.Dispose()
209 Return obj
210 End Function
211 End Class
212

浙公网安备 33010602011771号