基于.Net3.5编写,全异步操作。支持TCP、UDP两种方式,全事件模式通知。

' **********************************************************************
'
                适用于 .Net3.5版本
'
**********************************************************************


Imports  System.Net.Sockets
Imports  System.Net
Imports  System.Collections.Generic
Imports  System.Linq

Public   Class Socket35

#Region "自定义Socket结构体"
    
Public Class MySocket
        
Private MyWorkSocket As Socket
        
Private MyWorkID As Int32
        
Private MyWorkName As String

        
''' <summary>
        ''' 设置工作Socket
        ''' </summary>
        ''' <value>Scoket对象</value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property WorkSocket() As Socket
            
Get
                
Return MyWorkSocket
            
End Get
            
Set(ByVal value As Socket)
                MyWorkSocket 
= value
            
End Set
        
End Property


        
''' <summary>
        ''' Socket工作ID
        ''' </summary>
        ''' <value>Integer值</value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property WorkID() As Int32
            
Get
                
Return MyWorkID
            
End Get
            
Set(ByVal value As Int32)
                MyWorkID 
= value
            
End Set
        
End Property


        
''' <summary>
        ''' Socket工作名称
        ''' </summary>
        ''' <value>String值</value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property WorkName() As String
            
Get
                
Return MyWorkName
            
End Get
            
Set(ByVal value As String)
                MyWorkName 
= value
            
End Set
        
End Property

    
End Class

#End Region


#Region "Socket协义类型"
    
Public Enum SocketType
        TCP
        UDP
    
End Enum

#End Region


    
Private SocketID As Int32
    
Private Server As Socket
    
Private ServerHas As New HashSet(Of MySocket)
    
Private MyReceiveBuff(), MySendBuff() As Byte
    
Public Delegate Sub EventHandler(ByRef Sender As MySocket, ByVal e As SocketAsyncEventArgs)

    
'-------------------------------------------------------------------------------------------------------------

    
Public Event OnAccept As EventHandler '客户端连接事件
    Public Event OnReceive As EventHandler '客户端传入数据事件
    Public Event OnDisconnected As EventHandler  '客户端断开事件
    Public Event OnSent As EventHandler  '数据发送完毕


    
'**********************************************************************
    '      Socket对象定义、接收数据、发送数据、外部事件引发
    '**********************************************************************

#Region "构造函数"
    
''' <summary>
    ''' 初始化Socket35
    ''' </summary>
    ''' <param name="ProtocolType">协议类型</param>
    ''' <remarks></remarks>
    Sub New(ByVal ProtocolType As SocketType)
        
'复位SocketID值
        SocketID = 1

        
Select Case ProtocolType
            
Case SocketType.TCP
                Server 
= New Socket(AddressFamily.InterNetwork, Sockets.SocketType.Stream, Sockets.ProtocolType.Tcp)
            
Case SocketType.UDP
                Server 
= New Socket(AddressFamily.InterNetwork, Sockets.SocketType.Dgram, Sockets.ProtocolType.Udp)
        
End Select
    
End Sub


    
''' <summary>
    ''' 初始化Socket35
    ''' </summary>
    ''' <param name="ProtocolType">协议类型</param>
    ''' <param name="ReceiveBuffLength">接收缓冲区长度</param>
    ''' <param name="SendBuffLength">发送缓冲区长度</param>
    ''' <remarks></remarks>
    Sub New(ByVal ProtocolType As SocketType, ByVal ReceiveBuffLength As Int32, ByVal SendBuffLength As Int32)
        
'复位SocketID值
        SocketID = 1

        
If ReceiveBuffLength < 1 OrElse SendBuffLength < 1 Then
            
Throw New Exception("缓冲区大小必须大于0"New OverflowException)
            
Exit Sub
        
End If

        
Select Case ProtocolType
            
Case SocketType.TCP
                Server 
= New Socket(AddressFamily.InterNetwork, Sockets.SocketType.Stream, Sockets.ProtocolType.Tcp)
            
Case SocketType.UDP
                Server 
= New Socket(AddressFamily.InterNetwork, Sockets.SocketType.Dgram, Sockets.ProtocolType.Udp)
        
End Select

        ReceiveBuff 
= ReceiveBuffLength
        SendBuff 
= SendBuffLength
    
End Sub

#End Region


#Region "连接服务器"
    
''' <summary>
    ''' 连接到服务器端
    ''' </summary>
    ''' <param name="Ip">IP地址</param>
    ''' <param name="Port">端口</param>
    ''' <returns>MySocket对象</returns>
    ''' <remarks></remarks>
    Public Function Connect(ByVal Ip As StringByVal Port As Int32) As MySocket
        
Dim MS As New MySocket

        
'复位SocketID值
        SocketID = 1

        Server.Connect(Ip, Port)
        MS.WorkID 
= SocketID
        MS.WorkSocket 
= Server
        ServerHas.Add(MS)

        
Return MS
    
End Function


    
''' <summary>
    ''' 连接到服务器端
    ''' </summary>
    ''' <param name="RemotoEndPoint">远程服务器节点</param>
    ''' <returns>MySocket对象</returns>
    ''' <remarks></remarks>
    Public Function Connect(ByVal RemotoEndPoint As IPEndPoint) As MySocket
        
Dim MS As New MySocket

        
'复位SocketID值
        SocketID = 1

        Server.Connect(RemotoEndPoint)
        MS.WorkID 
= SocketID
        MS.WorkSocket 
= Server
        ServerHas.Add(MS)

        
Return MS
    
End Function

#End Region


#Region "接收缓冲区大小"
    
''' <summary>
    ''' 读取或设置接收缓冲区大小
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property ReceiveBuff() As Int32
        
Get
            
Return MyReceiveBuff.Length
        
End Get
        
Set(ByVal value As Int32)
            
ReDim MyReceiveBuff(value)
        
End Set
    
End Property

#End Region


#Region "发送缓冲区大小"
    
''' <summary>
    ''' 读取或设置发送缓冲区大小
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property SendBuff() As Int32
        
Get
            
Return MySendBuff.Length
        
End Get
        
Set(ByVal value As Int32)
            
ReDim MySendBuff(value)
        
End Set
    
End Property

#End Region


#Region "绑定地址和端口"
    
''' <summary>
    ''' 绑定地址和端口
    ''' </summary>
    ''' <param name="Ip">Ip地址</param>
    ''' <param name="Port">端口</param>
    ''' <remarks></remarks>
    Public Overloads Sub Bind(ByVal Ip As StringByVal Port As Int32)

        Server.Bind(
New IPEndPoint(IPAddress.Parse(Ip), Port))
    
End Sub


    
''' <summary>
    ''' 绑定地址和端口
    ''' </summary>
    ''' <param name="IpEndPoint">Ip地址和端口的节点</param>
    ''' <remarks></remarks>
    Public Overloads Sub Bind(ByVal IpEndPoint As IPEndPoint)

        Server.Bind(IpEndPoint)
    
End Sub

#End Region


#Region "侦听数"
    
''' <summary>
    ''' 设置侦听数
    ''' </summary>
    ''' <param name="val">侦听数</param>
    ''' <remarks></remarks>
    Public Sub Listen(ByVal val As Int32)
        Server.Listen(
val)
    
End Sub

#End Region


#Region "开始侦听"
    
''' <summary>
    ''' 开始侦听客户端连接
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub Start()
        
Select Case Server.ProtocolType
            
Case ProtocolType.Tcp
                StartForTcp()
            
Case ProtocolType.Udp
                StartForUdp()
        
End Select
    
End Sub


    
Private Sub StartForTcp()
        
Dim acc As New SocketAsyncEventArgs

        
AddHandler acc.Completed, AddressOf Accept_Completed
        Server.AcceptAsync(acc)
    
End Sub


    
Private Sub StartForUdp()
        
Dim acc As New SocketAsyncEventArgs

        
AddHandler acc.Completed, AddressOf UDP_Receive_Completed
        acc.RemoteEndPoint 
= Server.LocalEndPoint
        acc.SetBuffer(MyReceiveBuff, 
0, MyReceiveBuff.Length)
        Server.ReceiveFromAsync(acc)
    
End Sub

#End Region


#Region "客户端连接"
    
Private Sub Accept_Completed(ByVal Sender As ObjectByVal e As SocketAsyncEventArgs)
        
'事件进入
        Dim MS As New MySocket
        
Dim Client As Socket

        Client 
= e.AcceptSocket
        MS.WorkID 
= SocketID
        MS.WorkSocket 
= Client

        
RaiseEvent OnAccept(MS, e)

        
If IsNothing(Client) OrElse Not Client.Connected Then
            
If Not IsNothing(ServerHas) Then
                ServerHas.Remove(MS)
            
End If

            
Exit Sub
        
Else
            ServerHas.Add(MS)
        
End If

        
'接收数据
        RemoveHandler e.Completed, AddressOf Accept_Completed
        
AddHandler e.Completed, AddressOf TCP_Receive_Completed
        e.SetBuffer(MyReceiveBuff, 
0, MyReceiveBuff.Length)
        Client.ReceiveAsync(e)
        SocketID 
+= 1
        Start()
    
End Sub

#End Region


#Region "客户端传入数据(TCP)"
    
Private Sub TCP_Receive_Completed(ByVal Sender As ObjectByVal e As SocketAsyncEventArgs)
        
Dim MS As MySocket
        
Dim Client As Socket

        Client 
= Sender
        MS 
= GetMySocketBySocket(Client)

        
If e.BytesTransferred = 0 Then
            
On Error Resume Next

            ServerHas.Remove(MS)
            
'引发客户端断开事件
            RaiseEvent OnDisconnected(MS, e)
            
'执行断开操作
            Client.Close()
            Client 
= Nothing
            
Exit Sub
        
End If

        
'事件进入
        RaiseEvent OnReceive(MS, e)

        
If IsNothing(Client) OrElse Client.Connected = False Then
            
If Not IsNothing(ServerHas) Then
                ServerHas.Remove(MS)
            
End If

            
Exit Sub
        
End If

        
'清理缓冲数据
        Array.Clear(e.Buffer, 0, e.Buffer.Length)

        
'接收数据
        Client.ReceiveAsync(e)
    
End Sub

#End Region


#Region "客户端传入数据(UDP)"
    
Public Sub UDP_Receive_Completed(ByVal Sender As ObjectByVal e As SocketAsyncEventArgs)
        
Dim MS As New MySocket
        
Dim Client As Socket

        Client 
= Sender
        MS.WorkSocket 
= Client

        
'事件进入
        RaiseEvent OnReceive(MS, e)

        
If IsNothing(Client) OrElse Client.Connected = False Then
            
If Not IsNothing(ServerHas) Then
                ServerHas.Remove(MS)
            
End If

            
Exit Sub
        
End If

        
'清理缓冲数据
        Array.Clear(e.Buffer, 0, e.Buffer.Length)

        
'接收数据
        Client.ReceiveFromAsync(e)
    
End Sub

#End Region


#Region "发送数据"
    
''' <summary>
    ''' 发送Socket数据
    ''' </summary>
    ''' <param name="SocketID">Socket ID值</param>
    ''' <param name="DataBuff">Byte数组</param>
    ''' <returns>True:发送成功 False:发送失败</returns>
    ''' <remarks></remarks>
    Public Overloads Function Send(ByVal SocketID As Int32, ByVal DataBuff() As ByteAs Boolean
        
Dim MS As MySocket
        
Dim SD As New SocketAsyncEventArgs

        MS 
= GetMySocketByID(SocketID)

        
If IsNothing(MS) OrElse IsNothing(MS.WorkSocket) OrElse MS.WorkSocket.Connected = False Then
            
Return False
        
End If

        SD.SetBuffer(DataBuff, 
0, DataBuff.Length)
        SD.UserToken 
= MS.WorkSocket
        
AddHandler SD.Completed, AddressOf Send_Completed
        MS.WorkSocket.SendAsync(SD)

        
'进入接收数据异步
        Call ReceiveAfterSent(MS.WorkSocket)

        
Return True
    
End Function


    
''' <summary>
    ''' 发送Socket数据
    ''' </summary>
    ''' <param name="SocketName">Socket 名称</param>
    ''' <param name="DataBuff">Byte数组</param>
    ''' <returns>True:发送成功 False:发送失败</returns>
    ''' <remarks></remarks>
    Public Overloads Function Send(ByVal SocketName As StringByVal DataBuff() As ByteAs Boolean
        
Dim MS As MySocket
        
Dim SD As New SocketAsyncEventArgs

        MS 
= GetMySocketByName(SocketName)

        
If IsNothing(MS) OrElse IsNothing(MS.WorkSocket) OrElse MS.WorkSocket.Connected = False Then
            
Return False
        
End If

        SD.SetBuffer(DataBuff, 
0, DataBuff.Length)
        SD.UserToken 
= MS.WorkSocket
        
AddHandler SD.Completed, AddressOf Send_Completed
        MS.WorkSocket.SendAsync(SD)

        
'进入接收数据异步
        Call ReceiveAfterSent(MS.WorkSocket)

        
Return True
    
End Function


    
''' <summary>
    ''' 发送Socket数据
    ''' </summary>
    ''' <param name="Socket">Socket名称</param>
    ''' <param name="DataBuff">Byte数组</param>
    ''' <returns>True:发送成功 False:发送失败</returns>
    ''' <remarks></remarks>
    Public Overloads Function Send(ByVal Socket As Socket, ByVal DataBuff() As ByteAs Boolean
        
Dim SD As New SocketAsyncEventArgs

        
If IsNothing(Socket) OrElse Socket.Connected = False Then
            
Return False
        
End If

        SD.SetBuffer(DataBuff, 
0, DataBuff.Length)
        SD.UserToken 
= Socket
        
AddHandler SD.Completed, AddressOf Send_Completed
        Socket.SendAsync(SD)

        
'进入接收数据异步
        Call ReceiveAfterSent(Socket)

        
Return True
    
End Function


    
Private Sub Send_Completed(ByVal Sender As Socket, ByVal e As SocketAsyncEventArgs)
        
'异步发送完成操作
        Dim MS As MySocket

        MS 
= GetMySocketBySocket(Sender)
        
RaiseEvent OnSent(MS, e)

        
If IsNothing(Sender) OrElse Sender.Connected = False Then
            
If Not IsNothing(ServerHas) Then
                ServerHas.Remove(MS)
            
End If
        
End If
    
End Sub


    
Private Sub ReceiveAfterSent(ByVal Socket As Socket)
        
'发送数据后开始接收
        Dim SA As New SocketAsyncEventArgs

        SA.SetBuffer(MyReceiveBuff, 
0, MyReceiveBuff.Length)

        
Select Case Server.ProtocolType
            
Case ProtocolType.Tcp
                
'TCP接收
                AddHandler SA.Completed, AddressOf TCP_Receive_Completed
                Socket.ReceiveAsync(SA)
            
Case ProtocolType.Udp
                
'UDP接收
                AddHandler SA.Completed, AddressOf UDP_Receive_Completed
                SA.RemoteEndPoint 
= Socket.LocalEndPoint
                Socket.ReceiveFromAsync(SA)
        
End Select
    
End Sub

#End Region


#Region "得到ServerHas数据信息"
    
''' <summary>
    ''' 得到当前Socket列表
    ''' </summary>
    ''' <returns>String(,1)一维数组。0:Socket的ID 1:Socket的名称</returns>
    ''' <remarks></remarks>
    Public Function GetServerList() As String(,)
        
If IsNothing(ServerHas) Then
            
Throw New Exception("未初始化本类")
            
Exit Function
        
End If

        
Dim Result(,) As String
        
Dim Count As Int32
        
Dim i As Int32

        i 
= 0
        Count 
= ServerHas.Count
        
ReDim Result(Count - 11)

        
Dim Data = From s In ServerHas _
                     
Select s.WorkID, s.WorkName

        
For Each item In Data
            Result(i, 
0= item.WorkID.ToString
            Result(i, 
1= item.WorkName
            i 
+= 1
        
Next

        
Return Result
    
End Function

#End Region


#Region "清除Socket对象"
    
''' <summary>
    ''' 清除Socket对象
    ''' </summary>
    ''' <param name="SocketID">Socket的ID值</param>
    ''' <remarks></remarks>
    Public Sub Close(ByVal SocketID As Int32)
        
On Error Resume Next

        
Dim CS As MySocket

        CS 
= GetMySocketByID(SocketID)
        CS.WorkSocket.Close()
        CS.WorkSocket 
= Nothing
        CS 
= Nothing
        ServerHas.Remove(CS)
    
End Sub


    
''' <summary>
    ''' 清除Socket对象
    ''' </summary>
    ''' <param name="SocketName">Socket的名称</param>
    ''' <remarks></remarks>
    Public Sub Close(ByVal SocketName As String)
        
On Error Resume Next

        
Dim CS As MySocket

        CS 
= GetMySocketByName(SocketName)
        CS.WorkSocket.Close()
        CS.WorkSocket 
= Nothing
        CS 
= Nothing
        ServerHas.Remove(CS)
    
End Sub


    
''' <summary>
    ''' 清除Socket对象
    ''' </summary>
    ''' <param name="Socket">Socket对象</param>
    ''' <remarks></remarks>
    Public Sub Close(ByVal Socket As Socket)
        
On Error Resume Next

        
Dim CS As MySocket

        CS 
= GetMySocketBySocket(Socket)
        Socket.Close()
        Socket 
= Nothing
        CS 
= Nothing
        ServerHas.Remove(CS)
    
End Sub


    
''' <summary>
    ''' 清除Socket对象
    ''' </summary>
    ''' <param name="MySocket">MySocket对象</param>
    ''' <remarks></remarks>
    Public Sub Close(ByVal MySocket As MySocket)
        
On Error Resume Next

        MySocket.WorkSocket.Close()
        MySocket.WorkSocket 
= Nothing
        ServerHas.Remove(MySocket)
    
End Sub

#End Region


    
'**********************************************************************
    '                LinQ 查询 MySocket结构体
    '**********************************************************************

#Region "得到MySocket对象"
    
''' <summary>
    ''' 以Socket的ID值得到MySocket对象
    ''' </summary>
    ''' <param name="ID">SocketID值</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetMySocketByID(ByVal ID As Int32) As MySocket

        
If IsNothing(ServerHas) Then
            
Return Nothing
        
End If

        
Dim Result = From s In ServerHas _
                     Where s.WorkID 
= ID

        
If Result.Count = 0 Then
            
Return Nothing
        
End If

        
Return Result.First
    
End Function


    
''' <summary>
    ''' 以Socket的名称值得到MySocket对象
    ''' </summary>
    ''' <param name="Name"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetMySocketByName(ByVal Name As StringAs MySocket

        
If IsNothing(ServerHas) Then
            
Return Nothing
        
End If

        
Dim Result = From s In ServerHas _
                     Where s.WorkName 
= Name

        
If Result.Count = 0 Then
            
Return Nothing
        
End If

        
Return Result.First
    
End Function


    
''' <summary>
    ''' 以Socket对象得到MySocket对象
    ''' </summary>
    ''' <param name="Socket">Socket对象</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetMySocketBySocket(ByVal Socket As Socket) As MySocket
        
Dim SocketHandle As Int32

        SocketHandle 
= Socket.Handle

        
If IsNothing(Socket) OrElse IsNothing(ServerHas) Then
            
Return Nothing
        
End If

        
Dim Result = From s In ServerHas _
                            Where s.WorkSocket.Handle 
= SocketHandle

        
If Result.Count = 0 Then
            
Return Nothing
        
End If

        
Return Result.First
    
End Function

#End Region


#Region "释放对象"
    
Public Sub Dispose()
        
On Error Resume Next

        Server.Close()
        Server 
= Nothing

        
For Each item In ServerHas
            item.WorkSocket.LingerState.Enabled 
= False
            item.WorkSocket.Shutdown(SocketShutdown.Both)
            item.WorkSocket.Close()
            item.WorkSocket 
= Nothing
        
Next

        ServerHas.Clear()
        ServerHas 
= Nothing
    
End Sub

#End Region


End Class




 

调用示例:

TCP:

 

Dim  Server  As  Socket35
Server 
=   New  Socket35(Socket35.SocketType.TCP,  1024 1024 )
Server.Bind(
New  IPEndPoint(IPAddress.Any,  5614 ))
Server.Listen(
100 )

' Socket事件
AddHandler  server.OnAccept,  AddressOf  accept
AddHandler  server.OnReceive,  AddressOf  received
AddHandler  server.OnSent,  AddressOf  sent
AddHandler  server.OnDisconnected,  AddressOf  disconnect

' 开始监听
Server.Start()

' Socket连接进入
Private   Sub accept(ByRef Sender As Socket35.MySocket, ByVal e As SocketAsyncEventArgs)
    
    Sender.WorkName 
= Now.ToString
    Debug.Write(Sender.WorkID)

End Sub



' Socket接收入数
Private   Sub received(ByRef Sender As Socket35.MySocket, ByVal e As SocketAsyncEventArgs)

    
Dim Content As String
    
Dim SendBuff() As Byte

    Content 
= System.Text.Encoding.GetEncoding("gb2312").GetString(e.Buffer)
    server.Send(Sender.WorkSocket, SendBuff)

End Sub


' 查看当前Socket活动连接信息(二维数组)
Dim  SocketList(,)  As   String
SocketList 
=  Socket35.GetServerList()

 

UDP:

 

Dim  Server  As  Socket35
Server 
=   New  Socket35(Socket35.SocketType.UDP,  1024 1024 )
Server.Bind(
New  IPEndPoint(IPAddress.Any,  5614 ))

AddHandler  server.OnAccept,  AddressOf  accept
AddHandler  server.OnReceive,  AddressOf  received
AddHandler  server.OnSent,  AddressOf  sent
AddHandler  server.OnDisconnected,  AddressOf  disconnect
Server.Start()

' 接收UDP传来的数据
Private   Sub received(ByRef Sender As Socket35.MySocket, ByVal e As SocketAsyncEventArgs)

    
Dim Content As String
    
Dim SendBuff() As Byte

    Content 
= System.Text.Encoding.GetEncoding("gb2312").GetString(e.Buffer)

    Server.Send(Sender.WorkSocket, SendBuff)

End Sub
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值