Publié le 23/07/2013
Auteur Fobec
Réseaux sociaux
0 partages
0 tweets
2 plus
0 commentaires

Communiquer directement avec un socket

Tous les échanges sur un réseau passe par une connexion à un socket. Par exemple, le chargement d'une page internet nécessite l'ouverture d'un socket, l'envoi de requête puis la réception du code HTML.
La plupart de ces opérations sont invisibles pour l'internautes, voire même pour le développeur. Par contre il peut être utile de savoir ce qui se cache derrière les communications entre un client et un serveur.

Envoi et reception de données avec la Class HttpRawSocket

Contrairement à HttpURLConnection, la class est un wrapper minimaliste de l'objet JAVA socket. Les fonctions implémentées servent à couvrir les requêtes courantes:
- connect(): se connecter puis receptionner la réponse,
- setUserAgent(): fixer le UserAgent, car certains serveurs bloquent s'il n'est pas défini,
- setEncoding(): demander la compression gzip de la page,
- getHeader(): retourne l'entete de la page HTML,
- getHtml(): retourne le code source de la page.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
 
/**
 * Communiquer directement avec un socket
 * @author Fobec 2013
 * @see http://www.fobec.com/java/1130/communiquer-directement-avec-socket.html
 */
public class HttpRawSocket {
 
    private String request = ""; //commande envoye
    private String header=""; //reponse header
    private String html=""; //reponse html
    private String ua = null; //user agent
    private boolean gzip=false; //compression demande
 
    /**
     * Ouvrir un socket et envoyer une commande
     * @param aURL
     * @throws MalformedURLException
     * @throws IOException 
     */
    public void connect(String aURL) throws MalformedURLException, IOException {
        Socket socket = new Socket();
        URL url = new URL(aURL);
        socket.connect(new InetSocketAddress(url.getHost(), 80));
        try {
            InputStreamReader inputreader=new InputStreamReader(socket.getInputStream());
            BufferedReader reader = new BufferedReader(inputreader);
            PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
            //envoyer la requete
            this.request=this.buildCommand(url);
            writer.println(this.request);
            //receptionner la réponse
            String line;
            StringBuilder sb = new StringBuilder();
            while ((line = reader.readLine()) != null) {
                sb.append(line).append(System.getProperty("line.separator"));
            }
            //Séparer le header du code html
            String response = sb.toString();
            String tag=System.getProperty("line.separator")+System.getProperty("line.separator");
            int idx=response.indexOf(tag);       
            this.header = response.substring(0,idx);
            this.html = response.substring(idx+1);
        } finally {
            socket.close();
        }
    }
 
    /**
     * Fixer le UserAgent
     * @param useragent 
     */
    public void setUserAgent(String useragent) {
        this.ua = useragent;
    }
    //Fixer la compression
    public void setEncoding(boolean acceptGzip) {
        this.gzip = acceptGzip;
    }
    //Retourner la requete envoyé au serveur
    public String getRequest() {
        return this.request;
    }
    //Retourner le header de la réponse
    public String getHeader() {
        return this.header;
    }
    //retourner le code html
    public String getHtml() {
        return this.html;
    }
    /**
     * Assembler la requete à envoyer au serveur
     * @param url
     * @return 
     */
    private String buildCommand(URL url) {
        String cmd = "GET " + url.getPath() + " HTTP/1.1rn";
        cmd += "Host: " + url.getHost() + "rn";
        if (this.ua != null) {
            cmd += "User-Agent: "+this.ua+"rn";
        }
        if (this.gzip == true) {
            cmd += "Accept-Encoding: gzip, deflatern";
        }
 
        //Close
        cmd+="rn";        
 
        return cmd;
    }
}

Charger une page internet avec les sockets

Au delà de l'aspect pédagogique, la class a pour but de charger rapidement des pages HTML en recueillant le maximum d'information sur la communication avec le serveur web. Pour l'exemple, nous allons nous connecter au serveur d'Ubuntu.org et charger la page HTML de téléchargement de ubuntu.
public class HttpRawSocket {
 
    public static void main(String[] args) {
        HttpRawSocket httpSocket = new HttpRawSocket();
        try {
            httpSocket.setUserAgent("Exemple java de Fobec.com");
            httpSocket.connect("http://ubuntu-fr.org/telechargement");
 
            System.out.println(httpSocket.getRequest());
            System.out.println(httpSocket.getHeader());
            System.out.println(httpSocket.getHtml());
        } catch (MalformedURLException ex) {
            Logger.getLogger(HttpRawSocket.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(HttpRawSocket.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

La requête envoyée au serveur
GET /telechargement HTTP/1.1
Host: ubuntu-fr.org
User-Agent: Exemple java de Fobec.com

La commande GET indique que l'on souhaite receptionner des données. Pour l'envoi d'un formulaire, nous aurions utiliser un POST.

L'entête de la réponse
HTTP/1.0 200 OK
Server: nginx
Content-Type: text/html; charset=utf-8
Expires: Sun, 19 Nov 1978 05:00:00 GMT
Last-Modified: Tue, 23 Jul 2013 15:05:15 +0000
ETag: "1374591915"
Content-Language: en
X-Generator: Drupal 7 (http://drupal.org)
Link: </telechargement>; rel="canonical",</node/14>; rel="shortlink"
Content-Length: 13978
Date: Tue, 23 Jul 2013 15:05:15 GMT
Age: 0
Cache-Control: no-cache, must-revalidate, max-age=0
Pragma: no-cache
X-Cache: MISS from ipcop.localdomain
Via: 1.0 ipcop.localdomain:800 (squid/2.6.STABLE21)
Connection: close

Le plus important est la mention 200 tout s'est bien passé !!!

Le code HTML renvoyé
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN"
"http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" version="XHTML+RDFa 1.0" dir="ltr"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:dc="http://purl.org/dc/terms/"
xmlns:foaf="http://xmlns.com/foaf/0.1/"
xmlns:og="http://ogp.me/ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:sioc="http://rdfs.org/sioc/ns#"
xmlns:sioct="http://rdfs.org/sioc/types#"
xmlns:skos="http://www.w3.org/2004/02/skos/core#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#">

<head profile="http://www.w3.org/1999/xhtml/vocab">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

....

Voici le code HTML qui sera affiché dans un navigateur internet par exemple.

Optimiser et sécuriser la communication avec un socket

Le but de la class est de communiquer rapidement et facilement avec un serveur web au travers d'un socket. En production sur des taches automatiques, il faudrait en premier lieu traiter les erreurs de communication avec le serveur, à savoir les erreurs de connexion, les Time-out ou encore la reception partielle du code HTML.

Ajouter un commentaire

Les champs marqués d'un * sont obligatoires, les adresses emails se sont pas publiées.

A lire aussi

Réseaux sociaux
Présentation de l'article
Catégorie
java - class
Mise a jour
23/07/2013
Visualisation
vu 3491 fois
Public
Internaute
Auteur de la publication
Fobec
Admin
Auteur de 261 articles
|BIO_PSEUDO|
Commentaires récents

Publié par web agency cms Typo3 dans tuto

De nombreux articles sur le web parlent des CMS (Content Management System) et tentent de lister les meilleurs d'entres-eux.
Mais très souvent, sauf quelques rares libres blancs, ces article...

Publié par Julie dans logiciel

C'est donc un moteur de recherche specialise. On peut vraiment rechercher tous les domaines que l'on veut. Cela permettrait aux gens de ne plus se faire arnaquer. Quelle bonne idee!

Publié par hilflo dans tuto

Tres bon article qui montre bien les subtilites des mutualises de 1and1.
Je l'ai utilise pour un de mes sites en y ajoutant de l'url rewriting pour eviter d'avoir des parametres dans l'url avec cet...

Publié par Celibataire dans news

Le trustrant est pas clair du tout peu d'informations sont disponibles sur lui!

Publié par nabil23 dans CMS

j\'arrive pas e telecharger les icons