Un servidor Http simple con Java / Socket?

Actualmente estoy creando un pequeño servidor HTTP que devuelve una página estática

Hello!

… Intenté con sockets con Java:

  public static void main(String[] args) throws Exception { // création de la socket int port = 1989; ServerSocket serverSocket = new ServerSocket(port); System.err.println("Serveur lancé sur le port : " + port); // repeatedly wait for connections, and process while (true) { // on reste bloqué sur l'attente d'une demande client Socket clientSocket = serverSocket.accept(); System.err.println("Nouveau client connecté"); // on ouvre un flux de converation BufferedReader in = new BufferedReader( new InputStreamReader(clientSocket.getInputStream()) ); PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(clientSocket.getOutputStream())), true); // chaque fois qu'une donnée est lue sur le réseau on la renvoi sur le flux d'écriture. // la donnée lue est donc retournée exactement au même client. String s; while ((s = in.readLine()) != null) { System.out.println(s); out.write("HTTP/1.0 200 OK\r\n"); out.write("Date: Fri, 31 Dec 1999 23:59:59 GMT\r\n"); out.write("Server: Apache/0.8.4\r\n"); out.write("Content-Type: text/html\r\n"); out.write("Content-Length: 59\r\n"); out.write("Expires: Sat, 01 Jan 2000 00:59:59 GMT\r\n"); out.write("Last-modified: Fri, 09 Aug 1996 14:21:40 GMT\r\n"); out.write("\r\n"); out.write("Exemple"); out.write("

Ceci est une page d'exemple.

"); } // on ferme les flux. System.err.println("Connexion avec le client terminée"); out.close(); in.close(); clientSocket.close(); } }

este código no contiene ningún error y recibí una respuesta del navegador como esta:

 GET / HTTP/1.1 Host: localhost:1989 Connection: keep-alive User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.46 Safari/536.5 Comodo_Dragon/19.0.3.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Encoding: gzip,deflate,sdch Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 

¿Pero mi problema es que no obtengo ninguna página en el navegador? ¿Alguna ayuda, por favor?

PD: Ya leí este artículo: http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol , (lo siento por el idioma francés …)

Además del \ r \ n después de cada línea de encabezado de solicitud, debe enviar una línea vacía después del encabezado. Ejemplo:

 out.write("HTTP/1.0 200 OK\r\n"); // Header... out.write("Last-modified: Fri, 09 Aug 1996 14:21:40 GMT\r\n"); out.write("\r\n"); // The content starts afters this empty line out.write("Hello!"); // Content... 

Corregí tu código para que funcione (pero aún no es perfecto, debes manejar cada solicitud en un hilo separado, por ejemplo, con java.util.concurrent.ThreadPoolExecutor):

 public static void main(String[] args) throws Exception { // création de la socket int port = 1989; ServerSocket serverSocket = new ServerSocket(port); System.err.println("Serveur lancé sur le port : " + port); // repeatedly wait for connections, and process while (true) { // on reste bloqué sur l'attente d'une demande client Socket clientSocket = serverSocket.accept(); System.err.println("Nouveau client connecté"); // on ouvre un flux de converation BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); BufferedWriter out = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream())); // chaque fois qu'une donnée est lue sur le réseau on la renvoi sur // le flux d'écriture. // la donnée lue est donc retournée exactement au même client. String s; while ((s = in.readLine()) != null) { System.out.println(s); if (s.isEmpty()) { break; } } out.write("HTTP/1.0 200 OK\r\n"); out.write("Date: Fri, 31 Dec 1999 23:59:59 GMT\r\n"); out.write("Server: Apache/0.8.4\r\n"); out.write("Content-Type: text/html\r\n"); out.write("Content-Length: 59\r\n"); out.write("Expires: Sat, 01 Jan 2000 00:59:59 GMT\r\n"); out.write("Last-modified: Fri, 09 Aug 1996 14:21:40 GMT\r\n"); out.write("\r\n"); out.write("Exemple"); out.write("

Ceci est une page d'exemple.

"); // on ferme les flux. System.err.println("Connexion avec le client terminée"); out.close(); in.close(); clientSocket.close(); } }

Esta es una respuesta a su última pregunta solamente y la razón por la que no hay nada visible en el navegador se debe a que calculó el número de caracteres incorrectamente.

Debería ser 57 en lugar de 59.

Mejor aún es tener el número de caracteres calculado automáticamente, pero creo que su muestra es solo una muestra.

¿Qué máquina estás usando? ¿Qué sistema operativo? Si está ejecutando una máquina UNIX, println no funcionará porque solo envía un carácter LF. HTTP requiere CR y LF para sus encabezados. Intente agregar \ r al final de sus cadenas y vea si eso funciona.

Oh, también, tu:

  out.println("HTTP/1.0 200 OK"+ "Date: Fri, 31 Dec 1999 23:59:59 GMT"+ "Server: Apache/0.8.4"+ "Content-Type: text/html"+ "Content-Length: 59"+ "Expires: Sat, 01 Jan 2000 00:59:59 GMT"+ "Last-modified: Fri, 09 Aug 1996 14:21:40 GMT"+ 

Está imprimiendo una sola cadena larga.

Cámbielos a una lista de impresión para cada cadena, o agregue \ r \ n a la cadena.

Necesita los separadores de línea correctos ( \r\n ) entre cada salida de línea. No es suficiente concatenarlos, lo cual puede ver si imprime la respuesta.

Solo un recordatorio: este no es un servidor HTTP, como sugeriría el título. Es un socket que escribe una respuesta HTTP codificada específica (suponiendo que se corrige según las sugerencias en las otras respuestas). Incluso si cambió el contenido devuelto y el encabezado de longitud de contenido de forma dinámica, aún no es suficiente para cumplir con el protocolo HTTP.

Como aprendí por las malas mientras escribía JLHTTP , hay mucho más en HTTP que eso. No es que sea muy complicado, sino que hay muchos detalles y requisitos adicionales que deben manejarse adecuadamente. Puede leer los RFC (el protocolo central se define en RFC 7230, o el RFC 2616 anterior) para obtener más información sobre lo que esto implica.

También puedo ofrecer el código fuente JLHTTP como referencia para una implementación bien documentada y mínimamente compatible de un servidor HTTP: es un archivo, actualmente ~ 3K líneas de las cuales casi la mitad son documentación. Su objective es ser pequeño, pero obediente. Creo que mirar el código puede ser útil para cualquiera que quiera saber qué tiene que hacer un servidor HTTP. Como dije, no es muy complicado, pero tiene muchos pequeños detalles.

En realidad, para ser exactos, JLHTTP no es lo mínimo posible: incluye algunas funciones adicionales útiles, como el manejo de datos de formularios de varias partes para subir archivos o soportar HTTPS, que no son requeridos por el protocolo HTTP en sí. Pero puede extraer fácilmente esas partes (o simplemente omitirlas) y llegar a una implementación del servidor HTTP Java verdaderamente mínima.