Socket35.vb
' 適用於 .Net3.5版本
'**********************************************************************
Imports System.Net.Sockets
Imports System.Net
Imports System.Collections.Generic
Imports System.Linq
Public Class Socket35Class Socket35
自定義Socket結構體#Region "自定義Socket結構體"
Public Class MySocketClass 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()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()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()Property WorkName() As String
Get
Return MyWorkName
End Get
Set(ByVal value As String)
MyWorkName = value
End Set
End Property
End Class
#End Region
Socket協義類型#Region "Socket協義類型"
Public Enum SocketTypeEnum 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()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()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()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()Function Connect(ByVal Ip As String, ByVal 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()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()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()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()Sub Bind(ByVal Ip As String, ByVal 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()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()Sub Listen(ByVal val As Int32)
Server.Listen(val)
End Sub
#End Region
開始偵聽#Region "開始偵聽"
''' <summary>
''' 開始偵聽客戶端連接
''' </summary>
''' <remarks></remarks>
Public Sub Start()Sub Start()
Select Case Server.ProtocolType
Case ProtocolType.Tcp
StartForTcp()
Case ProtocolType.Udp
StartForUdp()
End Select
End Sub
Private Sub StartForTcp()Sub StartForTcp()
Dim acc As New SocketAsyncEventArgs
AddHandler acc.Completed, AddressOf Accept_Completed
Server.AcceptAsync(acc)
End Sub
Private Sub StartForUdp()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()Sub Accept_Completed(ByVal Sender As Object, ByVal 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
客戶端傳入數據(TCP)#Region "客戶端傳入數據(TCP)"
Private Sub TCP_Receive_Completed()Sub TCP_Receive_Completed(ByVal Sender As Object, ByVal 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
客戶端傳入數據(UDP)#Region "客戶端傳入數據(UDP)"
Public Sub UDP_Receive_Completed()Sub UDP_Receive_Completed(ByVal Sender As Object, ByVal 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()Function Send(ByVal SocketID As Int32, ByVal DataBuff() As Byte) As 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()Function Send(ByVal SocketName As String, ByVal DataBuff() As Byte) As 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()Function Send(ByVal Socket As Socket, ByVal DataBuff() As Byte) As 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()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()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
得到ServerHas數據信息#Region "得到ServerHas數據信息"
''' <summary>
''' 得到當前Socket列表
''' </summary>
''' <returns>String(,1)一維數組。0:Socket的ID 1:Socket的名稱</returns>
''' <remarks></remarks>
Public Function GetServerList()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 - 1, 1)
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
清除Socket對象#Region "清除Socket對象"
''' <summary>
''' 清除Socket對象
''' </summary>
''' <param name="SocketID">Socket的ID值</param>
''' <remarks></remarks>
Public Sub Close()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()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()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()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結構體
'**********************************************************************
得到MySocket對象#Region "得到MySocket對象"
''' <summary>
''' 以Socket的ID值得到MySocket對象
''' </summary>
''' <param name="ID">SocketID值</param>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetMySocketByID()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()Function GetMySocketByName(ByVal Name As String) As 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()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()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:
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()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()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:
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()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
轉自http://blog.csdn.net/gxboy/archive/2008/05/06/2398876.aspx