2009-05-22 21 views
11

Para un proyecto en la escuela, estamos creando un servidor multiproceso en Java 5.0. Este proyecto se centra en el aspecto de concurrencia de un servidor.Java: ¿ServerSocket.accept es seguro?

Tenemos algunos hilos dedicados a tratar las solicitudes. Para hacerlo, tienen una llamada a un ServerSocket.accept() para aceptar nuevas conexiones. Nuestra elección fue comenzar un montón de ellos y dejarlos tratar las conexiones entrantes con la suposición de que dos hilos no pueden aceptar() la misma conexión al mismo tiempo.

Pero ahora el problema principal es que no podemos encontrar nada en la API que nos garantice este comportamiento (o que no parezcamos correcto) y no tenemos nada excepto la prueba "funciona".

¿Alguien tiene una fuente para buscar este tipo de información sobre los métodos de Java?

+0

Sabemos que este diseño no es realmente bueno y ya lo hemos cambiado para usar un conjunto de hilos de trabajo. Ahora solo tenemos un hilo que acepta y envía las solicitudes a los hilos de trabajo. Todavía sabría si hay información en algún lugar sobre la seguridad de subprocesos de los métodos de Java. –

Respuesta

25

Respuesta corta: si la documentación no especifica que algo es seguro para subprocesos, entonces usted debe asumir que no lo es. Debe coordinar usted mismo los hilos para asegurarse de que no haya dos hilos que utilicen el socket del servidor al mismo tiempo.

Esto es especialmente importante porque algún otro código podría haber registrado su propia implementación de socket con ServerSocket.setSocketFactory. Incluso si la implementación de socket predeterminada es segura para subprocesos, las implementaciones personalizadas no tienen que serlo. No hay nada en la documentación que lo diga.

Respuesta larga: el valor predeterminado de Windows Implementación

Puede descargar e inspeccionar el java SE 1.6 source code.

Empecé en \j2se\src\share\classes\java\net\ServerSocket.java y desde allí el sendero condujo al PlainSocketImpl.java. El método PlainSocketImpl.Accept está marcado como native.

El código nativo de C++ para Windows está en \j2se\src\windows\native\java\net\PlainSocketImpl.c. Utiliza la función winsock accept. Desde un (énfasis mío) MSDN article on WinSock:

En Windows NT y Windows 2000, Windows Sockets apoyo para aplicaciones de 16 bits se basa en WINSOCK.DLL. Para aplicaciones de 32 bits, el soporte se encuentra en WSOCK32.DLL. Las API proporcionadas son idénticas, excepto que las versiones de 32 bits tienen parámetros ampliados a 32 bits. En Win32, la seguridad de la rosca es suministrada.

Así, al menos, en las ventanas, Socket.Accept es seguro para subprocesos en el sentido de que no permitirá que dos hilos aceptan la misma conexión. También hay infraestructura en la implementación ServerSocket (e.gramo. el método Close() usa un bloqueo) que indica que está destinado a ser seguro para subprocesos.

+2

+1 para la respuesta detallada, bien investigada – talonx

+0

de nuevo +1 para esta gran respuesta – Kartoch

8

Esto no responde completamente a su pregunta, pero al ejecutar accept() en varios hilos suena como que hay algo mal con el diseño del servidor.

Normalmente no debería haber necesidad de ejecutar accept() desde múltiples hilos.

el código debe ve algo como esto:

while (serverIsUpAndRunning()) 
{ 
    // Wait for an incoming connection. 
    Socket s = serverSocket.accept(); 
    // Spawn a thread to handle the socket, 
    // so that we don't block new connections. 
    SocketHandlerThread t = new SocketHandlerThread(s); 
    t.start(); 
} 
+0

Cada hilo de trabajador que acepta su propia conexión es un diseño perfectamente válido. Se beneficia al no tener que pasar a otros hilos. –

+1

¿Estás pensando en un grupo de subprocesos fijo donde cada subproceso compite por el accept()? Eso es sin duda una inversión de la propiedad de hilo habitual. Debo admitir que no puedo ver cómo "el costo de la entrega" a un nuevo hilo (o uno de un hilo) justificaría la complejidad en la mayoría de los casos. ¿Hay algún ejemplo en que este tipo de diseño sea práctico? – Nuoji

+3

Lo que es más importante, Java * NO * garantiza la seguridad de la ejecución de subprocesos: el hecho de que la API nativa subyacente lo haga en Windows (según lo citado por la respuesta aceptada) no tiene sentido. –