تقييم الموضوع :
  • 0 أصوات - بمعدل 0
  • 1
  • 2
  • 3
  • 4
  • 5
[VB.NET] طلب مساعدة في أستعمل Class Winsock
#1
أرجوا من السادة المخطصين في برمجة vb.net
شرح كيفية أستعمال2 class المرفقين مع الموضوع وشكرا

client
كود :
Imports System
Imports System.Net
Imports System.Net.Sockets
Imports System.Threading
Imports System.Text

Public Class Winsock

    Private Class StateObject

        ' Socket cliente.
        ' Client socket.
        Public workSocket As Socket = Nothing

        ' Tamaٌo del buffer de recepcion.
        ' Size of receive buffer.
        Public Const BufferSize As Integer = 8192

        ' Buffer de recepcion.
        ' Receive buffer.
        Public buffer(BufferSize) As Byte

        ' Ultimos Datos recibidos.
        ' Received data string.
        Public UltimosDatos As String

    End Class 'StateObject

#Region " VARIABLES "

    ' Creo un socket TCP/IP.
    ' Create a TCP/IP socket.
    Private Client As Socket

    ' Estado Inicial.
    ' Initial state.
    Private SockState As States = States.Closed

    ' Indica si el socket debera reconectar automaticamente si hay una desconexion.
    ' It indicates if socket connect automatically if there is a disconnection.
    Private LReConnect As Boolean = False

    ' Tiempo de Espera desde la desconexion hasta el nuevo intento de conexion.(milisegundos)
    ' esperar 10 segundos antes del reintento.
    ' Time of Delay from the disconnection to the new attempt of connection. (milliseconds)
    ' wait 10 seconds before reconnect.
    Private LWait As Integer = 10000

    ' Valores para reconexion. ip y port.
    ' Values to reconnect. ip and port.
    Private OpTimer As String = String.Empty

    ' Timer que intentara reconectar.
    ' Timer that tried to reconnect
    Private stateTimer As Timer

    Private LVerifyConnexion As Boolean

    Private LInterval As Integer

    Private stateTimerVer As Timer

#End Region

#Region " FUNCIONES PRIVADAS "

    Private Sub ChangeState(ByVal NuevoEstado As States)

        SockState = NuevoEstado
        RaiseEvent StateChanged(NuevoEstado)

    End Sub 'ChangeState

    Private Sub ReConnectSock(ByVal State As String)

        Try
            Dim timerDelegate As TimerCallback = AddressOf MyTimerCallBack
            stateTimer = New Timer(timerDelegate, State, LWait, LWait)
        Catch
            LReConnect = False
        End Try

    End Sub

    Private Sub Verify()

        Try
            Dim timerDelegate As TimerCallback = AddressOf MyTimerCallBackVer
            stateTimerVer = New Timer(timerDelegate, Nothing, LInterval, LInterval)
        Catch
            LVerifyConnexion = False
        End Try

    End Sub
#End Region

#Region " FUNCIONES PUBLICAS "

    Public Function IsConnected() As Boolean
        ' Asي se puede determinar si un socket estل conectado.
        ' This is how you can determine whether a socket is still connected.
        Dim blockingState As Boolean
        Try
            blockingState = Client.Blocking
            Dim tmp(0) As Byte

            Client.Blocking = False
            Client.Send(tmp, 0, 0)
            Return True

        Catch e As SocketException
            ' 10035 == WSAEWOULDBLOCK
            If e.NativeErrorCode.Equals(10035) Then
                'Esta conectado pero no puede enviar
                If Not GetState.Equals(States.Closed) Or Not GetState.Equals(States.Closing) Then
                    Call Close()
                End If
                Return False
            Else
                Return False
            End If
        Catch e As Exception
            Return False
        Finally
            If Not IsNothing(Client) Then
                If Client.Connected = True Then Client.Blocking = blockingState
            End If

        End Try

    End Function 'IsConnected

    Public Function IsFreeToSend() As Boolean

        If IsConnected() And GetState.Equals(States.Connected) Then
            Return True
        Else
            Return False
        End If

    End Function 'IsFreeToSend

    Public Function RemoteHostIP() As String
        Try
            Dim Idcliente As IPEndPoint = Client.RemoteEndPoint
            Return Idcliente.Address.ToString
        Catch
            ChangeState(States.Error)
            RaiseEvent ErrorSocket(Err.Number, Err.Description)
            Return ""
        End Try

    End Function 'RemoteHostIP

    Public Function RemoteHostPort() As String
        Try
            Dim Idcliente As IPEndPoint = Client.RemoteEndPoint
            Return Idcliente.Port.ToString
        Catch
            ChangeState(States.Error)
            RaiseEvent ErrorSocket(Err.Number, Err.Description)
            Return ""
        End Try

    End Function 'RemoteHostPort

    Public Function LocalPort() As String
        Try
            Dim Idcliente As IPEndPoint = Client.LocalEndPoint
            Return Idcliente.Port.ToString
        Catch
            ChangeState(States.Error)
            RaiseEvent ErrorSocket(Err.Number, Err.Description)
            Return ""
        End Try

    End Function 'LocalPort

    Public Function LocalIP() As String
        Try
            Dim Idcliente As IPEndPoint = Client.LocalEndPoint
            Return Idcliente.Address.ToString
        Catch
            ChangeState(States.Error)
            RaiseEvent ErrorSocket(Err.Number, Err.Description)
            Return ""
        End Try

    End Function 'LocalIP


#End Region

#Region " EVENTOS "

    Public Event Connected()

    Public Event ErrorSocket(ByVal Number As Integer, ByVal Message As String)

    Public Event SendComplete()

    Public Event DataArrival(ByVal Data As String)

    Public Event Disconnected()

    Public Event StateChanged(ByVal State As String)


#End Region

#Region " PROPIEDADES "

    Public ReadOnly Property GetState() As States

        Get
            Return SockState
        End Get

    End Property 'GetState

    Public Property ReConnect() As Boolean

        Get
            ReConnect = LReConnect
        End Get

        Set(ByVal value As Boolean)
            LReConnect = value
        End Set

    End Property 'ReConnect

    Public Property WaitMilliseconds() As Integer

        Get
            WaitMilliseconds = LWait
        End Get

        Set(ByVal value As Integer)
            LWait = IIf(value < 10000, 10000, value)
        End Set

    End Property 'WaitMilliseconds

    Public Property VerifyConnexion() As Boolean

        Get
            VerifyConnexion = LVerifyConnexion
        End Get

        Set(ByVal value As Boolean)
            If LVerifyConnexion = False And value = True Then
                LVerifyConnexion = value
                Call Verify()
            End If
            LVerifyConnexion = value
        End Set

    End Property 'VerifyConnexion

    Public Property Interval() As Integer

        Get
            Interval = LInterval
        End Get

        Set(ByVal value As Integer)
            LInterval = IIf(value < 30000, 30000, value)
        End Set

    End Property 'WaitMilliseconds

#End Region

#Region " METODOS "

    Public Sub Connect(ByVal Ip As String, ByVal Port As Integer)
        '    'Compruebo si el cliente esta conectado.
        If GetState <> States.Closed Then
            RaiseEvent ErrorSocket(0, "Para Conectar el socket debe estar Cerrado. Estado actual : " & GetState)
            Exit Sub
        End If
        'String que contiene los valores para reconectar.
        OpTimer = Ip + vbTab + Port.ToString + vbTab

        Try
            
            Dim ipAddress As IPAddress
            Dim remoteEP As IPEndPoint = Nothing
            Try
                ipAddress = Net.IPAddress.Parse(Ip)
                remoteEP = New IPEndPoint(ipAddress, Port)
            Catch ex As Exception
                For i As Integer = 0 To Dns.GetHostEntry(Ip).AddressList.Length - 1
                    Dim Nip As String = Dns.GetHostEntry(Ip).AddressList(i).ToString
                    ipAddress = Net.IPAddress.Parse(Nip)
                    remoteEP = New IPEndPoint(ipAddress, Port)
                    If ipAddress.IsIPv6LinkLocal = True Or ipAddress.IsIPv6Multicast = True Or ipAddress.IsIPv6SiteLocal = True Then
                        remoteEP = Nothing
                    Else
                        Exit For
                    End If
                Next
            End Try

            Client = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)

            'Permanencia de un segundo después de llamar al método Close.
            'Linger one second after calling the Close method.
            Dim myOpts As New LingerOption(True, 1)
            Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, _
               myOpts)

            ChangeState(States.Connecting)

            'si he de reconectar
            If LReConnect = True And IsNothing(stateTimer) Then Call ReConnectSock(OpTimer)

            ' Conecto con el endpoint.
            ' Connect to the remote endpoint.
            Client.BeginConnect(remoteEP, New AsyncCallback(AddressOf ConnectCallback), Client)

        Catch ex As SocketException
            ChangeState(States.Error)
            RaiseEvent ErrorSocket(ex.ErrorCode, ex.Message)
        Catch ex1 As Exception
            ChangeState(States.Error)
            RaiseEvent ErrorSocket(Err.Number, ex1.Message)
        End Try

    End Sub 'Connect

    Public Sub SendData(ByVal Data As String)
        Try
            ChangeState(States.Sending)
            ' Envيo los datos
            ' Send data to the remote device.
            Send(Client, Data)
        Catch ex As SocketException
            ChangeState(States.Error)
            RaiseEvent ErrorSocket(ex.ErrorCode, ex.Message)
        End Try
    End Sub 'Sendata

    Public Sub Close()
        Try
            If GetState <> States.Closed Then
                If GetState = States.Connected Then Client.Shutdown(SocketShutdown.Both)
                ChangeState(States.Closing)
                Client.BeginDisconnect(False, New AsyncCallback(AddressOf CloseCallBack), Client)
            End If
        Catch ex1 As SocketException
            ChangeState(States.Closed)
            RaiseEvent ErrorSocket(Err.Number, Err.Description)
        Catch ex As Exception
            ChangeState(States.Closed)
            RaiseEvent ErrorSocket(Err.Number, Err.Description)

        End Try

    End Sub 'Close

    Private Sub Send(ByVal client As Socket, ByVal data As String)
        Try
            ' Convertir la cadena a bytes utilizando la codificaciَn ASCII.
            ' Convert the string data to byte data using ASCII encoding.
            Dim byteData As Byte() = Encoding.Default.GetBytes(data)
            ' Empezar a enviar datos
            ' Begin sending the data to the remote device.
            client.BeginSend(byteData, 0, byteData.Length, 0, New AsyncCallback(AddressOf SendCallback), client)

        Catch ex As SocketException
            ChangeState(States.Error)
            RaiseEvent ErrorSocket(ex.ErrorCode, ex.Message)
        Catch ex1 As Exception
            ChangeState(States.Error)
            RaiseEvent ErrorSocket(Err.Number, ex1.Message)
        End Try
    End Sub 'Send

    Private Sub Receive(ByVal client As Socket)
        Try
            ' Creo el objeto
            ' Create the state object.
            Dim state As New StateObject
            state.workSocket = client
            ' Empezar a recibir datos
            ' Begin receiving the data from the remote device.
            client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf ReceiveCallback), state)
        Catch ex As SocketException
            ChangeState(States.Error)
            RaiseEvent ErrorSocket(ex.ErrorCode, ex.Message)
        Catch ex1 As Exception
            ChangeState(States.Error)
            RaiseEvent ErrorSocket(Err.Number, ex1.Message)
        End Try
    End Sub 'Receive


#End Region

#Region " SUB ASYNC "

    Private Sub ConnectCallback(ByVal ar As IAsyncResult)
        ' Recupero el socket
        ' Retrieve the socket from the state object.
        Dim Client As Socket = CType(ar.AsyncState, Socket)

        Try
            ' Se completa la conexiَn
            ' Complete the connection.
            Client.EndConnect(ar)

            ChangeState(States.Connected)

            RaiseEvent Connected()
            ' Empezamos a recibir
            ' Receive the response from the remote device.
            Receive(Client)

        Catch ex As SocketException
            ChangeState(States.Error)
            RaiseEvent ErrorSocket(ex.ErrorCode, ex.Message)
        Catch ex1 As Exception
            ChangeState(States.Error)
            RaiseEvent ErrorSocket(Err.Number, ex1.Message)
        End Try

    End Sub 'ConnectCallback

    Private Sub SendCallback(ByVal ar As IAsyncResult)

        Try
            ' Recupero el socket
            ' Retrieve the socket from the state object.
            Dim client As Socket = CType(ar.AsyncState, Socket)

            ' Completar el envيo de datos al dispositivo remoto.
            ' Complete sending the data to the remote device.
            Dim bytesSent As Integer = client.EndSend(ar)

            ChangeState(States.Connected)
            ' Seٌal de que todo se ha enviado
            ' Signal that all bytes have been sent.
            RaiseEvent SendComplete()

        Catch ex As SocketException
            ChangeState(States.Error)
            RaiseEvent ErrorSocket(ex.ErrorCode, ex.Message)
        End Try

    End Sub 'SendCallback

    Private Sub ReceiveCallback(ByVal ar As IAsyncResult) 'ReceiveCallback
        ' Recupero el objeto y el socket
        ' Retrieve the state object and the client socket
        ' from the asynchronous state object.
        Try
            Dim state As StateObject = CType(ar.AsyncState, StateObject)
            Dim client As Socket = state.workSocket

            Dim bytesRead As Integer = client.EndReceive(ar)

            If bytesRead < 1 Then
                If Not GetState.Equals(States.Closed) And Not GetState.Equals(States.Closing) Then Call Close()
            Else
                ' Compruebo si la linea acaba en <EOF>
                Dim Linea As String = Nothing
                Linea = Encoding.Default.GetString(state.buffer, 0, bytesRead)

                If Linea.EndsWith("<EOF>") Then
                    state.UltimosDatos += Encoding.Default.GetString(state.buffer, 0, bytesRead)
                    'Genero el evento de la recepcion del mensaje
                    RaiseEvent DataArrival(state.UltimosDatos)
                    state.UltimosDatos = String.Empty
                Else
                    'almaceno hasta que acabe en <EOF>
                    state.UltimosDatos += Encoding.Default.GetString(state.buffer, 0, bytesRead)
                End If

                client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf ReceiveCallback), state)
            End If

        Catch ex1 As SocketException
            If Not GetState.Equals(States.Closed) And Not GetState.Equals(States.Closing) Then Call Close()
        Catch ex As Exception
            If Not GetState.Equals(States.Closed) And Not GetState.Equals(States.Closing) Then Call Close()
        End Try

    End Sub 'ReceiveCallback

    Private Sub CloseCallBack(ByVal ar As IAsyncResult)

        If Not GetState.Equals(States.Closed) Then
            ChangeState(States.Closed)

            RaiseEvent Disconnected()

        End If


    End Sub 'CloseCallBack

    Private Sub MyTimerCallBack(ByVal State As Object)

        Try
            If LReConnect = False Then
                If Not IsNothing(stateTimer) Then stateTimer.Dispose()
                stateTimer = Nothing
                Exit Sub
            End If

            If GetState.Equals(States.Error) Then ChangeState(States.Closed)
            If GetState.Equals(States.Closed) Then
                Dim optimer As String = DirectCast(State, String)
                Dim TheValues As String() = Split(optimer, vbTab)
                Call Connect(TheValues(0), CType(TheValues(1), Integer))
            End If

        Catch
            If Not IsNothing(stateTimer) Then stateTimer.Dispose()
            stateTimer = Nothing
        End Try

    End Sub 'MyTimerCallBack

    Private Sub MyTimerCallBackVer(ByVal State As Object)

        Try
            If LVerifyConnexion = False Then
                If Not IsNothing(stateTimerVer) Then stateTimerVer.Dispose()
                stateTimerVer = Nothing
                Exit Sub
            End If

            If GetState.Equals(States.Connected) Then
                If IsConnected.Equals(False) Then
                    If GetState.Equals(States.Connected) Then Call Close()
                End If
            End If

        Catch
            If Not IsNothing(stateTimerVer) Then stateTimerVer.Dispose()
            stateTimerVer = Nothing
        End Try

    End Sub 'MyTimerCallBackVer

#End Region

#Region " ENUM "

    Public Enum States
        Closed = 0
        Deleted = 1

        Sending = 3

        Connecting = 6
        Connected = 7
        Closing = 8
        [Error] = 9

    End Enum 'States

#End Region
End Class


server

كود :
Imports System
Imports System.Net
Imports System.Net.Sockets
Imports System.Threading
Imports System.Text

Public Class Winsock

    Private Class StateObject
        ' Socket Cliente.
        Public Socket As Socket = Nothing
        ' Tamaٌo del buffer.
        Public Const BufferSize As Integer = 8192
        ' Buffer de recepciَn.
        Public buffer(BufferSize) As Byte
        ' Ultima cadena recibida.
        Public UltimosDatos As String
        'Indice de conexion asignado.
        Public IndexCli As Integer
        'Estado del Socket.
        Public SockState As States = States.Closed

    End Class 'StateObject

#Region " VARIABLES "

    ' Create a TCP/IP socket to Listen.
    Private Listener As Socket
    'Estado del socket que escucha.
    Private SockState As States = States.Closed
    'Aqui se guarda la informacion de todos los clientes conectados
    Private Clientes As New Hashtable()
    ''Ultimo indice que se ha aٌadido a la coleccion
    'Private NuevaCon As Integer
    ''Numero de conexion mayor
    'Private NconIP As Integer
    'Informo a CloseCallBack para que cierre el listener y limpie la hashtable.
    Private CloseAllSockets As Boolean

#End Region

#Region " EVENTOS "

    Public Event ConnectionRequest(ByVal Index As Integer)

    Public Event DataArrival(ByVal Index As Integer, ByVal Data As String)

    Public Event Disconnected(ByVal Index As Integer)

    Public Event ErrorSocket(ByVal Index As Integer, ByVal Number As Integer, ByVal Message As String, ByVal Method As String)

    Public Event SendComplete(ByVal Index As Integer)

    Public Event StateChanged(ByVal Index As Integer, ByVal State As String)

#End Region

#Region " METODOS "

    Public Sub Listen(ByVal Ip As String, ByVal Port As Integer)

        If GetState(0) = States.Listening Then Exit Sub

        Try
            
            Dim ipAddress As IPAddress = Nothing
            Dim Nip As String = String.Empty
            Try
                IPAddress = Net.IPAddress.Parse(Ip)
            Catch ex As Exception
                For i As Integer = 0 To Dns.GetHostEntry(Ip).AddressList.Length - 1
                    Nip = Dns.GetHostEntry(Ip).AddressList(i).ToString
                    ipAddress = Net.IPAddress.Parse(Nip)
                    Dim value As Boolean
                    value = ipAddress.IsIPv6LinkLocal
                    If value = False Then Exit For
                Next
                'Ip = Dns.GetHostEntry(Ip).AddressList(0).ToString
                'ipAddress = Net.IPAddress.Parse(Ip)            

            End Try



            Dim localEndPoint As New IPEndPoint(ipAddress, Port)

            Listener = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)

            'Permite enlazar un socket para obtener acceso exclusivo.En este caso es Falso.
            Listener.ExclusiveAddressUse = False

            'Permite enlazar el socket a una direcciَn que ya estل en uso
            Listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, True)


            Listener.Bind(localEndPoint)
            Listener.Listen(100)

            ChangeState(0, States.Listening)

            Listener.BeginAccept(New AsyncCallback(AddressOf AcceptCallback), Listener)

        Catch
            If Not IsNothing(Listener) Then Listener.Close()
            ChangeState(0, States.Error)
            RaiseEvent ErrorSocket(0, Err.Number, Err.Description, "Listen")
        End Try

    End Sub 'Listen

    Public Sub Close(ByVal Index As Integer)
        Dim Cliente As New StateObject
        Try
            Select Case Index
                Case 0
                    Dim Keycol As New Collection

                    For Each Cliente In Clientes.Values
                        Keycol.Add(Cliente.IndexCli)
                    Next

                    If Keycol.Count > 0 Then

                        'Informo a CloseCallBack para que cierre el listener y limpie la hashtable.
                        CloseAllSockets = True

                        For i As Integer = 1 To Keycol.Count
                            Close(CType(Keycol.Item(i), Integer))
                        Next
                    End If

                    If Keycol.Count = 0 Then
                        Clientes.Clear()

                        'Compruebo el estado del listener antes de cambiar a Closed.
                        'para no disparar el evento Disconnected, en el caso de que ya estuviera
                        'desconectado al cerrar el listener.
                        Dim Actualstate As States = SockState

                        'Cambio el estado del listener.
                        If Actualstate <> States.Closed Then ChangeState(Index, States.Closed)


                        'Cierro el socket que escucha.
                        If Not IsNothing(Listener) Then Listener.Close()

                        'Genero el evento disconnected de listener
                        If Actualstate <> States.Closed Then RaiseEvent Disconnected(0)
                    Else
                        'Limpio la colecion de key.
                        Keycol.Clear()
                    End If



                Case Else

                    If Clientes.ContainsKey(Index) Then

                        'Obtengo la informacion del cliente solicitado.
                        Cliente = Clientes(Index)
                        If GetState(Index) <> States.Closed And GetState(Index) <> States.Closing Then

                            'Cierro la conexion con el cliente.
                            If Cliente.Socket.Connected = True Then Cliente.Socket.Shutdown(SocketShutdown.Both)
                            ChangeState(Index, States.Closing)
                            ''''''''''''''''''''''''
                            Dim handler As Socket = Cliente.Socket

                            handler.BeginDisconnect(False, New AsyncCallback(AddressOf CloseCallBack), Cliente)

                        End If
                    End If
            End Select
        Catch ex1 As SocketException
            ChangeState(Index, States.Closed)
            Cliente.Socket.Close()
        Catch ex As Exception
            ChangeState(Index, States.Closed)
            RaiseEvent ErrorSocket(Index, Err.Number, Err.Description, "Close")

        End Try

    End Sub 'Close

    Public Sub SendData(ByVal Index As Integer, ByVal Data As String)
        Try
            ' Convert the string data to byte data using ASCII encoding.
            Dim byteData As Byte() = Encoding.Default.GetBytes(Data)

            Dim Cliente As StateObject = Clientes(Index)

            Dim handler As Socket = Cliente.Socket
            ' Begin sending the data to the remote device.

            ChangeState(Index, States.Sending)
            'SyncLock Me
            handler.BeginSend(byteData, 0, byteData.Length, 0, New AsyncCallback(AddressOf SendCallback), Cliente)
            'End SyncLock

        Catch
            ChangeState(Index, States.Error)
            RaiseEvent ErrorSocket(Index, Err.Number, Err.Description, "SendData")
        End Try
    End Sub 'Send

    Public Sub SendDataToAll(ByVal Data As String, ByVal Exclude As Integer)

        Dim Cliente As New StateObject
        ' Convert the string data to byte data using ASCII encoding.
        Dim byteData As Byte() = Encoding.Default.GetBytes(Data)

        Try
            'Recorro todos los clientes conectados, y les envio Datos
            For Each Cliente In Clientes.Values
                If Not Cliente.IndexCli.Equals(Exclude) Then
                    Dim handler As Socket = Cliente.Socket
                    ChangeState(Cliente.IndexCli, States.Sending)
                    ' Begin sending the data to the remote device.
                    handler.BeginSend(byteData, 0, byteData.Length, 0, New AsyncCallback(AddressOf SendCallback), Cliente)
                End If
            Next
        Catch
            ChangeState(Cliente.IndexCli, States.Error)
            RaiseEvent ErrorSocket(Cliente.IndexCli, Err.Number, Err.Description, "SendDataToAll - Index : " _
            & Cliente.IndexCli.ToString)
        End Try
    End Sub 'SendDataToAll

#End Region

#Region " METODOS PRIVADOS "

    Private Sub ChangeState(ByVal Index As Integer, ByVal NuevoEstado As States)
        Select Case Index
            Case 0
                SockState = NuevoEstado
            Case Else
                'si se ha encontrado en la coleccion y esta conectado
                If Clientes.ContainsKey(Index) = True Then
                    Dim Cliente As New StateObject
                    Cliente = Clientes(Index)
                    Try
                        Cliente.SockState = NuevoEstado
                    Catch

                    End Try
                Else
                    NuevoEstado = States.Deleted
                End If
        End Select
        'SyncLock Me
        RaiseEvent StateChanged(Index, CType(NuevoEstado, String))
        'End SyncLock
    End Sub

    'Private Function ComprobarNConIp(ByVal Index As Integer) As Boolean

    '    'si se ha encontrado en la coleccion y esta conectado
    '    If Clientes.ContainsKey(Index) = True Then
    '        'si esta conectado devuelvo true
    '        'si no lo esta false.
    '        If IsConnected(Index) Then
    '            Return True
    '        Else
    '            Clientes.Remove(Index)
    '            Return False
    '        End If
    '    Else
    '        Return False
    '    End If

    'End Function

#End Region

#Region " PROPIEDADES "

    Public ReadOnly Property GetState(ByVal Index As Integer) As States
        Get
            Select Case Index
                Case 0
                    Return SockState
                Case Else
                    'si se ha encontrado en la coleccion.
                    If Clientes.ContainsKey(Index) = True Then
                        Try
                            Dim Cliente As New StateObject
                            Cliente = Clientes(Index)
                            Return Cliente.SockState
                        Catch

                        End Try
                    Else
                        Return States.Deleted
                    End If
            End Select
        End Get
    End Property

#End Region

#Region " FUNCIONES PUBLICAS "

    Public Function IsConnected(ByVal Index As Integer) As Boolean

        Dim Cliente As New StateObject
        Try
            Select Case Index
                Case 0
                    If SockState = States.Listening Then
                        If Listener.Poll(1000, SelectMode.SelectRead) Or _
                            Listener.Poll(1000, SelectMode.SelectWrite) Or _
                            Listener.Poll(1000, SelectMode.SelectError) = False Then
                            Return True
                        End If
                    End If
                Case Else
                    'si se ha encontrado en la coleccion.
                    If Clientes.ContainsKey(Index) = True Then

                        Cliente = Clientes(Index)

                        ' This is how you can determine whether a socket is still connected.
                        Dim blockingState As Boolean
                        Try
                            blockingState = Cliente.Socket.Blocking
                            Dim tmp(0) As Byte

                            Cliente.Socket.Blocking = False
                            Cliente.Socket.Send(tmp, 0, 0)
                            Return True

                        Catch e As SocketException
                            ' 10035 == WSAEWOULDBLOCK
                            If e.NativeErrorCode.Equals(10035) Then
                                'Esta conectado pero no puede enviar
                                Call Close(Index)
                                Return False
                            Else
                                Return False
                            End If
                        Catch e As Exception
                            Return False
                        Finally
                            If Not IsNothing(Cliente.Socket) Then
                                If Cliente.Socket.Connected = True Then Cliente.Socket.Blocking = blockingState
                            End If
                        End Try
                    Else
                        Return False
                    End If
            End Select
        Catch
            Return False
        End Try
    End Function 'IsConnected

    Public Function IsFreeToSend(ByVal Index As Integer) As Boolean
        Dim Cliente As New StateObject
        Try
            Select Case Index
                Case 0
                    Return False
                Case Else
                    'si se ha encontrado en la coleccion.
                    If Clientes.ContainsKey(Index) = True Then
                        Cliente = Clientes(Index)
                        'Not allowed for the state Sending
                        If IsConnected(Index) And GetState(Index) = States.Connected Then
                            Return True
                        End If
                    Else
                        Return False
                    End If
            End Select
        Catch
            Return False
        End Try

    End Function 'IsFreeToSend

    Public Function RemoteClientIP(ByVal Index As Integer) As String
        Try
            Dim Cliente As StateObject = Clientes(Index)
            Dim Idcliente As IPEndPoint = Cliente.Socket.RemoteEndPoint
            Return Idcliente.Address.ToString
        Catch
            'RaiseEvent ErrorSocket(Index, Err.Number, Err.Description, "RemoteClientIP")
            Return ""
        End Try

    End Function 'RemoteClientIP

    Public Function RemoteClientPort(ByVal Index As Integer) As String
        Try
            Dim Cliente As StateObject = Clientes(Index)
            Dim Idcliente As IPEndPoint = Cliente.Socket.RemoteEndPoint
            Return Idcliente.Port.ToString
        Catch ex As Exception
            'RaiseEvent ErrorSocket(Index, Err.Number, Err.Description, "RemoteClientIP")
            Return ""
        End Try

    End Function 'RemoteClientPort

    Public Function LocalIP() As String
        Try
            Dim Idlocal As IPEndPoint = Listener.LocalEndPoint
            Return Idlocal.Address.ToString
        Catch
            'RaiseEvent ErrorSocket(0, Err.Number, Err.Description, "LocalIP")
            Return ""
        End Try

    End Function 'LocalIP

    Public Function LocalPort() As String
        Try
            Dim Idlocal As IPEndPoint = Listener.LocalEndPoint
            Return Idlocal.Port.ToString
        Catch
            'RaiseEvent ErrorSocket(0, Err.Number, Err.Description, "LocalIP")
            Return ""
        End Try
    End Function 'LocalPort

#End Region

#Region " SUB ASYNC "

    Private Sub AcceptCallback(ByVal ar As IAsyncResult)
        If GetState(0) = States.Closed Then Exit Sub
        Dim state As New StateObject
        'compruebo que Index le asigno.
        'NuevaCon = 0

        Dim handler As Socket = Nothing
        Try
            ' Get the socket that handles the client request.
            Dim listener As Socket = CType(ar.AsyncState, Socket)
            ' End the operation.
            handler = listener.EndAccept(ar)
            listener.BeginAccept(New AsyncCallback(AddressOf AcceptCallback), listener)

            ' Create the state object for the async receive.
            state.Socket = handler

            'Permanencia de un segundo después de llamar al método Close.
            'Linger one second after calling the Close method.
            Dim myOpts As New LingerOption(True, 1)
            state.Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, _
               myOpts)
            'le asigno siempre el indice 1
            state.IndexCli = 1
            state.SockState = States.Connected
            Clientes.Add(state.IndexCli, state)
            RaiseEvent ConnectionRequest(state.IndexCli)
            ''For i As Integer = 1 To NconIP
            ''    If ComprobarNConIp(i) = False Then
            ''        NuevaCon = i
            ''        Exit For
            ''    End If
            ''Next i
            ''If NuevaCon = 0 Then NconIP = NconIP + 1 : NuevaCon = NconIP
            ' ''indice de conexion del cliente.
            ''state.IndexCli = NuevaCon
            ' ''estado del socket cliente.
            ''state.SockState = States.Connected
            ''SyncLock Me
            ''    'aٌado el cliente a la coleccion.
            ''    Clientes.Add(state.IndexCli, state)
            ''    ChangeState(state.IndexCli, States.Connected)
            ''    RaiseEvent ConnectionRequest(state.IndexCli)
            ''End SyncLock
            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf ReceiveCallback), state)
        Catch
            If Not IsNothing(handler) Then
                handler.Close()
            Else
                Call Close(0)
                ChangeState(0, States.Error)
                RaiseEvent ErrorSocket(0, Err.Number, Err.Description, "AcceptCallback")
            End If
        End Try
    End Sub 'AcceptCallback

    Private Sub ReceiveCallback(ByVal ar As IAsyncResult)
        'Retrieve the state object and the handler socket
        ' from the asynchronous state object.
        Dim state As StateObject = CType(ar.AsyncState, StateObject)
        Dim handler As Socket = state.Socket
        Try
            ' Read data from the client socket.
            Dim bytesRead As Integer = handler.EndReceive(ar)

            If bytesRead < 1 Then
                If CloseAllSockets = False Then Close(state.IndexCli)
                Exit Sub
            Else
                'If state.IndexCli = 0 Then
                '    'indice de conexion del cliente.
                '    state.IndexCli = CType(Encoding.Default.GetString(state.buffer, 0, bytesRead), Integer)
                '    'estado del socket cliente.
                '    state.SockState = States.Connected
                '    SyncLock Me
                '        'si ya existe la clave primero la elimino
                '        If Clientes.ContainsKey(state.IndexCli) Then Clientes.Remove(state.IndexCli)
                '        'aٌado el cliente a la coleccion.
                '        Clientes.Add(state.IndexCli, state)
                '    End SyncLock

                '    ChangeState(state.IndexCli, States.Connected)

                '    'SyncLock Me
                '    RaiseEvent ConnectionRequest(state.IndexCli)
                '    'End SyncLock
                'Else
                ' Compruebo si la linea acaba en <EOF>
                Dim Linea As String = Nothing
                Linea = Encoding.Default.GetString(state.buffer, 0, bytesRead)

                If Linea.EndsWith("<EOF>") Then
                    state.UltimosDatos += Encoding.Default.GetString(state.buffer, 0, bytesRead)
                    'Genero el evento de la recepcion del mensaje
                    RaiseEvent DataArrival(state.IndexCli, state.UltimosDatos)
                    state.UltimosDatos = String.Empty
                Else
                    ' There  might be more data, so store the data received so far.
                    state.UltimosDatos += Encoding.Default.GetString(state.buffer, 0, bytesRead)
                End If
            End If
            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf ReceiveCallback), state)
            'End If
        Catch ex As SocketException
            Close(state.IndexCli)
            Exit Sub
        Catch e As Exception
            Exit Sub
        End Try

    End Sub 'ReadCallback

    Private Sub SendCallback(ByVal ar As IAsyncResult)

        Dim Cliente As StateObject = CType(ar.AsyncState, StateObject)
        Try
            ' Retrieve the socket from the state object.
            Dim handler As Socket = Cliente.Socket

            ' Complete sending the data to the remote device.
            Dim bytesSent As Integer = handler.EndSend(ar)

            ChangeState(Cliente.IndexCli, States.Connected)

            'SyncLock Me
            RaiseEvent SendComplete(Cliente.IndexCli)
            'End SyncLock
        Catch
            ChangeState(Cliente.IndexCli, States.Error)
            RaiseEvent ErrorSocket(Cliente.IndexCli, Err.Number, Err.Description, "SendCallback")
        End Try
    End Sub 'SendCallback

    Private Sub CloseCallBack(ByVal ar As IAsyncResult)

        Dim Cliente As StateObject = CType(ar.AsyncState, StateObject)

        If Clientes.ContainsKey(Cliente.IndexCli) Then
            If GetState(Cliente.IndexCli) <> States.Closed Then ChangeState(Cliente.IndexCli, States.Deleted)

            RaiseEvent Disconnected(Cliente.IndexCli)

            SyncLock Me
                'Elimino el cliente de la colecion.
                Clientes.Remove(Cliente.IndexCli)
            End SyncLock
        End If

        If CloseAllSockets = True Then
            If Clientes.Count = 0 Then
                CloseAllSockets = False
                'Cambio el estado del listener.
                ChangeState(0, States.Closed)

                'Cierro el socket que escucha.
                Listener.Close()

                'Genero el evento disconnected de listener
                RaiseEvent Disconnected(0)
            End If
        End If
    End Sub 'CloseCallBack

#End Region

#Region " ENUM "

    Public Enum States
        Closed = 0
        Deleted = 1
        Listening = 2
        Sending = 3

        Connecting = 6
        Connected = 7
        Closing = 8
        [Error] = 9

    End Enum

#End Region

End Class
الرد }}}
تم الشكر بواسطة:



التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم