MokaByte 65 - Luglio Agosto 2002 

Il mondo java embedded
VI parte
: Il sistema di comunicazione del MIDP
il package javax.microedition.io

di
Marco Tomà
Il MIDP (Mobile Information Device Profile), come più volte detto nei precedenti articoli apparsi su MokaByte, è dedicato al settore dei dispositivi embedded ed in particolare ad apparati wireless come pager, smart-phone, telefoni cellulari, palmari ecc.
Data la tipologia di tali apparati, uno degli aspetti che "stuzzica" maggiormente gli addetti ai lavori è, non tanto la realizzazione di applicazioni stand-alone, quanto la possibilità di utilizzarli come "client estremi", ovvero come dispositivi ultra portabili per l'accesso a reti di telecomunicazione e quindi a sistemi informativi. Inoltre, date le risorse hardware di cui dispongono tali apparati, molte applicazioni possono essere viste solamente in un "ottica client-server", cercando di spostare, il più possibile, il carico computazionale sul lato server (ad esempio si potrebbe implementare un sistema client-server per gestire lo stradario di Firenze. In questo caso il cellulare - client - effettua la richiesta al server e questo invia una mappa contenente la strada richiesta. Inserire l'intero stradario nel cellulare non solo è (può essere) privo di significato, ma spesso non sarebbe possibile a causa della poca memoria e delle caratteristiche dei processori).Va da se, quindi, che trattandosi di dispositivi fortemente "orientati alla connessione", il MIDP non poteva trascurare questo importante aspetto.

Generic Connection Framework
Nell'articolo pubblicato su MokaByte di febbraio, riguardante la configurazione CLDC, abbiamo già accennato alla gestione delle connessioni in J2ME. Abbiamo visto che, data la varietà di dispositivi che possono supportare J2ME e le differenti tipologie di connessione che questi possono avere (porta seriale, USB, rete telefonica cellulare a commutazione di pacchetto o a commutazione di circuito, porta infrarossi, blutooth, ecc.), l'implementazione dei "meccanismi" di comunicazione non viene effettuata a livello di configurazione ma viene lasciata ai profili proprio perché più "legati" alle piattaforme host. Il MIDP si occupa quindi dell'implementazione del cosiddetto Generic Connection Framework.



Figura 1 - Gerarchia delle interfacce di connessione (MIDP).

Si tratta di un insieme di interfacce (le stesse previste dalla configurazione CLDC, più l'HttpConnection introdotta dal MIDP) che rappresentano diversi gradi di astrazione dal particolare tipo di connessione (o di protocollo).
La radice della gerarchia, Connection, costituisce la rappresentazione "più astratta" di connessione stabilendo semplicemente che qualunque tipo di connessione può essere aperta (open(..)) o chiusa con il metodo:

public void close()

(in realtà la connessione viene aperta utilizzando il metodo statico open della classe Connector che vedremo tra breve). Le interfacce InputConnection e OutputConnection sono un'estensione di Connection e rappresentano rispettivamente un flusso in ingresso e un flusso in uscita da un dispositivo di comunicazione. Queste interfacce forniscono i metodi per l'apertura dei flussi di ingresso e uscita dalla connessione:

public InputStream openInputStream()
public DataInputStream openDataInputStream()

per quanto riguarda una connessione in ingresso (InputConnection), mentre per quelle in uscita (OutputConnection) sono previsti metodi analoghi per l'apertura di stream in scrittura:

public OutputStream openOutputStream()
public DataOutputStream openDataOutputStream()

La combinazione di InputConnection e OutputConnection "genera" una nuova interfaccia, StreamConnection, provvista di flussi bidirezionali (input e output stream).
StreamConnection, infatti, non possiede alcun metodo, se non quelli ereditati dalle sue "superinterfacce".
ContentConnection estende direttamente StreamConnection e fornisce tre metodi addizionali:

public String getType()
public String getEncoding()
public long getLength()

per la gestione dei dati (e dei tipi MIME) inviati e ricevuti ( ad esempio se il protocollo utilizzato è l' Http essi ritornano rispettivamente il Content-Type, il Content-Encoding e il Content-Length).
L'interfaccia HttpConnection infine fornisce, come vedremo più avanti, un insieme di metodi per il supporto del protocollo Http.
StreamConnectionNotifier possiede un unico metodo:

public StreamConnection acceptAndOpen()

questo restituisce uno StreamConnection, che rappresenta la "versione server" di un socket per la comunicazione con un client (è simile ad un ServerSocket ).
L'interfaccia DatagramConnection, permette la creazione di datagram per la comunicazione di tipo UDP (User Datagram Protocol). Analizzeremo il supporto alle connessioni di tipo datagram del MIDP più avanti in questo articolo, passando ora ad occuparci del procedimento di apertura di una connessione.

Apertura di una connessione: la classe Connector
Nel package javax.microedition.io, che è il "contenitore" di tutti gli strumenti di connessione troviamo, oltre alle già citate interfacce anche una, peraltro unica, classe "concreta": Connector. Tale classe possiede sette metodi statici che permettono l'apertura effettiva della connessione sulla quale sarà poi possibile collegare gli stream di I/O, per le operazioni di lettura e/o scrittura.
Indipendentemente dal tipo di connessione che si intende utilizzare occorrerà richiamare il metodo (statico) open per poterla utilizzare in lettura e/o scrittura.
Il metodo open prevede tre firme differenti:

public static Connection open(String connectionString)
public static Connection open(String connectionString, int mode)
public static Connection open(String connectionString, int mode, boolean timeouts)

Il parametro connectionString rappresenta la stringa di connessione ed ha un formato particolare che tra breve illustreremo, il valore intero mode indica la modalità di apertura della connessione e può assumere uno dei seguenti valori interi (variabili intere statiche della classe Connector):

  • READ - apertura in sola lettura;
  • WRITE - apertura in sola scrittura;
  • READ_WRITE - apertura sia in lettura che in scrittura (valore di default);

Il booleano timeout, il cui valore di default è false, se impostato a true indica che il metodo può generare eccezioni dovute al timeout del tipo InterruptedIOException.
Per quanto riguarda la connectionString, essa ha una generica forma del tipo:

{protocol}: [{target}] [{parameters}]

  • protocol - indica il tipo di connessione che si vuole attivare (ad esempio: I/O su file, porta seriale, datagram, socket, Http)
  • target - dipende da protocol e, può essere il nome di un file, di una porta seriale, il nome di una porta di comunicazione o il nome di un host.
  • parameters - sono parametri aggiuntivi (opzionali) che forniscono informazioni funzionali per un dato tipo di connessione. Ad esempio la velocità, i bit di start e stop e la parità di una connessione seriale.

Alcuni esempi di stringhe di connessione possono essere:

Connection fileConn = Connector.open("file:/myFile.txt");
Connection serialConn = Connector.open("comm.:0;baudrate=9600");
Connection socketConn = Connector.open("socket://193.0.0.1");
Connection datagramConn = Connector.open("datagram://193.0.0.1:9000");
Connection httpConn = Connector.open("http://www.mokabyte.it");

Per l'apertura di una connessione si può, in alternativa all'utilizzo del metodo open, ricorrere ai metodi:

public static DataInputStream openDataInputStream(String connectionString)
public static InputStream openInputStream(String connectionString)
public static DataOutputStream openDataOutputStream(String connectionString)
public static OutputStream openOutputStream(String connectionString)

che ritornano stream di input/output associati alla connessione indicata da connectionString. Essi permettono di ottenere immediatamente uno stream di I/O per una data connessione, ad esempio, l'istruzione:

DataInputStream in = Connector.openDataInputStream("socket://193.0.0.1:8080");

è equivalente al seguente codice:

InputConnection inConnection =(InputConnection ) Connector.open("socket://193.0.0.1:8080");
DataInputStream in = inConnection. OpenDataInputStream();


Le operazioni di apertura di una connessione possono generare eccezioni; in particolare se la connectionString passata ad un "metodo di apertura" non è ben formata si avrà una IllegalArgumentException, mentre se essa indica un tipo di protocollo non supportato verrà generata una ConnectionNotFoundException. Una eccezione di tipo IOException, infine, sta ad indicare che si è verificato un qualche errore di I/O.

 

Connessioni di tipo datagram
La comunicazione datagram si basa sull'invio in rete di "messaggi" (i datagram, appunto), senza garanzie sull'integrità dei dati giunti al destinatario, sull'istante di arrivo e neppure sulla consegna dei dati stessi. Si tratta di una tecnica di comunicazione di tipo non-connesso, nel senso che non esiste tra mittente e destinatario del messaggio un percorso dedicato (neppure logico): i dati inviati contengono al loro interno le informazioni necessarie per individuare il destinatario (indirizzo IP e porta della macchina di destinazione). Questo tipo di comunicazione si adatta molto bene a reti di comunicazione wireless a commutazione di pacchetto, mentre può non essere supportata da reti a commutazione di circuito che si basano su stream (esiste un percorso diretto tra mittente e destinatario attraverso il quale vengono inviati i dati).

L'utilizzo delle connessioni di tipo datagram impone, solitamente, questi sei passi:

  1. il mittente stabilisce una connessione datagram
  2. il mittente costruisce un oggetto datagram da inviare contenente indirizzo e porta del destinatario e naturalmente le informazioni da inviare
  3. invio del datagram costruito attraverso la connessione aperta
  4. costruzione di un oggetto datagram (vuoto) per la ricezione di eventuali dati in risposta
  5. attesa di una eventuale risposta. I dati ricevuti vengono scritti nel datagram vuoto pre-allocato
  6. chiude la connessione datagram aperta

Le operazioni appena esposte possono essere eseguite, nel MIDP, utilizzando le classi Datagram e DatagramConnection: la prima rappresenta "l'unità informativa" cioè il datagram, l'altra la connessione datagram vera e propria.
Per l'apertura della connessione datagram si utilizzano il metodo open, visto in precedenza, nel seguente modo:

DatagramConnection datagramConn = (DatagramConnection)
Connector.open("datagram://193.0.0.1:8000);

L'omissione dell'indirizzo nella stringa di connessione permette l'apertura di connessioni in modalità server:

DatagramConnection datagramConn = (DatagramConnection)
Connector.open("datagram://:8000);

Che è equivalente a:

DatagramConnection datagramConn = (DatagramConnection)
Connector.open("datagram://localhost:8000);

Le connessioni aperte in modalità server possono essere utilizzate sia per l'invio sia per la ricezione dei datagram, mentre con le connessioni client permettono solo l'invio.
Per la manipolazione dei datagram e del loro contenuto l'omonima classe prevede un insieme di metodi che permetto l'accesso al "campo" indirizzo e al "campo" dati del datagram stesso:

public String getAddress()
public void setAddress(String address)
public void setAddress(Datagram reference)

il primo metodo ritorna l'indirizzo inserito in un oggetto datagram, gli altri due ne permettono il settaggio passando rispettivamente una stringa corrispondente all'indirizzo stesso o un riferimento ad un datagram (in questo caso l'indirizzo sarà uguale a quello del datagram di riferimento).

public int getLength()
public void setLength(int length)
public int getOffset()
public void setData(byte[] buffer, int offset, int length)
public byte[] getData()
public void reset()

permettono invece la manipolazione dei dati e degli attributi ad essi inerenti.
Il primo metodo, getLength, fornisce informazioni sul lunghezza (in byte) del buffer contenente i dati mentre utilizzando il secondo è possibile impostarla.
getOffset permette di ottenere il posizionamento dell'offeset (puntatore in scrittura) all'interno del campo dati.
Il metodo setData, consente la scrittura dei dati all'interno del datagram: i dati da scrivere sono contenuti in un array di byte (buffer) il metodo provvederà alla loro scrittura dentro il datagram a partire dalla posizione indicata da offset e per un numero totale di byte stabiliti con la variabile length. Per l'operazione contraria, cioè la lettura, è previsto il metodo getData, che ritorna appunto un array di byte che rappresentano il "campo" dati del datagram.
reset, infine, permette di "ripulire" il datagram riportando il puntatore ai dati scritti/letti nella posizione iniziale.
I metodi finquì visti permettono di operare sull'oggetto datagram senza però occuparsi né della loro creazione né della loro trasmissione/ricezione: la classe DatagramConnection gestisce proprio questi aspetti.
Attraverso il metodo newDatagram è possibile creare un oggetto datagram.

public Datagram newDatagram(int size)
public Datagram newDatagram(int size, String address)
public Datagram newDatagram(byte[] buf, int size)
public Datagram newDatagram(byte[] buf, int size, String addr)

Le differenti firme di questo metodo permettono la creazione di nuovo datagram "sempre più specifici": nel primo caso viene creato un nuovo generico datagram specificando solo la dimensione (lunghezza dei dati che può contenere), il secondo metodo permette di specificare anche l'indirizzo di destinazione, il terzo crea un datagram di dimensioni prestabilite (size) nel cui campo dati sono state inserite le informazioni contenute in buffer, l'ultimo infine permette la creazione di un datagram "pronto per essere inviato", cioè con dati, dimensione e indirizzo del destinatario settati.
Infine,

public void send(Datagram datagram)
public void receive(Datagram datagram)

si occupano dell'invio e della ricezione dei datagram, mentre

public int getNominalLength()
public int getMaximumLength()

forniscono rispettivamente la dimensione nominale e la massima dimensione consentita di un datagram. Quello che segue è un esempio di come può essere impostata la connessione datagram nel MIDP:

import java.io.*;
import javax.microedition.*;
...
...
String destAddress = "datagram://193.0.0.1:8080";
DatagramConnection datagramConn;
String message;
try {
  // Apre la connessione datagram in modalità
  //
server(invio/ricezione) sulla porta 8000
  datagramConn = (DatagramConnection)
  Connector.open("datagram://:8000);

  // Viene impostato il messaggio da inviare
  message=......
  // Il messaggio viene convertito in array di byte
  byte data[] = message.getBytes();
  // Viene settata la dimensione del datagram
  // (è la dimensione dei dati da inviare)
  int size = data.length;
  // Crea il datagram contenente il messaggio da
  // inviare a destAddress
  Datagram datagramSend;
  datagramSend = datagramConn.newDatagram(data, size, destAddress);
  //Invia il datagram
  DatagramConn.send(datagramSend );
  //Ricava la dimensione massima di un datagram
  int maxLength = datagramConn.getMaximumLength();
  //Crea un datagram vuoto per i dati da ricevere
  Datagram datagramReceive = datagramConn.newDatagram(maxLength);
  //Resta in attesa della ricezione di un datagram
  DatagramConn.receive(datagramReceive );
  //Legge i dati contenuti nel datagram ricevuto
  byte receivedData[] = datagramReceive.getData();
  //Utilizza i dati ricevuti
  ...
  ...
}
catch(Exception e) {
  //Gestisce l'eccezione
}

 

Connessioni di tipo socket
La comunicazione con l'utilizzo di socket del MIDP è praticamente identica a quella, "classica", a cui siamo abituati lavorando con la versione Standard di java. Tale comunicazione può essere suddivisa in quattro fasi:

  1. il client apre una connessione (socket) con un server remoto o con un altro dispositivo wireless;
  2. gli stream di input/output devono essere collegati alla connessione socket aperta;
  3. una volta aperti gli stream è possibile inviare dati al server (outputstream) e da questo riceverli (inputstream);
  4. al termine delle operazioni di lettura/scrittura occorre chiudere la connessione e gli stream di I/O;

Un esempio di utilizzo della classe Connector e dell'apertura delle connessione di tipo Socket può essere:

import java.io.*;
import javax.microedition.*;
...
...
String connectionString = "socket://193.0.0.1:8080";

DataInputStream dis = null;
DataOutputStream dos = null;
StreamConnection sc = null;
...
...
try {
  // Apre la connessione come specificato da connectionString
  // Viene restituita una
  // StreamConnection alla quale vengono collegati gli stream
  // di input/output (dis/dos)
  sc = (StreamConnection) Connector.open(connectionString);
  dis = sc.openDataInputStream();
  dos = sc.openDataOutputStream();
  ...
  ...
  // Operazioni di lettura e scrittura sugli stream di
  // input/output dis/dos.
  ...

  dis.close();
  dos.close();
  sc.close();
}
catch (IOException e) {
  // gestisce l'eccezione di I/O
}

Connessioni Http
L'Http (HyperText Transport Protocol) è un protocollo di livello applicazione (modello OSI), molto diffuso, utilizzato per le comunicazioni con web server, sul quale si basa tutto il "mondo" WWW (World Wide Web), Sebbene sia, comunque possibile accedere ad un web server utilizzando i socket, in MIDP esiste una apposita classe che implementa il protocollo Http e ne favoriscono la gestione (vedremo, ad esempio come, con appositi metodi si può facilmente accedere ai vari campi dell'header del messaggio Http). I vantaggi derivanti dal supporto Http, non riguardano solo la maggiore "facilità di gestione" delle richieste WWW, occorre infatti tener presente che mentre alcuni dispositivi MIDP non implementano comunicazioni di tipo socket o datagram praticamente tutti supportano l'Http. Inoltre, mentre socket e datagram sono comunque vincolati dal tipo di rete (commutazione di circuito o di pacchetto) le connessioni Http sono, dal punto di vista del programmatore, indipendenti dalla rete sottostante, questo facilita l'utilizzo delle applicazioni su reti wireless di tipo diverso. Non va dimenticato inoltre che l'Http ben si presta ad essere utilizzato in combinazione con l'Xml (eXtensible Markup Language) ( ..... SOAP).
HttpConnection rappresenta l'implementazione del protocollo Http (Versione 1.1) nel MIDP.
Come già accennato essa permette una facile gestione delle operazioni previste dal protocollo.
Come per ogni altro tipo di connessione, anche quella Http, viene attivata, nel MIDP, con il metodo open nella seguente forma:

HttpConnection httpConn = (HttpConnection)
Connector.open("http://www.mokabyte.it");

L'implementazione dell'Http del MIDP supporta tre tipi di richieste: GET, POST e HEAD.
Il valore di default è GET, gli altri tipi di richeste possono essere impostate tramite il metodo:

public void setRequestMethod(String method)

dove method può assumere appunto i valori POST e HEAD e naturalmente GET.
Il metodo:

public void setRequestProperty(String key, String value)

serve per poter impostare i campi dell'header Http relativi alla richiesta (ecco alcuni esempi di tali campi:

http.setRequestProperty("User-Agent","Profile/MIDP-1.0 Configuration/CLDC-1.0");
http.setRequestProperty("Content-Language","en-US");
http.setRequestProperty("Content-Type","text/plain");
http.setRequestProperty("Content-Length",String.valueOf(length));
http.setRequestProperty("Cache-Control","no-store");
http.setRequestProperty("Pragma","no-cache");
http.setRequestProperty("Expires","Tue, 1 Jul 1997 00:00:00 GMT");

dove http è l'oggetto HttpConnection (la connessione Http aperta con il metodo open)).

Se la richiesta Http è di tipo POST, è necessario collegare alla connessione Http uno stream di output per poter inviare i dati al server:

//Apre la connessione Http
HttpConnection httpConn = (HttpConnection)
Connector.open("http://www.mokabyte.it/MIDPServlet");
//Imposta il tipo richiesta a POST
httpConn.setRequestMethod(HttpConnection.POST);
//Apre uno stream di output per inviare il corpo della richiesta POST al server
DataOutputStream dos = httpConn.openDataOutputStream();
String requestBody =.........
//Converte il corpo della richiesta in array di byte
byte data[] = requestBody.getBytes();
//Effettua la scrittura del corpo del messaggio Http Post sullo stream
for( int i=0; i< data.length; i++){
  dos.writeByte(data[i]);
}
...
dos.flush();

I campi, della risposta Http ottenuta dal server a seguito di una richiesta del client, sono accessibili utilizzando i metodi forniti da HttpConnection. Spesso, infatti, il client ha necessità di accedere ai campi dell'header Http, per poter decidere di intraprendere un'azione piuttosto che un'altra. Ad esempio potrebbe comportarsi in un determinato modo nel caso ottenga dal server una risposta positiva mentre potrebbe svolgere altre operazioni in caso contrario. O ancora, potrebbe controllare la data dell'ultima modifica effettuata sulla risorsa richiesta per valutare la necessità di un aggiornamento dei dati. Nella pratica, quindi, utilizzando connessioni Http è di fondamentale importanza poter accedere ai campi dell'header della risposta ottenuta dal server. Riportiamo di seguito i metodi previsti dal MIDP per ottenere e manipolare i valori dell'header Http:

public long getDate()
ritorna il valore del campo data nell'header Http, il valore tornato è espresso come numero di millisecondi trascorsi a partire dall'"epoca" (01-01-1970).
public long getLastModified()
ritorna il valore del campo Last-Modified dell'header come millisecondi trascorsi dal 01-01-1970

public long getExpiration()
questo metodo serve ad ottenere il valore del campo expires dell'header Http. Indica la scadenza della risorsa richiesta, cioè il momento in cui la risorsa stessa è da considerarsi non valida e deve essere nuovamente richiesta al server (il valore è espresso in millisecondi dall'"epoca" 01-01-1970).

public String getHeaderField(String name)
ritorna il valore, in formato stringa, del campo dell'header Http indicato da name, null nel caso in cui il campo sia mancante.

public int getHeaderFieldInt(String name, int default)
questo metodo ritorna il valore convertito in intero del campo dell'header identificato da name. Se tale campo non esiste, oppure non può essere convertito in intero, ritorna il valore default.

public long getHeaderFieldDate(String name, long default)
questo metodo fornisce il valore in millisecondidel campo dell'header identificato da name. Il valore di tale campo viene parserizzato come una data. Se il valore del campo richiesto è mancante o non è una data viene ritornato il valore default.

public String getHeaderFieldKey(int index)
ritorna il valore del campo dell'header nella posizione indicata con index, ritorna null se l'indice è superiore al numero di campi presenti.

public int getResponseCode()
ritorna lo "status code" del protocollo Http, ovvero un numero intero associato ad una determinata risposta ( ad esempio 200 se la risposta è positiva, 404 se la risorsa richiesta non è stata trovata, 400 se la richiesta non è stata mal formulata).

public String getResponseMessage()
ritorna la "reason phrase" dell'Http, cioè una breve descrizione del codice di risposta (status code)
(ad esempio: OK nel caso di 200 , NOT FOUND nel caso di 404, BAD REQUEST se il codice è 400) .


Da ContentConnection, vengono poi ereditati i seguenti tre metodi che permettono l'accesso a tre campi dell'header Http di fondamentale importanza:

public String getType()
ritorna il valore del Content-Type dell'header Http. E' il tipo MIME relativo alla risorsa richiesa (ad esempio text/plain, text/html, image/png).

public String getEncoding()
ritorna il Content-Encoding dell'header Http, ed indica il tipo di codifica applicata al corpo del messaggio Http, ossia alla risorsa richiesta

public long getLength()
ritorna il Content-Length Http, ossia la dimensione, espressa come numero di byte, del corpo della risposta Http, ovvero della risorsa richiesta

Oltre ai suddetti metodi HttpConnection contiene tutta una serie di metodi che permettono di accedere alle informazioni relative alla connessione Http aperta e alla richiesta effettuata:

public String getRequestMethod()
fornisce il valore il tipo di richiesta effettuata, può assumere i valori GET, POST, HEAD.

public String getRequestProperty(String key)
ritorna il valore di una proprietà della richiesta Http, impostata con setRequestProperty ed individuata da key.

public String getURL()
ritorna la stringa rappresentativa dell'URL della connessione Http aperta (ad esempio: "http://www.mokabyte.it" ).

public String getProtocol()
indica il tipo di protocollo utilizzato (ad esempio: http, https).

public String getHost()
ritorna le informazioni sul campo host contenuti nella URL (ad esempio: "www.mokabyte.it").

public String getFile()
ritorna la porzione di URL relativa al file richiesto, null se tale parte non è presente nella URL ( ad esempio se la URL è http://www.mokabyte.it ritorna null, ma se la fosse: "http://www.mokabyte.it/index_07_2002.html" il metodo ritornerebbe "/index_07_2002.html").

public String getRef()
ritorna la parte di URL relativa ad un riferimento (anchor) cioè ad una ben precisa sezione di un documento html. Tale porzione è individuata nell'URL dopo il carattere "#" ( ad esempio con una URL del tipo "http://www.mokabyte.it/index_07_2002.html#secton91918273" il metodo getRef ritorna "secton91918273").

public String getQuery()
questo metodo ritorna la porzione di URL relativa ad una query. Nell'Http le query sono individuate dalla parte di URL posta dopo il carattere "?" e vengono utilizzate per passare parametri a programmi CGI o servlet, nel formato chiave=valore. Una URL può contenere query formate da più coppie chiave=valore che dovranno essere separate dal carattere ":" (ad esempio il metodo getQuery richiamato su una connessione relativa alla URL:
"http://www.mokabyte.it/MIDPServlet?code=867:number=23:color=red"
ritorna "code=867:number=23:color=red")

public int getPort()
fornisce il valore della porta indicata nella URL, 80 (il valore di default per l'Http) se nella URL non viene specificato diversamente ( ad esempio : se la URL è http://www.mokabyte.it ritorna 80, 8081 se la URL fosse "http://www.mokabyte.it:8081").

Riportiamo qui sotto, a titolo di esempio, alcune parte di codice relative ad una richiesta GET ed una POST.

Richiesta GET
import java.io.*;
import javax.microedition.*;
...
...
String connectionString = "http://www.mokabyte,it";

HttpConnection httpConn = null;
DataInputStream dis = null;
String message = null;
...
try{
  // Apre la connessione ed effettua la richiesta.
  // Si tratta di una GET (valore di default)
  httpConn = (HttpConnection) Connector.open(connectionString);
  // Apre uno stream in input associato alla connessione
  dis = httpConn.openDataInputStream();
  int ch;
  // Legge dallo stream finchè ci sono caratteri da leggere
  while( (ch = dis.read()) != -1){
    message += (char) ch;
  }
  //Controlla il risultato della richiesta
  int statusCode = httpConn.getResponseCode();
  // Sulla base della risposta ottenuta dal server svolge
  // una ben determinata azione
  switch (statusCode){
    case HttpConnection.HTTP_OK:
    //Azione da intraprendere nel caso di risposta 200 OK
    break;
    case HttpConnection.HTTP_NOT_FOUND:
    //Azione da intraprendere nel caso di risposta 404 NOT FOUND
    break;
    case HttpConnection.HTTP_MOVED_TEMP:
    //Azione da intraprendere nel caso di risposta 302 MOVED TEMP
    break;
    case HttpConnection.HTTP_BAD_REQUEST:
    //Azione da intraprendere nel caso di risposta 400 BAD REQUEST
    break;
    case HttpConnection.HTTP_UNAUTHORIZED:
    //Azione da intraprendere nel caso di risposta 401 UNAUTHORIZED
    break;
    ...
    //Gestisce altri tipi di risposta
    ...
  }
  ...
  ...
  // Chiude la connessione Http e lo stream di input associato
  dos.close();
  httpConn.close();
  ...
}
catch( Exception e){
  // Gestisce le eventuali eccezioni
}


Richiesta POST
import java.io.*;
import javax.microedition.*;
...
...

String connectionString = "http://www.mokabyte,it/MIDPServlet";

HttpConnection httpConn = null;
DataInputStream dis = null;
DataOutputStream dos = null;
String messageBody = null;
...
try{
  // Apre la connessione ed effettua la richiesta
  httpConn = (HttpConnection) Connector.open(connectionString);
  // Imposta il tipo di richiesta a POST
  httpConn.setRequestMethod(HttpConnection.POST);
  // Apre uno stream in output associato alla connessione
  dos = httpConn.openDataOutputStream();
  ...
  ...
  messageBody =...
  // Converte il corpo del messaggio Http in un array di byte
  byte data[] = messageBody.getBytes();
  // Imposta il valore del Content-Type e del Content-Length
  // nell'header della richiesta Http Post
  httpConn.setRequestProperty("Content-Type","text/plain");
  httpConn.setRequestProperty("Content-Length",
                               String.valueOf(data.length));

  for(int i=0; i<data.length; i++){
    dos.writeByte(data[i]);
  }
  dos.flush();

  // Controlla il risultato della richiesta
  int statusCode = httpConn.getResponseCode();
  // Sulla base della risposta ottenuta dal server svolge
  // una ben determinata azione
  switch (statusCode){
    case HttpConnection.HTTP_OK:
    // Azione da intraprendere nel caso di risposta 200 OK
    break;
    case HttpConnection.HTTP_NOT_FOUND:
    // Azione da intraprendere nel caso di risposta 404 NOT FOUND
    break;
    case HttpConnection.HTTP_MOVED_TEMP:
    // Azione da intraprendere nel caso di risposta 302 MOVED TEMP
    break;
    case HttpConnection.HTTP_BAD_REQUEST:
    // Azione da intraprendere nel caso di risposta 400 BAD REQUEST
    break;
    case HttpConnection.HTTP_UNAUTHORIZED:
    // Azione da intraprendere nel caso di risposta 401 UNAUTHORIZED
    break;  
    ...
    // Gestisce altri tipi di risposta
    ...
  }

// Chiude connessione e stream associato
dos.close();
httpConn.close();
}
catch(Exception e) {
  //Gestisce eventuali eccezioni
}
...
...

 

Riferimenti
MokaByte: Il mondo java embedded
http://www.mokabyte.it/2002/01/j2me_1.htm

MokaByte: La configurazione CLDC
http://www.mokabyte.it/2002/02/j2me_2.htm


http://developer.java.sun.com/developer/technicalArticles/wireless
Developing Wireless Applications using J2ME[tm] Technology - Bill Day http://wireless.java.sun.com/getstart/articles/wirelessdev/wirelessdev.pdf
http://java.sun.com/products/midp/

Le specifiche del protocollo Http 1.1:
http://www.w3.org/Protocols/#Specs
ftp://ftp.isi.edu/in-notes/rfc2616.txt

 
MokaByte® è un marchio registrato da MokaByte s.r.l. 
Java®, Jini® e tutti i nomi derivati sono marchi registrati da Sun Microsystems.
Tutti i diritti riservati. E' vietata la riproduzione anche parziale.
Per comunicazioni inviare una mail a info@mokabyte.it