TCPserver客户端

本文介绍了一个聊天服务器的实现细节,包括服务器的初始化、启动、连接管理、消息收发等功能。通过多线程技术实现了客户端的并发处理,并且具备了客户端数量限制、断线处理等实用功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值