Socket programování v jazyce Java: návod

Tento kurz je úvodem do zásuvky programování v Java, počínaje s jednoduchým klient-server příklad demonstrující základní funkce Java I/O. Budete být zavedeny do původní java.io balíček a NIO, non-blocking I/O (java.nio) Api zavedena v Java 1.4. Nakonec uvidíte příklad, který demonstruje Java networking, jak je implementován z Java 7 forward, v NIO.2.,

programování zásuvek se scvrkává na dva systémy, které spolu komunikují. Obecně platí, že síťová komunikace přichází ve dvou příchutích: Transport Control Protocol (TCP) a User Datagram Protocol (UDP). TCP a UDP jsou použity pro různé účely, a oba mají jedinečné omezení:

  • TCP je relativně jednoduchý a spolehlivý protokol, který umožňuje klienta pro připojení k serveru a dva systémy pro komunikaci. V TCP každý subjekt ví, že jeho komunikační zatížení bylo přijato.,
  • UDP je protokol bez připojení a je vhodný pro scénáře, kde nemusíte nutně potřebovat každý paket, aby dorazil na místo určení, jako je streamování médií.

oceníte rozdíl mezi TCP a UDP, zvažte, co by se stalo, pokud jste streamované video z oblíbených stránek a zahozených snímcích. Chtěli byste raději, aby klient zpomalil váš film, aby obdržel chybějící snímky, nebo byste raději, aby video pokračovalo v přehrávání? Protokoly pro streamování videa obvykle využívají UDP., Protože TCP zaručuje doručení, je to protokol volby pro HTTP, FTP, SMTP, POP3 a tak dále.

v tomto tutoriálu vám představím programování soketů v Javě. Představuji řadu příkladů klient-server, které demonstrují funkce z původního Java i / o frameworku, pak postupně postupovat k použití funkcí zavedených v NIO.2.

old-school Java sockets

v implementacích před NIO je Kód klientského soketu Java TCP zpracován třídou java.net.Socket., Následující kód otevře připojení k serveru:

Socket socket = new Socket( server, port );

Jednou socket instance je připojen k serveru, můžeme začít získávat vstupní a výstupní proudy na sever. Vstupní toky se používají ke čtení dat ze serveru, zatímco výstupní proudy se používají k zápisu dat na server., Můžeme provést následující metody jak získat vstupní a výstupní proudy:

InputStream in = socket.getInputStream();OutputStream out = socket.getOutputStream();

Protože jsou to obyčejní proudy, stejné proudy, které budeme používat pro čtení a zápis do souboru, můžeme je převést do formy, která nejlépe slouží náš případ použití. Například bychom mohli zabalit OutputStream pomocí PrintStream, abychom mohli snadno psát text metodami jako println()., Pro další příklad můžeme zabalit do InputStream BufferedReader, tak prostřednictvím InputStreamReader, aby se snadno číst text s metodami jako readLine().

stáhnout

zdrojový kód pro “ programování soketů v Javě: tutoriál.“Vytvořil Steven Haines pro JavaWorld.

Java Socket client example

pojďme pracovat přes krátký příklad, který provádí HTTP GET proti HTTP serveru., HTTP je mnohem sofistikovanější než v našem příkladu povoluje, ale můžeme napsat kód klienta zvládnout nejjednodušší případ: žádost o zdroje ze serveru a server vrátí odpověď a zavře datový proud. Tento případ vyžaduje následující kroky:

  1. Vytvořte zásuvku pro poslech webového serveru na portu 80.
  2. Získat PrintStream na server a odeslat žádost GET PATH HTTP/1.0, kde PATH je požadovaný zdroj na serveru., Pokud bychom například chtěli otevřít kořen webu, cesta by byla /.
  3. získejteInputStream na server, zabalte jej BufferedReader a přečtěte si řádek po řádku odpovědi.

Výpis 1 zobrazuje zdrojový kód pro tento příklad.

seznam 1. SimpleSocketClientExample.java

Výpis 1 přijímá dva argumenty příkazového řádku: server pro připojení k (za předpokladu, že jsme připojení k serveru na port 80) a zdrojů získat., Vytvoří Socket, který ukazuje na server a explicitně určuje port 80. To pak provede příkaz:

GET PATH HTTP/1.0

například:

GET / HTTP/1.0

Co se právě stalo?

Při načtení webové stránky z webového serveru, například , HTTP klient používá DNS servery najdete na serveru adresu: začíná tím, že žádá top-level domény serveru pro com domény, kde autoritativní domény-jméno serveru je ., Poté požádá server doménového jména pro adresu IP (nebo adresy) pro . Dále otevře zásuvku na tento server na portu 80. (Nebo, pokud chcete definovat jiný port, můžete tak učinit přidáním dvojtečky následuje číslo portu, například: :8080.) A konečně, HTTP klient provede zadaného HTTP metodu, například GET POST PUT DELETE HEAD nebo OPTI/ONS. Každá metoda má svou vlastní syntaxi., Jak je uvedeno ve výše uvedeném kódu snips, metoda GET vyžaduje cestu následovanou HTTP/version number a prázdným řádkem. Pokud bychom chtěli přidat záhlaví HTTP, mohli jsme tak učinit před vstupem do nového řádku.

v seznamu 1 jsme získali OutputStream a zabalili jsme jej do PrintStream abychom mohli snadněji provádět naše textové příkazy., Náš kód získaný InputStream, zabalené, že v InputStreamReader, který převede jej do Reader, a pak zabalené, že v BufferedReader. Použili jsme PrintStream spustit GET metoda a pak použít BufferedReader, přečíst odpověď, řádek po řádku, dokud jsme obdrželi null reakci, což znamená, že zásuvky byly zavřené.,

provedení této třídy a předat následující argumenty:

java com.geekcap.javaworld.simplesocketclient.SimpleSocketClientExample www.javaworld.com /

Byste měli vidět výstup podobný tomu, co je níže:

Tento výstup ukazuje testovací stránku na JavaWorld webové stránky. Odpověděl zpět, že mluví HTTP verze 1.1 a odpověď je 200 OK.

Java Socket Server example

pokryli jsme klientskou stranu a naštěstí je komunikační aspekt strany serveru stejně snadný., Z zjednodušující perspektivy, proces je následující:

  1. Vytvořit ServerSocket, určení portu pro naslouchání.
  2. vyvolatServerSocket‚saccept() způsob pro poslech na nakonfigurovaném portu pro připojení klienta.
  3. Když se klient připojí k serveru, accept() metoda vrací Socket přes který server může komunikovat s klientem., To je stejné Socket třídy, který jsme použili pro našeho klienta, takže proces je stejný: získat InputStream přečtěte si od klienta a OutputStream napište klienta.
  4. pokud je třeba server škálovat, budete chtít přenéstSocket na jiné vlákno, které bude zpracovávat, aby váš server mohl pokračovat v poslechu dalších připojení.
  5. volejteServerSocket‚saccept() znovu poslouchat další připojení.,

jak brzy uvidíte, řešení tohoto scénáře NIO by bylo trochu jiné., Teď, když můžeme přímo vytvořit ServerSocket průchodem port pro naslouchání (více o ServerSocketFactoryy v další části):

ServerSocket serverSocket = new ServerSocket( port );

A teď můžeme přijmout příchozí připojení pomocí accept() metoda:

Socket socket = serverSocket.accept();// Handle the connection ...

Vícevláknové programování v Java zásuvky

Výpis 2, níže, staví všechny kód serveru spolu tak daleko do mírně robustnější příklad, který používá vlákna pro zpracování více požadavků., Zobrazený server je echo server, což znamená, že odráží zpět jakoukoli zprávu, kterou obdrží.

Zatímco například v Výpis 2 není složité, to se předvídat, co přijde v další části na NIO. Věnujte zvláštní pozornost množství závitů kód musíme napsat s cílem vybudovat server, který dokáže zpracovat více souběžných požadavků.

Seznam 2. SimpleSocketServer.java

ve výpisu 2 vytvoříme novou instanci SimpleSocketServer a spustíme server., To je nutné, protože SimpleSocketServer rozšiřuje Thread vytvořit nové vlákno zvládnout blokování accept() volání, které vidíte v read() metoda. run() metoda sedí ve smyčce přijímá požadavky klientů a vytváří RequestHandler vláken ke zpracování požadavku. Opět je to relativně jednoduchý kód, ale také zahrnuje značné množství závitového programování.,

Všimněte si, že RequestHandler zpracovává komunikaci s klientem podobně jako kód ve Výpisu 1: zábaly OutputStream PrintStream k usnadnění snadno píše a podobně zábaly InputStream BufferedReader pro snadné čtení. Pokud jde o server, čte řádky od klienta a odráží je zpět klientovi. Pokud klient odešle prázdný řádek, konverzace je u konce aRequestHandler zavře zásuvku.

NIO a NIO.,2

pro mnoho aplikací stačí základní programovací model Java socket, který jsme právě prozkoumali. Pro aplikace zahrnující více intenzivní I/O nebo asynchronní vstup/výstup, budete chtít, aby se seznámili s non-blokování Api zavedena v Java NIO a NIO.2.

balíček JDK 1.4 NIO nabízí následující klíčové vlastnosti:

  • kanály jsou navrženy tak, aby podporovaly hromadné přenosy z jedné vyrovnávací paměti NIO do druhé.
  • Buffery představují souvislý blok paměti propojený jednoduchou sadou operací.,
  • neblokující vstup / výstup je sada tříd, které vystavují kanály běžným zdrojům I / O, jako jsou soubory a zásuvky.

Při programování s NIO, otevřete kanál k cíli, a pak čtení dat do vyrovnávací paměti od destinace, zapisovat data do vyrovnávací paměti, a poslat na místo určení., Budeme ponořit do nastavení zásuvky a získání kanál, aby to brzy, ale nejprve podívejme se na proces, pomocí vyrovnávací paměti:

  1. Zápis dat do vyrovnávací paměti
  2. Volat do vyrovnávací paměti flip() způsob, jak připravit je pro čtení
  3. Čtení dat z vyrovnávací paměti
  4. Volat do vyrovnávací paměti clear() nebo compact() způsob, jak připravit ji přijímat více dat

Při zápisu dat do vyrovnávací paměti, vyrovnávací paměti, ví, že množství dat zapsaných do., To udržuje tři vlastnosti, jejichž významy se liší, pokud je vyrovnávací paměť v režimu čtení nebo v režimu zápisu:

  • Poloha: V režimu zápisu, počáteční pozice je 0 a drží aktuální pozice je napsán ve vyrovnávací paměti; poté, co jste fanda vyrovnávací paměti, aby ji v režimu čtení, to obnoví pozici 0 a drží aktuální pozice v bufferu čtené z,
  • Kapacita: Pevné velikosti vyrovnávací paměti
  • Omezení: V režimu zápisu, limit určuje, kolik dat může být zapsáno do vyrovnávací paměti; v režimu čtení, limit určuje, kolik dat lze číst z vyrovnávací paměti.,

Java i / o demo: Echo server s NIO.2

NIO.2, který byl představen v JDK 7, rozšiřuje Java je non-blocking I/O knihovny přidat podporu pro souborový systém úkolů, jako je například java.nio.file balíček java.nio.file.Path třídy a odhaluje nový Systém Souborů API. S ohledem na toto pozadí napíšeme nový server Echo pomocí NIO.2 AsynchronousServerSocketChannel.

AsynchronousServerSocketChannel poskytuje neblokující asynchronní kanál pro stream orientované na poslech zásuvky., Abychom jej mohli použít, nejprve provedeme jeho statickou metodu open() a poté bind() na konkrétní port. Dále provedeme metodu accept() a předáme jí třídu, která implementuje rozhraní CompletionHandler. Nejčastěji najdete toho psovoda vytvořeného jako anonymní vnitřní třída.

Výpis 3 zobrazuje zdrojový kód pro náš nový asynchronní Echo Server.

Výpis 3. SimpleSocketServer.,java

Výpis 3 jsme nejprve vytvořit nový AsynchronousServerSocketChannel a pak svázat ho do port 5000:

 final AsynchronousServerSocketChannel listener = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(5000));

AsynchronousServerSocketChannel, vzýváme accept() říct, je začít naslouchat pro připojení, mimochodem na to vlastní CompletionHandler instance. Když vyvoláme accept(), okamžitě se vrátí., Všimněte si, že tento příklad se liší od ServerSocket třídy ve Výpisu 1; vzhledem k tomu, že accept() metoda blokován, dokud klient připojen k němu, AsynchronousServerSocketChannel accept() metoda zpracovává to pro nás.

dokončení handler

Naším dalším úkolem je vytvořit CompletionHandler class a poskytují provádění completed() failed() metody., completed() metoda je volána, když AsynchronousServerSocketChannel přijímá připojení z klienta a zahrnuje AsynchronousSocketChannel pro klienta. Metoda completed() nejprve přijme připojení z AsynchronousServerSocketChannel a poté začne komunikovat s klientem. První věc, kterou dělá, je napsat zprávu“ Hello“: vytvoří řetězec, převede jej na pole bajtů a poté ji předá ByteBuffer.wrap() a vytvoří ByteBuffer., ByteBuffer pak může být předánAsynchronousSocketChannel‚swrite() metoda.

přečtěte si od klienta, jsme se vytvořit nový ByteBuffer vyvoláním jeho allocate(4096) (který vytváří 4K buffer), pak vzýváme AsynchronousSocketChannelread() metoda. read() vrací Future<Integer>, na které se můžeme odvolávat get() načíst počet bajtů číst od klienta., V tomto příkladu předámeget() hodnotu časového limitu 20 sekund: pokud nedostaneme odpověď za 20 sekund, pak metodaget() hodíTimeoutException. Naše pravidlo pro tento echo server je, že pokud budeme pozorovat 20 sekund ticha, ukončíme konverzaci.

dále zkontrolujeme polohu vyrovnávací paměti, což bude umístění posledního bajtu přijatého od klienta. Pokud klient odešle prázdný řádek, dostaneme dva bajty: návrat vozíku a posuv linky., Kontrola zajišťuje, že pokud klient odešle prázdný řádek, vezmeme jej jako indikátor, že klient je ukončen konverzací. Pokud máme smysluplná data, nazývámeByteBuffer‚sflip() způsob, jak jej připravit ke čtení. Jsme vytvořit dočasný byte pole držet počet bajtů čtení z klienta, a pak vyvolat ByteBufferget() načíst data do pole bajtů. Nakonec převedeme pole bajtů na řetězec vytvořením nové instanceString., Jsme echo na řádku zpět klientovi tím, že převede řetězec na pole bajtů, kolem které ByteBuffer.wrap() metoda a vyvolání AsynchronousSocketChannelwrite() metoda. Nyní jsme clear() ByteBuffer, které připomínají znamená, že se to přemístí position na nulu a staví ByteBuffer do režimu zápisu, a pak jsme si přečíst další řádek od klienta.,

jediná věc je být si vědom, je, že main() metoda, která vytvoří server, také zřizuje 60 sekund časovač, aby aplikace běží. Protože AsynchronousSocketChannelaccept() metoda vrátí okamžitě, pokud nemáme Thread.sleep() pak naše aplikace bude okamžitě zastavit.,

tento test, spustit server a připojit se k němu pomocí telnet klienta:

telnet localhost 5000

Poslat pár nitek na server, pozorovat, že jsou ozvěnou zpátky k vám, a pak poslat prázdný řádek ukončit rozhovor.

závěr

V tomto článku jsem představil dva přístupy k programování socket s Java: tradiční přístup zavedl s Java 1.0 a novější, non-blokování NIO a NIO.2 přístupy zavedené v Java 1.4 a Java 7, resp., Viděli jste několik iterací Java socket client a Java socket server příklad, prokazující, jak nástroj základní Java I/O a některé scénáře, kde non-blocking I/O zlepšuje Java socket programming model. Použití non-blocking I/O, můžete program Java síťových aplikací pro zpracování více souběžných připojení, aniž byste museli spravovat více nití sbírky. Můžete také využít nové škálovatelnosti serveru, která je zabudována do NIO a NIO.2.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *