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

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


Public
Class Socket35
Class 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



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()
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()
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()
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






































































































































































































































































































































































































































































































































































































































































































































































调用示例:
TCP:







































UDP:





















