Maison  >  Article  >  Java  >  Notes d'étude Tomcat (1) Un serveur Web simple

Notes d'étude Tomcat (1) Un serveur Web simple

PHP中文网
PHP中文网original
2017-07-07 18:12:481027parcourir
Le contenu comprend les points clés du premier chapitre de "Analyse approfondie de Tomcat", ainsi que mon propre résumé. Si la description n'est pas claire, vous pouvez consulter le livre original.
1. Protocole HTTP :
1. Définition : Protocole utilisé pour la communication entre les serveurs et les clients, permettant aux serveurs Web et aux navigateurs d'envoyer et de recevoir des données sur Internet. Il s'agit d'un protocole de requête et de réponse qui utilise le protocole TCP fiable. Le port du protocole TCP est 80 et est un protocole orienté connexion.
2. Trois composants de la requête du protocole HTTP : Ces trois parties sont séparées par un retour chariot et un saut de ligne (CRLF)
Partie requête : Méthode (7 types dont GET/POST, d'autres sont rarement utilisés et sont introduits dans le livre) [espace, cette partie du contenu est séparée par des espaces] Uniform Resource Identifier URI [espace, cette partie du contenu le contenu est séparé par des espaces] protocole/version du protocole
Les URL sont généralement relatives au répertoire racine du serveur, elles commencent donc par "/".
En-tête de requête : l'en-tête de requête contient des informations utiles sur l'environnement client et le contenu du corps de la requête. Par exemple, cela peut inclure la langue des paramètres du navigateur, la longueur du contenu principal, etc. Chaque en-tête est séparé par un caractère CRLF (retour chariot).
Contenu du corps de la requête : Pour le format de requête HTTP, il est très important d'avoir un saut de ligne de retour chariot (CRLF) entre l'en-tête et le contenu du corps. CRLF indique au serveur HTTP où commence le contenu du corps. Dans certains livres de programmation Internet, CRLF est également considéré comme la quatrième partie des requêtes HTTP.
3. La réponse HTTP comprend également trois parties :
·Méthode—Identificateur de ressource uniforme (URI)—Protocole/Version
· En-têtes de réponse
· Contenu principal
2. Communication entre serveur et client
1. La communication entre le serveur et le client nécessite deux parties : Socket (client) et ServerSocket (serveur)
(1) ServerSocket (java.net.ServerSocket, socket côté serveur), pour créer un socket serveur, vous devez utiliser l'une des quatre méthodes de construction fournies par la classe ServerSocket. Vous devez spécifier l'adresse IP et le numéro de port sur lesquels le socket serveur écoutera. Généralement, l'adresse IP sera 127.0.0.1, ce qui signifie que le socket du serveur écoutera sur la machine locale. L'adresse IP sur laquelle le socket serveur écoute est appelée adresse de liaison. Un autre attribut important du socket serveur est le backlog, qui correspond à la longueur maximale de la file d'attente des demandes de connexion entrantes avant que le socket serveur ne commence à rejeter les demandes entrantes. Les quatre méthodes de construction sont :
.
ServerSocket ss = new ServerSocket();//Créer un ServerSocket non lié
ServerSocket ss = new ServerSocket(int port);//Créer un ServerSocket lié à un certain port
ServerSocket ss = new ServerSocket(int port, int log);//Créez un ServerSocket lié à un certain port et définissez la longueur maximale de la file d'attente.
ServerSocket ss = new ServerSocket(int port, int log, InetAddress address);//Créez un ServerSocket lié à une certaine adresse et un certain port, et définissez la longueur maximale de la file d'attente.
Pour le quatrième constructeur, l'adresse de liaison doit être une instance d'InetAddress. Un moyen simple de construire un objet InetAddress consiste à appeler sa méthode statique getByName, en passant une chaîne contenant le nom d'hôte, comme ci-dessous. Le code est le même. .
InetAddress.getByName("127.0.0.1");
Méthodes courantes pour créer ServerSocket :
new ServerSocket(8080, 1, InetAddress.getByName("127.0.0.1"));
Le code construit un ServletSocket qui écoute le port 8080 de la machine locale et sa longueur de file d'attente est de 1.
Une fois le serveur créé, il reste dans un état d'attente (le protocole TCP, un protocole de transmission fiable, est un protocole synchrone, c'est-à-dire qu'il attendra qu'il n'y ait pas de réponse)
(2) Socket (classe java.net.Socket, socket client) : vous devez connaître le nom IP/hôte et le numéro de port du serveur auquel vous souhaitez accéder, et vous pouvez envoyer une requête au serveur. Vous pouvez utiliser l'une des nombreuses méthodes de construction de Socket pour créer un Socket
nouveau Socket ("yahoo.com", 80);
Une fois que vous avez créé avec succès une instance de la classe Socket, vous pouvez l'utiliser pour envoyer et recevoir des flux d'octets. Pour envoyer un flux d'octets, vous devez d'abord appeler la méthode getOutputStream de la classe Socket pour obtenir un objet java.io.OutputStream. Pour envoyer du texte à une application distante, vous construisez souvent un objet java.io.PrintWriter à partir de l'objet OutputStream renvoyé. Pour recevoir un flux d'octets de l'autre extrémité de la connexion, vous pouvez appeler la méthode getInputStream de la classe Socket pour renvoyer un objet java.io.InputStream.
(3) Le serveur reçoit la demande de connexion du client via la méthode accept(), établit une connexion avec le client et renvoie un Socket
Prise s = ss accepter();
(4) Un flux d'entrée et un flux de sortie peuvent être obtenus via Socket. Le flux d'entrée est utilisé pour lire les données de la demande du client et le flux de sortie est utilisé pour renvoyer les informations de réponse au client.
Par exemple : InputStream input = s.getInputStream();
Sortie OutputStream = s.getOutputStream();
3. Exemple de communication simple avec un serveur Web (il est recommandé de le copier sur MyEclipse pour le visualiser et l'exécuter)
1. Classe de serveur
package com.socket.httpservertest;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class HttpServer {
     public static final String WEB_ROOT = System.getProperty("user.dir") + File.separator + "webroot";
     // shutdown command
     private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";
     // the shutdown command received
     private boolean shutdown = false;
     public static void main(String[] args)
     {
           HttpServer server = new HttpServer();
           server.await();
           
     }
     public void await() {
     //   System.out.println(System.getProperty("user.dir"));
           ServerSocket serverSocket = null;
           int port = 8080;
           try {
                serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
           } catch (IOException e) {
                e.printStackTrace();
                System.exit(1);
           }
           while (!shutdown) {
                Socket socket = null;
                InputStream input = null;
                OutputStream output = null;
                try {
                     //接收了客户端发来的请求,否则一致是等待状态
                     socket = serverSocket.accept();
                     input = socket.getInputStream();
                     output = socket.getOutputStream();
                     // create Request object and parse
                     Request request = new Request(input);
                     request.parse(); //从请求中读取内容
                     // create Response object
                     Response response = new Response(output);
                     response.setRequest(request);
                     response.sendStaticResource();
                     // Close the socket
                     socket.close();
                     //check if the previous URI is a shutdown command
                     shutdown = request.getUri().equals(SHUTDOWN_COMMAND);
                }catch (Exception e)
                {
                     e.printStackTrace ();
                     continue;
                }
           }
    }
}
2. Demander un cours
package com.socket.httpservertest;
import java.io.IOException;
import java.io.InputStream;
public class Request {
     private InputStream input;
     private String uri;
     public Request(InputStream input)
     {
           this.input = input;
     }
     
     public void parse() {
           // Read a set of characters from the socket
           StringBuffer request = new StringBuffer(2048);
           int i;
           byte[] buffer = new byte[2048];
           try {
                i = input.read(buffer); //将从输入流取2048长度的内容存到buffer字节数组中,如果内容不到2048,数组其他空间剩余空着
           } catch (IOException e) {
                e.printStackTrace();
                i = -1;
           }
           
           for (int j=0; j<i; j++)
           {
                request.append((char) buffer[j]);
           }
           System.out.print(request.toString());
           uri = parseUri(request.toString());
     }
     
     private String parseUri(String requestString) {
           int index1, index2;
           index1 = requestString.indexOf(' ');
           /*
            * http请求行的结构:方法 统一资源标识符(URI) 协议/版本(它们之间以空格分隔)
            * 例如:POST //examples/default.jsp HTTP/1.1
            */
           if (index1 != -1) {// index1 == -1表示没找到
                     index2 = requestString.indexOf(' ', index1 + 1);//从index+1位置开始寻找‘ ’
                     if (index2 > index1)
                     return requestString.substring(index1 + 1, index2);
                }
           return null;
     }
     
     public String getUri()
     {
           return uri;
     }
}
3. Classe de réponse
package com.socket.httpservertest;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Response {
     private static final int BUFFER_SIZE = 1024;
     Request request;
     OutputStream output;
     public Response(OutputStream output) {
           this.output = output;
     }
     public void setRequest(Request request) {
           this.request = request;
     }
     
     public void sendStaticResource() throws IOException {
           byte[] bytes = new byte[BUFFER_SIZE];
           FileInputStream fis = null;
           try {
                File file = new File(HttpServer.WEB_ROOT, request.getUri());
                if (file.exists()) {
                     fis = new FileInputStream(file);
                     int ch = fis.read(bytes, 0, BUFFER_SIZE);
                     while (ch!=-1) { //ch==-1表示读到末尾了
                           output.write(bytes, 0, ch); //写出到浏览器
                           ch = fis.read(bytes, 0, BUFFER_SIZE);//再读会接上一次读的位置往下读,如果读到末尾就会返回-1,终止输出
                     }
                } else {
                     // file not found
                     String errorMessage = "HTTP/1.1 404 File Not Found\r\n" + "Content-Type: text/html\r\n" + "Content-Length: 23\r\n" + "\r\n" + "<h1>File Not Found</h1>";
                     output.write(errorMessage.getBytes());
                }
           }catch (Exception e) {
                // thrown if cannot instantiate a File object
                System.out.println(e.toString() );
           } finally {
                if (fis!=null)
                     fis.close();
           }
     }
}
4. Exemple de description de la fonction de code : le navigateur saisit une requête http, telle que http://localhost:8080/MyHtml.html ; après avoir reçu la requête, le serveur utilise le flux d'entrée pour lire le contenu de la requête afin d'obtenir le emplacement du fichier, puis utilise le flux d'entrée du fichier pour lire Obtenez le contenu du fichier ; renvoie enfin une réponse au client du navigateur et affiche le contenu dans le fichier html sur le navigateur, comme indiqué dans la figure :
5. Exemple d'organigramme interfonctionnel de code :

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn