Jak již z názvu článku vyplývá, budeme se zabývat implementací sledování sezení neboli session trackingem v MIDp aplikacích. Hlavním důvodem, proč tak musíme činit, je, že HTTP protokol je bezstavový. Tedy vždy, když klient vytvoří nový požadavek na server, jsou po jeho obsloužení jakékoli informace o něm ztraceny. Naštěstí existuje několik způsobů, jak na serveru identifikovat klienta. My si tu tentokrát ukážeme dva z nich.

Proč sledování sezení?

Chceme-li vytvořit jakoukoli aplikaci typu klient-server, ať už se jedná o multiplayer hru nebo například přístup do nějakého systému, je třeba udržovat informace o klientovi na serveru. Tímto způsobem jsme schopni klienta identifikovat a na základě jeho identifikace mu zasílat potřebná data, například změny ve hře.

Jak to funguje?

Základní princip spočívá ve vytvoření unikátního ID, které vygeneruje server při prvním požadavku a pošle jej zpět klientovi. Ten při každém dalším požadavku na server posílá i toto ID a server si tak o něm může udržovat informace. V tomto článku si ukážeme implementaci podobného mechanismu pomocí cookies a vlastního komunikačního protokolu.

Cookies

Tuto technologii vyvinula firma Netscape a postupem času se stala standardem pro všechny internetové prohlížeče. Cookies jsou malé textové informace ve formátu název_cookie=hodnota_cookie a jsou součásti HTTP hlavičky. Jednotlivé cookie oddělujeme od sebe středníkem. Standardně jsou cookies uloženy v cache prohlížeče – v MIDp aplikacích se nabízí uložit přijaté cookies do RMS. Specifikaci a další informace naleznete v RFC2109 a RFC2695.

Serverová část

Základem serverové části je jednoduchý servlet, který si získává session z requestu. Pokud se jedná o novou session, je do objektu response uložena nová cookie s názvem session a hodnotou ID, získanou metodou getId nad objektem session. Pro zpětnou kontrolu je vytvořen atribut counter, který se při každém přístupu inkrementuje a jehož hodnota je pro kontrolu posílána zpět klientovi, který ji zobrazí.

HttpSession session = req.getSession(true); //získej session
if (session.isNew()) {
  //přidej cookie
  res.addCookie(new Cookie(„session“, session.getId()));
}

pw.println(„Counter = “ + counterStr); //pošli výsledek klientovi

Klientská část

V klientské části je nutné přečíst zaslanou cookie od serveru ze záhlaví „set-cookie“ HTTP protokolu (více v RFC2616). Protože žádnou jinou cookie server neposílá, obsahuje záhlaví řetězec session=xxx, kde xxx je hodnota session. Tu musí klient vždy, když komunikuje se serverem, posílat zpět na server, o což se nám postará metoda setCookiesSession. Její získání provede metoda getCookiesSession, která iteruje přes všechny záhlaví protokolu, a najde-li záhlaví „set-cookie“, uloží hodnotu session do řetězce sessionIDStr.

private void setCookiesSession(HttpConnection con) throws IOException {
con.setRequestProperty(„cookie“, sessionIDStr);
}

private void getCookiesSession(HttpConnection con)
throws IOException {
  int headerIndex = 0;
  while (con.getHeaderFieldKey(headerIndex) != null) {
    String headerFieldKey = con.getHeaderFieldKey(headerIndex);
    if (headerFieldKey.equals(„url-attachment“)) {
      String value = con.getHeaderField(headerFieldKey);
      sessionURLStr = „;jsessionid=“ + value.substring(value.indexOf(‚=‘) + 1, value.length());
    }
    headerIndex++;
  }
}

Ve vlastní komunikaci jsou potom funkce použity následovně:

// získej connection
con = (HttpConnection) Connector.open(URL, Connector.READ, true);
//… nastavení záhlaví
if (sessionIDStr != null) {
  setCookiesSession(con);
}
in = con.openInputStream();
// Před zpracováním dat získej cookie
if (sessionIDStr == null) {
  getCookiesSession(con);
}

Proprietární komunikační protokol

Druhý způsob implementace používá k identifikaci klienta komunikační protokol, jehož součástí je i identifikační řetězec. Tento způsob má výhodu v tom, že identifikace je plně v naší režii a máme tak možnost plně ovlivnit datový typ identifikačního řetězce a optimalizovat náročnost na datový tok HTTP protokolu. Další změnou je nutnost implementovat správu sessions, tedy vytvoření, získaní dle ID a zrušení. Řešením může být objekt, který mimo vytvořené session ponese navíc informaci o čase vytvoření. Při každém požadavku je pak tento čas aktualizován. Pokud je časový rozdíl větší, než je nastavený timeout, session zrušíme.

Serverová část

Na rozdíl od předchozí metody je serverová část o něco složitější. Zasílá-li klient první požadavek na server, nemá k dispozici žádné ID, proto použije prázdný řetězec. Server takto identifikuje nového klienta, vytvoří pro něj novou session a uloží ji do cache pod klíčem, jenž session identifikuje. ID session zasílá zpět klientovi.

Vlastní implementace:

// vyžaduje klient novou session
boolean empty = ID.equals(„“);
if (empty) {
  //získej novou session a ulož ji do cache
  session = req.getSession(true);
  sessions.put(session.getId(), session);
} else {
  session = (HttpSession) sessions.get(ID);
}
//kód pro inkrementaci počítadla
//zapiš ID session a hodnotu počítadla
dos.writeUTF(session.getId());
dos.writeInt(counter);
dos.close();
os.write(baos.toByteArray()); //pošli výsledek klientovi
os.close();

Klientská část

Na straně klienta je třeba odezvu serveru zpracovat a získat session ID, které uložíme pro další požadavky zasílané serveru. Součástí odezvy je i aktuální hodnota počítadla, která v tomto případě slouží pouze pro kontrolu.

// získej outputstream a zapiš aktualní hodnotu ID
DataOutputStream dos = new DataOutputStream(con.openOutputStream());
dos.writeUTF((sessionProtocolStr != null)? sessionProtocolStr : „“);
//otevřeme inputstream a načteme ID session a počítadla
dis = new DataInputStream(con.openInputStream());
if (sessionProtocolStr.equals(„“)) {
  sessionProtocolStr = dis.readUTF();
}
response = „Counter = “ + dis.readInt();

Ještě bych se chtěl zmínit o jedné věci. Jistě vás napadlo použít metodu pro přepis URL (URL rewriting). Tato metoda ovšem není použitelná, protože není způsob, jak dostat session ID ke klientovi. Pokud bychom použili některou z hlaviček HTTP protokolu, bylo by to v podstatě stejné jako použití cookies.

Kompletní zdrojové kódy našeho řešení jsou vám k dispozici.

Jakou metodu zvolit?

Jak vidíte, implementace sledování sezení v MIDp aplikacích je o něco komplikovanější a vyžaduje určité zásahy na straně klientské části, v případě implementace proprietárním protokolem i na serveru. Mimo tyto dvě metody je možné i zapouzdřit data do XML a použít XML wrapper, ovšem vzhledem k náročnosti na přenos dat není tato metoda zrovna nejvhodnější.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Žádný příspěvek v diskuzi

Odpovědět