总结一下.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个字节。

 

 

  1 Imports System
  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 IntegerByVal 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 ByteImplements 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 StringAs 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 StringAs 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 ByteByVal offset As LongByVal count As LongAs 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 ByteAs 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 ObjectAs 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 ByteByVal index As IntegerAs 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 

 

 

 

 

posted @ 2010-05-30 11:49  soleds  阅读(1363)  评论(0)    收藏  举报