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:35Seguramente 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:59Estas 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:06Si, 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) ThentcpTread.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.ConnectedThreading.Thread.Sleep(5)
True) End While
clisocket.Shutdown(SocketShutdown.Both)
clisocket.Disconnect(clisocket.Close()
Nothing End If End If
GC.SuppressFinalize(clisocket)
clisocket = -
martes, 17 de marzo de 2009 22:18puedes 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
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 Nothing) Then 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 String, ByVal HostPort As Integer, ByVal tespera As Integer) As 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 Nothing) Then 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

