Unanswered Puertos efímeros en vista

  • martes, 17 de marzo de 2009 10:03
     
     

    Hola:

    Estoy haciendo una aplicación cliente-servidor en VB 2008 que necesita realizar un sondeo a muchos clientes en poco tiempo, de modo que se consumen todos los puertos y no me deja reutilizarlos pese a que están cerrados (lo he analizado con netstat).

    El socket se cierra mediante las órdenes shutdown, disconnect y close y admito el uso compartido de puertos mediante la orden socket.setsocketoption(socket, reuseadress,1). También he hecho una subrutina que libera memoria y los recursos del socket.

    He habilitado el uso compartido de puertos net.tcp en Vista.

    El programa le he probado en Windows XP y reutiliza los puertos perfectamente.

    ¿ Sabe alguien dónde puede estar el el problema?

    Muchas gracias.

Todas las respuestas

  • martes, 17 de marzo de 2009 13:35
     
     
    Seguramente tu aplicacion requiere ejecutarse con ciertos privilegios dado el nivel de seguridad de windows vista.

    ya trataste de ejecutarla elvando privilegios? es decir click derecho ejecutar como administrador?
    Juan Carlos Ruiz - http://juank.black-byte.com
  • martes, 17 de marzo de 2009 13:57
     
     

    Ante todo gracias por responder.

    Si, he probado a ejecutarla con privilegios de administrador y nada. Una vez consumidos todos los puertos la aplicación no es capaz reutilizar ninguno de los anteriores, provocandose el error 10055 (WSAENDBUFF): "No se puede ejecutar la operación en un socket ya que el sistema no tiene suficiente espacio de búfer o porque una cola estaba llena"

    Un saludo 

  • martes, 17 de marzo de 2009 13:59
     
     
    Estas cerrando los socket SIEMPRE? sino los cierras... el sistema no los cerrara por ti.

    Recuerda que incluso en las excepciones debes cerrarlo, una buena practica es en los eventos de cierre de la aplicación introducir código que valide el estado del socket y lo cierre.

    Juan Carlos Ruiz - http://juank.black-byte.com
  • martes, 17 de marzo de 2009 14:06
     
     
     Si, el cierre del socket es perfecto, o eso parece, ya que herramientas de análisis de tramas, como el netstat o el wiresark, así lo confirman. Otro aspecto será en como maneje Vista los puertos. Te adjunto el código de desconexión:

    '**********************************************
    ' RUTINA PARA CERRAR EL THREAD DEL CLIENTE
    '**********************************************

    If Not (tcpTread Is Nothing) Then
        If (tcpTread.IsAlive) Then

        tcpTread.Abort()

        End If
    End If

    If Not (clisocket Is Nothing) Then

         If clisocket.Connected Then

    '  Espera a que el cliente se haya deconectado

    While clisocket.Connected

        Threading.Thread.Sleep(5)
        clisocket.Shutdown(SocketShutdown.Both)
        clisocket.Disconnect(
    True)

    End While

    clisocket.Close()
    GC.SuppressFinalize(clisocket)
    clisocket =
    Nothing

    End If

    End If


  • martes, 17 de marzo de 2009 22:18
     
     
    puedes pasarme plz un poco mas de codigo?
     es decir en que funciono evento estas? cuando se disopara ese codigo?
    Juan Carlos Ruiz - http://juank.black-byte.com
  • miércoles, 18 de marzo de 2009 8:21
     
      Tiene código
     Gracias por responder.


    El código anterior se dispara mediannte la orden winsockcliente.Cerrar() que puedes ver en el fragemneto de programa inferior. El objetivo de esta subrutina es comprobar que un cliente (una línea de producción) está ejecutando el programa para monitorizar la línea, para lo que establece una conexión TCP al puerto 8051 del cliente, en donde se está esperando una transmisión mediante un TCP listener. Esta intento de conexión se hace mediante el código que ves debajo de la rutina de sondeo, donde se permite tan sólo un segundo para la conexión mediante un baginconnect.

    1  Private Sub sondeo()  
    2  
    3         Dim conexion As Boolean         ' Indica si se ha podido realizar una conexión al cliente remoto  
    4         Dim sqlser As Boolean 
    5         Dim nlin As Integer = 3  
    6         Dim linea(3) As String 
    7         Dim host(3) As String 
    8         Dim cont As Integer = 1  
    9  
    10         linea(0) = "1221" 
    11         linea(1) = "1227" 
    12         linea(2) = "1217" 
    13  
    14         host(0) = "Delfin" 
    15         host(1) = "Perdiz" 
    16         host(2) = "Jaguar" 
    17  
    18  
    19         While True 
    20  
    21             Try 
    22  
    23                 For cont = 0 To nlin - 1  
    24                     ' Intenta una conexión al cliente por le puesto 8050 y espera 1 segundo para dar por inalcanzable el host  
    25                     conexion = winsockcliente.Conectar(host(cont), 8051, 1000)  
    26  
    27                     If conexion Then 
    28                         winsockcliente.EnviarDatos("fin")  
    29                         winsockcliente.Cerrar()  
    30                         Compartido.ClearMemory()  
    31                         GC.SuppressFinalize(winsockcliente)  
    32  
    33                         If (EstadoIndicador(linea(cont)) = Color.Black) Then 
    34                             ' Realiza una consulat SQL al servidor  
    35                             If (initCon(strcon)) Then 
    36                                 ColIndicador(linea(cont), "Peor")  
    37                                 closeCon()  
    38                             End If 
    39                         End If 
    40  
    41                     Else 
    42                         ' Encuentra el semáforo asignado a esa línea y cambia su color  
    43                         ColIndicador(linea(cont), "Negro")  
    44                     End If 
    45  
    46                 Next 
    47    
    48             Catch ex As ThreadAbortException  
    49                 If Not (winsockcliente Is NothingThen 
    50                     winsockcliente.Cerrar()  
    51                     winsockcliente = Nothing 
    52                 End If 
    53                 Exit While 
    54    
    55             Catch ex As Exception  
    56                 MsgBox(ex.Message)  
    57             Finally 
    58  
    59             End Try 
    60  
    61         End While 
    62  
    63     End Sub 




    1 Public Function Conectar(ByVal HostIP As StringByVal HostPort As IntegerByVal tespera As IntegerAs Boolean 
    2  
    3         '*****************************************************  
    4         'RUTINA PARA CONECTAR EL CLIENTE Y EL SERVIDOR  
    5         '*****************************************************  
    6         Try 
    7               
    8             'Define un Timeout igual (por defecto más de 20)  
    9             UserTimeoutTime.Enabled = False 
    10             UserTimeoutTime.Interval = tespera  
    11             UserTimeoutTime.Enabled = True 
    12             UserTimeoutTime.Start()  
    13  
    14             Conectar = False 
    15  
    16             ' Resulve la dirección IP mediante una solicitud al servidor DNS  
    17             lipa = Net.Dns.Resolve(HostIP)  
    18             lep = New Net.IPEndPoint(lipa.AddressList(0), HostPort)  
    19  
    20             clisocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) 'Socket cliente  
    21             clisocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, True)  
    22             clisocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse, False)  
    23             'clisocket.Blocking = False  
    24             'Dim bindaddress As New Net.IPEndPoint(Net.IPAddress.Parse("193.144.201.74"), 0)  
    25             'If Not (clisocket.IsBound) Then  
    26             'clisocket.Bind(bindaddress)  
    27             'End If  
    28  
    29             clisocket.BeginConnect(lep.Address, lep.Port, New AsyncCallback(AddressOf ConnectionReturned), clntSockParams)  
    30  
    31  
    32             'Espera que la conexión se produzca con éxito - Comportamiento síncrono  
    33             Do While UserTimeoutTime.Enabled  
    34                 System.Threading.Thread.Sleep(tespera)  
    35             Loop 
    36  
    37             'En caso de Time out, saca un mensaje de error  
    38             If Not (clisocket Is NothingThen 
    39                 If clisocket.Connected Then 
    40                     Conectar = True 
    41                  End If 
    42             End If 
    43  
    44         Catch ex As SocketException  
    45             Conectar = False 
    46         Catch ex As Exception  
    47             'Mensaje de error  
    48             'MessageBox.Show(ex.Message)  
    49         End Try 
    50  
    51     End Function 
    52