Imports System.Net
Imports System.Net.Sockets
Imports System
Imports System.Threading
Imports System.IO
Public Class ChatServer
Implements IDisposable
#Region "自定义变量"
Private ReadOnly ServerIP As IPAddress
Private ReadOnly PortNum As Integer = 5000
Private ReadOnly ServerTag As String
Private SocketList As New ArrayList
Private MySocket As Socket = Nothing
Private listener As TcpListener
Private SocketStream As NetworkStream
Private Writer As BinaryWriter
Private Reader As BinaryReader
Private NewThread As Thread = Nothing
Private IsStarted As Boolean = False '服务器状态为未启动
Private ClientCount As Integer = 0
Const CMAXCOUNT = 30 '容许连接的最大客户端数目
Public Event OnText(ByVal N As Integer, ByVal msg As String)
Private Index As Integer
Public ClientRemoteEndPoint As String
#End Region
#Region "初始化服务器端口参数"
''' <summary>
''' 初始化服务器端口参数
''' </summary>
Sub New(ByVal SerIP As IPAddress, ByVal Port As Integer, ByVal SerTag As String)
ServerIP = SerIP
PortNum = Port
ServerTag = SerTag
End Sub
#End Region
#Region "属性区域"
''' <summary>
''' 服务器连接状态
''' </summary>
Public ReadOnly Property IsConnected() As Boolean
Get
Return IsStarted
End Get
End Property
#End Region
#Region "自定义过程"
''' <summary>
''' 创建服务器
''' </summary>
Public Sub Start()
Try
'创建一个侦听对象
listener = New TcpListener(ServerIP, PortNum)
'启动服务器侦听端口
listener.Start()
IsStarted = True
RaiseEvent OnText(3, "服务器已启动")
While True
'连接客户端,返回一个 套接字
If ClientCount <= CMAXCOUNT Then
MySocket = listener.AcceptSocket()
'添加到连接列表中
SocketList.Add(MySocket)
ClientRemoteEndPoint = MySocket.RemoteEndPoint.ToString()
RaiseEvent OnText(1, ClientRemoteEndPoint)
SocketStream = New NetworkStream(MySocket)
Writer = New BinaryWriter(SocketStream)
'通知客户端,连接成功
' Writer.Write("与服务器成功连接" & vbCrLf) '应该在什么时候断开该连接
Writer.Write("EB90")
Writer.Flush()
ClientCount += 1
Else
MySocket = listener.AcceptSocket()
SocketStream = New NetworkStream(MySocket)
Writer = New BinaryWriter(SocketStream)
'通知客户端,连接成功
Writer.Write("Server>> 服务器的连接数已满,连接已经断开")
' MySocket.Disconnect(False) '断开连接
MySocket.Close()
End If
End While
Catch ex As Exception
IsStarted = False
If listener IsNot Nothing Then listener.Stop()
listener = Nothing
RaiseEvent OnText(3, "服务器启动失败,请检查网络。")
' MsgBox(ex.ToString)
Finally
SocketStream = Nothing
Writer = Nothing
MySocket = Nothing
End Try
End Sub
''' <summary>
''' 该方法在每个实例中仅容许使用一次
''' </summary>
Public Sub Connect()
If Not IsStarted Then
Try
'创建新线程,用新的线程启动服务器
NewThread = New Thread(New ThreadStart(AddressOf Start))
NewThread.Name = "Thread for sever start"
NewThread.Start()
' Catch ex As ThreadStartException
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.OkOnly, "线程启动错误")
'线程创建失败时服务器启动失败
End Try
Else
MsgBox("该实例中已经有一个服务器进程在运行,若要创建新的服务器请使用其它实例", _
MsgBoxStyle.OkOnly, "警告")
End If
End Sub
''' <summary>
''' 断开一个连接
''' </summary>
Public Sub Disconnect(ByVal index As Integer)
Try
Dim con As Socket = SocketList(index)
If con IsNot Nothing Then
SocketList.RemoveAt(index)
ClientCount -= 1
RaiseEvent OnText(2, con.RemoteEndPoint.ToString)
RaiseEvent OnText(3, con.RemoteEndPoint.ToString & " - 连接断开")
con.Close()
End If
Catch ex As Exception
MsgBox("操作错误")
End Try
End Sub
''' <summary>
''' 服务器连接断开
''' </summary>
Public Sub Close()
Try
If MySocket IsNot Nothing Then MySocket.Close()
If listener IsNot Nothing Then listener.Stop()
Catch ex As Exception
End Try
End Sub
''' <summary>
''' 发消息给指定客户端
''' </summary>
Public Sub SendMsg(ByVal index As Integer, ByVal msg As String)
Dim Con As Socket
Dim SocketStream As NetworkStream
Dim SentMsg As BinaryWriter
Try
Con = SocketList(index)
SocketStream = New NetworkStream(Con)
SentMsg = New BinaryWriter(SocketStream)
SentMsg.Write(msg) '发送信息
RaiseEvent OnText(3, "发送数据成功")
Catch ex As IndexOutOfRangeException
RaiseEvent OnText(3, "发送数据失败")
MsgBox(ex.Message, MsgBoxStyle.OkOnly, "越界异常")
Finally
Con = Nothing
SocketStream = Nothing
SentMsg = Nothing
End Try
End Sub
''' <summary>
''' 发消息给所有客户端
''' </summary>
Public Sub SendMsg(Optional ByVal msg As String = "")
Dim Con As Socket
Dim SocketStream As NetworkStream
Dim SentMsg As BinaryWriter
Try
If SocketList.Count > 0 Then
For Index = 0 To SocketList.Count - 1
Try
Con = SocketList(Index)
If Con Is Nothing Then
Thread.Sleep(300)
Continue For
End If
SocketStream = New NetworkStream(Con)
SentMsg = New BinaryWriter(SocketStream)
SentMsg.Write(msg) '发送信息
Catch ex As IOException
SocketList.RemoveAt(Index)
ClientCount -= 1
If Con IsNot Nothing Then
RaiseEvent OnText(2, Con.RemoteEndPoint.ToString)
RaiseEvent OnText(3, Con.RemoteEndPoint.ToString & " - 连接断开")
RaiseEvent OnText(3, "发送数据给所有客户时失败")
End If
Exit Sub
Finally
Con = Nothing
SocketStream = Nothing
SentMsg = Nothing
End Try
Thread.Sleep(300)
Next
If msg = "" Then
RaiseEvent OnText(3, "自动发送数据给所有客户成功")
Else
RaiseEvent OnText(3, "发送数据给所有客户成功")
End If
End If
Thread.Sleep(300)
Catch ex As Exception
RaiseEvent OnText(3, "发送数据给所有客户时失败")
End Try
End Sub
''' <summary>
''' 接收客户的客户端消息
''' </summary>
Public Function RecvieMsg() As String
Dim msg As String = ""
Dim Con As Socket
Dim SStream As NetworkStream
Dim i As Short
Try
For i = 0 To SocketList.Count - 1
Con = SocketList.Item(i)
If Con Is Nothing OrElse Not Con.Connected Then
Exit For
End If
If Con.Available = 0 Then
Thread.Sleep(30)
Continue For
End If
SStream = New NetworkStream(Con)
Reader = New BinaryReader(SStream)
Try
msg = Reader.ReadString
Return msg
Catch ex As SocketException
MsgBox(ex.Message)
Finally
Reader = Nothing
SStream = Nothing
Con = Nothing
End Try
Thread.Sleep(30)
Next
Catch ex As Exception
End Try
Return Nothing
End Function
#End Region
Public Shared Function GetMyFirstIPAddress()
Try
Dim MyHostName As String = System.Net.Dns.GetHostName()
Dim MyIPEntry As System.Net.IPHostEntry = System.Net.Dns.GetHostEntry(MyHostName)
Dim MyAddresses() As System.Net.IPAddress = MyIPEntry.AddressList
Dim IP As String
For Each MyIP As System.Net.IPAddress In MyAddresses
IP = MyIP.ToString()
Dim temp() As String = IP.Split(".")
' Debug.Print(temp.Length)
Next
Return IP
Catch ex As Exception
MsgBox(ex.Message)
End Try
Return DBNull.Value
End Function
#Region "IDisposable Support"
Private disposedValue As Boolean ' 检测冗余的调用
' IDisposable
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
' TODO: 释放托管状态(托管对象)。
If MySocket IsNot Nothing Then MySocket.Close()
If listener IsNot Nothing Then listener.Stop()
SocketList = Nothing
MySocket = Nothing
SocketStream = Nothing
Writer = Nothing
Reader = Nothing
NewThread = Nothing
listener = Nothing
IsStarted = False
ClientCount = 0
End If
' TODO: 释放非托管资源(非托管对象)并重写下面的 Finalize()。
' TODO: 将大型字段设置为 null。
End If
Me.disposedValue = True
End Sub
' TODO: 仅当上面的 Dispose(ByVal disposing As Boolean)具有释放非托管资源的代码时重写 Finalize()。
'Protected Overrides Sub Finalize()
' ' 不要更改此代码。请将清理代码放入上面的 Dispose(ByVal disposing As Boolean)中。
' Dispose(False)
' MyBase.Finalize()
'End Sub
' Visual Basic 添加此代码是为了正确实现可处置模式。
Public Sub Dispose() Implements IDisposable.Dispose
' 不要更改此代码。请将清理代码放入上面的 Dispose(ByVal disposing As Boolean)中。
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
Imports System.Net.Sockets
Imports System
Imports System.Threading
Imports System.IO
Public Class ChatServer
Implements IDisposable
#Region "自定义变量"
Private ReadOnly ServerIP As IPAddress
Private ReadOnly PortNum As Integer = 5000
Private ReadOnly ServerTag As String
Private SocketList As New ArrayList
Private MySocket As Socket = Nothing
Private listener As TcpListener
Private SocketStream As NetworkStream
Private Writer As BinaryWriter
Private Reader As BinaryReader
Private NewThread As Thread = Nothing
Private IsStarted As Boolean = False '服务器状态为未启动
Private ClientCount As Integer = 0
Const CMAXCOUNT = 30 '容许连接的最大客户端数目
Public Event OnText(ByVal N As Integer, ByVal msg As String)
Private Index As Integer
Public ClientRemoteEndPoint As String
#End Region
#Region "初始化服务器端口参数"
''' <summary>
''' 初始化服务器端口参数
''' </summary>
Sub New(ByVal SerIP As IPAddress, ByVal Port As Integer, ByVal SerTag As String)
ServerIP = SerIP
PortNum = Port
ServerTag = SerTag
End Sub
#End Region
#Region "属性区域"
''' <summary>
''' 服务器连接状态
''' </summary>
Public ReadOnly Property IsConnected() As Boolean
Get
Return IsStarted
End Get
End Property
#End Region
#Region "自定义过程"
''' <summary>
''' 创建服务器
''' </summary>
Public Sub Start()
Try
'创建一个侦听对象
listener = New TcpListener(ServerIP, PortNum)
'启动服务器侦听端口
listener.Start()
IsStarted = True
RaiseEvent OnText(3, "服务器已启动")
While True
'连接客户端,返回一个 套接字
If ClientCount <= CMAXCOUNT Then
MySocket = listener.AcceptSocket()
'添加到连接列表中
SocketList.Add(MySocket)
ClientRemoteEndPoint = MySocket.RemoteEndPoint.ToString()
RaiseEvent OnText(1, ClientRemoteEndPoint)
SocketStream = New NetworkStream(MySocket)
Writer = New BinaryWriter(SocketStream)
'通知客户端,连接成功
' Writer.Write("与服务器成功连接" & vbCrLf) '应该在什么时候断开该连接
Writer.Write("EB90")
Writer.Flush()
ClientCount += 1
Else
MySocket = listener.AcceptSocket()
SocketStream = New NetworkStream(MySocket)
Writer = New BinaryWriter(SocketStream)
'通知客户端,连接成功
Writer.Write("Server>> 服务器的连接数已满,连接已经断开")
' MySocket.Disconnect(False) '断开连接
MySocket.Close()
End If
End While
Catch ex As Exception
IsStarted = False
If listener IsNot Nothing Then listener.Stop()
listener = Nothing
RaiseEvent OnText(3, "服务器启动失败,请检查网络。")
' MsgBox(ex.ToString)
Finally
SocketStream = Nothing
Writer = Nothing
MySocket = Nothing
End Try
End Sub
''' <summary>
''' 该方法在每个实例中仅容许使用一次
''' </summary>
Public Sub Connect()
If Not IsStarted Then
Try
'创建新线程,用新的线程启动服务器
NewThread = New Thread(New ThreadStart(AddressOf Start))
NewThread.Name = "Thread for sever start"
NewThread.Start()
' Catch ex As ThreadStartException
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.OkOnly, "线程启动错误")
'线程创建失败时服务器启动失败
End Try
Else
MsgBox("该实例中已经有一个服务器进程在运行,若要创建新的服务器请使用其它实例", _
MsgBoxStyle.OkOnly, "警告")
End If
End Sub
''' <summary>
''' 断开一个连接
''' </summary>
Public Sub Disconnect(ByVal index As Integer)
Try
Dim con As Socket = SocketList(index)
If con IsNot Nothing Then
SocketList.RemoveAt(index)
ClientCount -= 1
RaiseEvent OnText(2, con.RemoteEndPoint.ToString)
RaiseEvent OnText(3, con.RemoteEndPoint.ToString & " - 连接断开")
con.Close()
End If
Catch ex As Exception
MsgBox("操作错误")
End Try
End Sub
''' <summary>
''' 服务器连接断开
''' </summary>
Public Sub Close()
Try
If MySocket IsNot Nothing Then MySocket.Close()
If listener IsNot Nothing Then listener.Stop()
Catch ex As Exception
End Try
End Sub
''' <summary>
''' 发消息给指定客户端
''' </summary>
Public Sub SendMsg(ByVal index As Integer, ByVal msg As String)
Dim Con As Socket
Dim SocketStream As NetworkStream
Dim SentMsg As BinaryWriter
Try
Con = SocketList(index)
SocketStream = New NetworkStream(Con)
SentMsg = New BinaryWriter(SocketStream)
SentMsg.Write(msg) '发送信息
RaiseEvent OnText(3, "发送数据成功")
Catch ex As IndexOutOfRangeException
RaiseEvent OnText(3, "发送数据失败")
MsgBox(ex.Message, MsgBoxStyle.OkOnly, "越界异常")
Finally
Con = Nothing
SocketStream = Nothing
SentMsg = Nothing
End Try
End Sub
''' <summary>
''' 发消息给所有客户端
''' </summary>
Public Sub SendMsg(Optional ByVal msg As String = "")
Dim Con As Socket
Dim SocketStream As NetworkStream
Dim SentMsg As BinaryWriter
Try
If SocketList.Count > 0 Then
For Index = 0 To SocketList.Count - 1
Try
Con = SocketList(Index)
If Con Is Nothing Then
Thread.Sleep(300)
Continue For
End If
SocketStream = New NetworkStream(Con)
SentMsg = New BinaryWriter(SocketStream)
SentMsg.Write(msg) '发送信息
Catch ex As IOException
SocketList.RemoveAt(Index)
ClientCount -= 1
If Con IsNot Nothing Then
RaiseEvent OnText(2, Con.RemoteEndPoint.ToString)
RaiseEvent OnText(3, Con.RemoteEndPoint.ToString & " - 连接断开")
RaiseEvent OnText(3, "发送数据给所有客户时失败")
End If
Exit Sub
Finally
Con = Nothing
SocketStream = Nothing
SentMsg = Nothing
End Try
Thread.Sleep(300)
Next
If msg = "" Then
RaiseEvent OnText(3, "自动发送数据给所有客户成功")
Else
RaiseEvent OnText(3, "发送数据给所有客户成功")
End If
End If
Thread.Sleep(300)
Catch ex As Exception
RaiseEvent OnText(3, "发送数据给所有客户时失败")
End Try
End Sub
''' <summary>
''' 接收客户的客户端消息
''' </summary>
Public Function RecvieMsg() As String
Dim msg As String = ""
Dim Con As Socket
Dim SStream As NetworkStream
Dim i As Short
Try
For i = 0 To SocketList.Count - 1
Con = SocketList.Item(i)
If Con Is Nothing OrElse Not Con.Connected Then
Exit For
End If
If Con.Available = 0 Then
Thread.Sleep(30)
Continue For
End If
SStream = New NetworkStream(Con)
Reader = New BinaryReader(SStream)
Try
msg = Reader.ReadString
Return msg
Catch ex As SocketException
MsgBox(ex.Message)
Finally
Reader = Nothing
SStream = Nothing
Con = Nothing
End Try
Thread.Sleep(30)
Next
Catch ex As Exception
End Try
Return Nothing
End Function
#End Region
Public Shared Function GetMyFirstIPAddress()
Try
Dim MyHostName As String = System.Net.Dns.GetHostName()
Dim MyIPEntry As System.Net.IPHostEntry = System.Net.Dns.GetHostEntry(MyHostName)
Dim MyAddresses() As System.Net.IPAddress = MyIPEntry.AddressList
Dim IP As String
For Each MyIP As System.Net.IPAddress In MyAddresses
IP = MyIP.ToString()
Dim temp() As String = IP.Split(".")
' Debug.Print(temp.Length)
Next
Return IP
Catch ex As Exception
MsgBox(ex.Message)
End Try
Return DBNull.Value
End Function
#Region "IDisposable Support"
Private disposedValue As Boolean ' 检测冗余的调用
' IDisposable
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
' TODO: 释放托管状态(托管对象)。
If MySocket IsNot Nothing Then MySocket.Close()
If listener IsNot Nothing Then listener.Stop()
SocketList = Nothing
MySocket = Nothing
SocketStream = Nothing
Writer = Nothing
Reader = Nothing
NewThread = Nothing
listener = Nothing
IsStarted = False
ClientCount = 0
End If
' TODO: 释放非托管资源(非托管对象)并重写下面的 Finalize()。
' TODO: 将大型字段设置为 null。
End If
Me.disposedValue = True
End Sub
' TODO: 仅当上面的 Dispose(ByVal disposing As Boolean)具有释放非托管资源的代码时重写 Finalize()。
'Protected Overrides Sub Finalize()
' ' 不要更改此代码。请将清理代码放入上面的 Dispose(ByVal disposing As Boolean)中。
' Dispose(False)
' MyBase.Finalize()
'End Sub
' Visual Basic 添加此代码是为了正确实现可处置模式。
Public Sub Dispose() Implements IDisposable.Dispose
' 不要更改此代码。请将清理代码放入上面的 Dispose(ByVal disposing As Boolean)中。
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class