Socket-ohjelmointi Java: opetusohjelma

Tämä opas on johdatus socket-ohjelmointi Java, alkaen yksinkertainen asiakas-palvelin esimerkki osoittaa, perus ominaisuudet Java I/O. sinulta käyttöön sekä alkuperäinen java.io paketti ja NIO, ei-esto I/O (java.nio) APIs käyttöön Java 1.4. Lopuksi, näet esimerkin, joka osoittaa Java networking toteutettuna Java 7 eteenpäin, NIO.2.,

Socket ohjelmointi kuihtuu kaksi järjestelmät kommunikoivat keskenään. Yleensä verkkoviestinnässä on kaksi makua: liikenteen Ohjausprotokolla (TCP) ja käyttäjän Datagram-protokolla (UDP). TCP-ja UDP käytetään eri tarkoituksiin ja molemmat on ainutlaatuinen rajoitukset:

  • TCP on suhteellisen yksinkertainen ja luotettava protokolla, jonka avulla asiakas muodostaa yhteyden palvelimeen ja kaksi järjestelmät voivat kommunikoida. TCP: ssä jokainen taho tietää, että sen tietoliikennekuormat on vastaanotettu.,
  • UDP on yhteydetön protokolla ja se on hyvä tilanteissa, joissa et välttämättä tarvitse jokaisen paketin saapua määränpäähänsä, kuten median suoratoisto.

arvostaa eroa on TCP ja UDP, mieti, mitä tapahtuisi, jos olit streaming video suosikki verkkosivuilla ja se laski kehyksiä. Toivoisitko, että asiakas hidastaisi elokuvaasi saadakseen puuttuvat kehykset vai haluaisitko, että video jatkuu? Video streaming protokollat tyypillisesti hyödyntää UDP., Koska TCP takaa toimituksen, se on protokollan valinta HTTP, FTP, SMTP, POP3, ja niin edelleen.

tässä opetusohjelmassa esittelen sinut socket-ohjelmoinnille Java-kielellä. Esittelen joukon asiakas-palvelin esimerkkejä, jotka osoittavat ominaisuuksia alkuperäisestä Java I/O-puitteet, sitten vähitellen siirtyä käyttämällä ominaisuuksia käyttöön NIO.2.

Vanhan koulun Java pistorasiat

– toteutuksissa ennen NIO, Java TCP-client socket-koodi on hoitaa java.net.Socket luokka., Seuraava koodi avaa yhteyden palvelimelle:

Socket socket = new Socket( server, port );

Kun socket tapauksessa on yhteydessä palvelimeen voimme alkaa saada input-ja output-virrat katkaista. Syöttövirroilla luetaan tietoja palvelimelta, kun taas lähdevirroilla kirjoitetaan tietoja palvelimelle., Voimme suorittaa seuraavia menetelmiä saada input-ja output-virrat:

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

Koska nämä ovat tavallisia syötteeseen, samaan syötteeseen, että käytämme lukea ja kirjoittaa tiedostoon, voimme muuntaa ne muotoon, joka parhaiten palvelee meidän tapauksessa käyttää. Esimerkiksi voisimme kääri OutputStream ja PrintStream, niin voimme helposti kirjoittaa tekstiä menetelmiä, kuten println()., Toinen esimerkki, voisimme kääri InputStream ja BufferedReader kautta InputStreamReader, jotta voit helposti lukea tekstiä menetelmiä, kuten readLine().

lataa

lähdekoodi ”Socket programming in Java: a tutorial.”Luonut Steven Haines Javaworldille.

Java socket client esimerkki

työn kautta lyhyt esimerkki, joka suorittaa HTTP GET-vastaan HTTP-palvelin., HTTP on enemmän hienostunut kuin esimerkiksi luvat, mutta me voimme kirjoittaa asiakkaan koodi käsitellä yksinkertaisin tapaus: pyytää resurssia palvelimelta ja palvelin palauttaa vastauksen ja suljetaan virta. Tämä tapaus vaatii seuraavat vaiheet:

  1. luo pistorasia www-palvelimelle kuunteluun portissa 80.
  2. Saada PrintStream palvelimelle ja lähettää pyynnön GET PATH HTTP/1.0, jossa PATH on pyydetty resurssi palvelimelle., Jos esimerkiksi haluaisimme avata verkkosivuston juuren, polku olisi /.
  3. Saada InputStream palvelimeen, kääri se BufferedReader ja lue vastaus line-by-line.

listaus 1 näyttää tämän esimerkin lähdekoodia.

listaus 1. SimpleSocketClientExample.java

Listaus 1 hyväksyy kaksi komentorivin argumentteja: palvelimen yhteyden (olettaen, että meillä on yhteys palvelimen porttiin 80) ja resurssi hakea., Se luo Socket viittaa palvelimeen ja määrittää erikseen, portti 80. Se sitten suorittaa komennon:

GET PATH HTTP/1.0

esimerkiksi:

GET / HTTP/1.0

Mitä juuri tapahtui?

Kun voit hakea web-sivun web-palvelin, kuten HTTP-asiakas käyttää DNS-palvelimet löytää palvelimen osoite: se alkaa pyytämällä top-level domain-palvelin com verkkotunnuksen, jossa arvovaltainen domain-nimi server on ., Sitten se pyytää, että verkkotunnuksen palvelin IP-osoite (tai osoitteet) . Seuraavaksi se avaa pistorasian portille 80. (Tai, jos haluat määrittää eri portti, voit tehdä niin lisäämällä kaksoispiste, jota seuraa portin numero, esimerkiksi: :8080.) Lopuksi, HTTP-asiakas suorittaa määritetyn HTTP menetelmää, kuten GET, POST, PUT, DELETE, HEAD tai OPTI/ONS. Jokaisella menetelmällä on oma syntaksinsa., Kuten yllä oleva koodin pätkä, GET menetelmä vaatii polku seuraa HTTP/version number ja tyhjä rivi. Jos olisimme halunneet lisätä HTTP-otsikoita, olisimme voineet tehdä sen ennen uuteen riviin astumista.

Listaus 1, me haetaan an OutputStream ja kääri sen PrintStream niin, että voisimme helpommin toteuttaa myös tekstipohjaisia komentoja., Meidän koodi saatu InputStream, kääritty, että InputStreamReader, joka muuntaa sen Reader, ja sitten kääritty, että BufferedReader. Käytimme PrintStream toteuttaa myös GET menetelmä ja sitten käytetään BufferedReader lukea vastaus line-by-line, kunnes saimme null vastausta, mikä osoittaa, että pistorasia oli suljettu.,

Nyt suorittaa tämän luokan ja siirtää sitä seuraavat perustelut:

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

Sinun pitäisi nähdä lähtö samanlainen kuin mitä on alla:

Tämä ulostulo osoittaa, testi sivu JavaWorld n verkkosivuilla. Se vastasi takaisin, että se puhuu HTTP-versiota 1.1 ja vastaus on 200 OK.

Java socket server esimerkki

Olemme käsitelleet asiakkaan puolella ja onneksi tiedonannossa näkökohta palvelimen puolella on aivan yhtä helppoa., Alkaen yksinkertainen näkökulmasta, prosessi on seuraava:

  1. Luoda ServerSocket, jossa määritellään sataman kuunnella.
  2. Vedota ServerSocket’s accept() tapa kuunnella määritetty portti asiakas-yhteys.
  3. Kun asiakas ottaa yhteyden palvelimeen, accept() metodi palauttaa Socket jonka kautta palvelin voi kommunikoida asiakkaan kanssa., Tämä on sama Socket luokkaa, että me käytetään meidän asiakas, niin prosessi on sama: saada InputStream lukea asiakasta ja OutputStream kirjoittaa asiakkaan.
  4. Jos server on skaalautuva, haluat siirtää Socket toiseen lanka prosessia niin, että palvelin voi jatkaa kuuntelemalla muita yhteyksiä.
  5. Kutsu ServerSocket’s accept() menetelmä taas kuuntelemaan toinen yhteys.,

kuten pian näet, NIO käsittelisi tätä skenaariota hieman eri tavalla., Nyt, vaikka emme voi suoraan luoda ServerSocket johtamalla se portti kuunnella (lisää ServerSocketFactorys. seuraava kohta):

ServerSocket serverSocket = new ServerSocket( port );

Ja nyt emme voi hyväksyä saapuvat yhteydet kautta accept() menetelmä:

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

Monisäikeinen ohjelmointi Java pistorasiat

Listaus 2, alla, laittaa kaikki palvelimen koodi toistaiseksi yhteen hieman vankempi esimerkki, joka käyttää kierteet käsitellä useita pyyntöjä., Näytetty palvelin on echo-palvelin, eli se kaikuu takaisin minkä tahansa saamansa viestin.

vaikka listauksen 2 esimerkki ei ole monimutkainen, se ennakoi joitakin siitä, mitä on tulossa seuraavassa osassa NIO. Kiinnitä erityistä huomiota siihen, kuinka paljon ketjukoodia meidän on kirjoitettava, jotta voimme rakentaa palvelimen, joka pystyy käsittelemään useita samanaikaisia pyyntöjä.

listasi 2. SimpleSocketServer.java

listauksessa 2 luodaan uusi SimpleSocketServer instance ja käynnistetään palvelin., Tämä on tarpeen, koska SimpleSocketServer ulottuu Thread luo uusi säie käsitellä esto accept() puhelu, että näet read() menetelmä. run() menetelmä istuu silmukka hyväksyä asiakkaan pyynnöt ja luo RequestHandler kierteet käsitellä pyynnön. Jälleen tämä on suhteellisen yksinkertainen koodi, mutta sisältää myös kohtuullisen määrän kierteitettyä ohjelmointia.,

Huomaa myös, että RequestHandler käsittelee asiakkaan viestintä paljon kuin koodi Listing 1 ei: se kietoo OutputStream ja PrintStream helpottaa helppo kirjoittaa ja, vastaavasti, huivi InputStream ja BufferedReader helppo lukee. Sikäli kuin palvelin menee, se lukee linjat asiakkaan ja kaikuu ne takaisin asiakkaalle. Jos asiakas lähettää tyhjä rivi sitten keskustelu on ohi ja RequestHandler sulkee socket.

NIO ja NIO.,2

monille sovelluksille riittää juuri tutkimamme Java socket-ohjelmointimalli. Sovelluksiin, joissa intensiivisempää I/O-tai asynkroninen input/output sinun haluavat olla perehtynyt ei-esto APIs käyttöön Java NIO NIO ja.2.

JDK 1.4 NIO paketti tarjoaa seuraavat ominaisuudet:

  • Kanavat ovat suunniteltu tukemaan irtotavaran siirrot yhdestä NIO puskuri toiseen.
  • Puskurit edustavat yhtenäistä muistilohkoa, jota yhdistää yksinkertainen joukko toimintoja.,
  • Non-Blocking Input/Output on joukko luokkia, jotka altistavat kanavien yhteinen I/O-lähteistä kuten tiedostoja ja pistorasiat.

Kun ohjelma NIO, voit avata kanava määränpäähän ja sitten lukea tietoja puskuriin kohde, kirjoita tiedot puskuri, ja lähettää määränpäähän., Me sukeltaa perustaa pistorasiaan ja saada kanava saada se pian, mutta ensin kerrataan prosessi käyttää buffer:

  1. Kirjoita tiedot puskuriin
  2. Soita buffer flip() tapa valmistaa sitä lukeminen
  3. Lue tietoja buffer
  4. Soita buffer clear() tai compact() menetelmä valmistaa sitä vastaanottamaan lisää tietoa

Kun tiedot on kirjoitettu puskuriin puskuri tietää määrä tietoja kirjoitettu siihen., Se ylläpitää kolmea ominaisuuksia, joiden merkitykset eroavat toisistaan, jos puskuri on vain luku-tilassa tai kirjoitus-tilassa:

  • Sijainti: kirjoita-tilassa, alkuperäinen kanta on 0 ja se pitää nykyinen asema on kirjoitettu puskuriin; kun olet flip puskurin laittaa se lukea-tilassa, se palautuu asentoon 0 ja pitää nykyinen asema puskuriin luetaan,
  • Kapasiteetti: Kiinteät puskurin
  • Raja: In kirjoitus-tilassa, raja määrittelee, kuinka paljon tietoa voidaan kirjoittaa puskuriin; luku-tilassa, raja määrittelee, kuinka paljon dataa voidaan lukea puskurista.,

Java I / O demo: Echo server with NIO.2

NIO.2, joka otettiin käyttöön vuonna JDK 7, ulottuu Java on ei-esto I/O-kirjastoja, lisätä tukea tiedostojärjestelmä tehtäviä, esimerkiksi java.nio.file paketti ja java.nio.file.Path luokan ja paljastaa uuden tiedostojärjestelmän API. Tämä tausta mielessä, kirjoitetaan Uusi Echo-palvelin käyttäen NIO.2: n AsynchronousServerSocketChannel.

AsynchronousServerSocketChannel tarjoaa non-blocking asynkroninen kanava stream suuntautunut kuuntelu pistorasiat., Voidakseen käyttää sitä, meidän on ensin suorittaa sen staattinen open() menetelmä ja sitten bind() sen tiettyyn porttiin. Seuraava, me suorittaa sen accept() menetelmä, kulkee se luokka, joka toteuttaa CompletionHandler käyttöliittymä. Useimmiten, löydät käsittelijä luotu nimettömänä sisäinen luokka.

Listing 3 näyttää uuden asynkronisen Echo-palvelimemme lähdekoodin.

listasi 3. SimpleSocketServer.,java

Listaus 3 me ensin luoda uusi AsynchronousServerSocketChannel ja sitten sitoa se portti 5000:

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

tästä AsynchronousServerSocketChannel, me vedota accept() kerro se alkaa kuuntelee yhteyksiä, kulkee sen mukautetun CompletionHandler instance. Kun vetoamme accept(), se palaa välittömästi., Huomaa, että tämä esimerkki on erilainen ServerSocket luokka Listing 1; ottaa huomioon, että accept() menetelmä estetty, kunnes asiakas on liitetty, AsynchronousServerSocketChannel accept() menetelmä käsittelee sitä meille.

loppuun handler

seuraava vastuulla on luoda CompletionHandler luokan ja antaa täytäntöönpanon completed() ja failed() menetelmiä., completed() menetelmää kutsutaan, kun AsynchronousServerSocketChannel saa yhteyden asiakkaan ja se sisältää AsynchronousSocketChannel asiakkaalle. completed() ensimmäinen menetelmä hyväksyy yhteyden AsynchronousServerSocketChannel ja sitten alkaa kommunikoida asiakkaan kanssa. Ensimmäinen asia, että se on kirjoittaa ”Hello” – viesti: Se rakentaa string, muuntaa tavu array, ja sitten syöttää sen ByteBuffer.wrap() rakentaa ByteBuffer., ByteBuffer voidaan sitten kulunut AsynchronousSocketChannel’s write() menetelmä.

lue asiakkaan, luomme uuden ByteBuffer vetoamalla sen allocate(4096) (joka luo 4K buffer), sitten voimme vedota AsynchronousSocketChannel’s read() menetelmä. read() palauttaa Future<Integer> johon voimme vedota get() hakea tavujen lukea asiakasta., Tässä esimerkissä, me pass get() timeout-arvo 20 sekuntia: jos emme saa vastausta 20 sekuntia sitten get() tapa heittää TimeoutException. Meidän sääntö tämän echo server on, että jos noudatamme 20 sekuntia hiljaisuutta niin lopetamme keskustelun.

seuraavaksi tarkistamme puskurin sijainnin, joka on asiakkaalta saadun viimeisen tavun sijainti. Jos asiakas lähettää tyhjän rivin, saamme kaksi tavua: kuljetuspalautuksen ja rivisyötön., Tarkistuksella varmistetaan, että jos asiakas lähettää tyhjän rivin, otamme sen indikaattorina siitä, että asiakas on lopettanut keskustelun. Jos meillä on merkityksellisiä tietoja, sitten soitamme ByteBuffer’s flip() tapa valmistaa sen lukemiseen. Me luoda väliaikainen tavu array pitää tavujen lukea asiakasta ja sitten vedota ByteBuffer’s get() load data tavu array. Lopuksi, me muuntaa tavu array string luomalla uusi String instance., Me kaiku linjaa takaisin asiakkaalle muuntamalla merkkijono, tavu array, ohimennen, että voit ByteBuffer.wrap() menetelmä ja vetoamalla AsynchronousSocketChannel’s write() menetelmä. Nyt me clear() ByteBuffer, joka recall tarkoittaa, että se sijoittaa position nollaan ja laittaa ByteBuffer kirjoitussuojattuun tilaan, ja sitten me lue seuraava rivi asiakkaalta.,

ainoa asia olla tietoinen on, että main() metodi, joka luo palvelin, määrittää myös 60 sekunnin ajastin, jos haluat pitää sovelluksen käynnissä. Koska AsynchronousSocketChannel’s accept() metodi palauttaa välittömästi, jos meillä ei ole Thread.sleep() sitten meidän sovellus pysähtyy välittömästi.,

testata tätä ulos, käynnistää palvelimen ja muodostaa siihen yhteyden käyttämällä telnet-asiakas:

telnet localhost 5000

Lähettää muutaman jousille palvelimen, huomaa, että ne toistetaan takaisin sinulle, ja sitten lähettää tyhjä rivi lopettaa keskustelun.

lopuksi

tässä artikkelissa olen esitellyt kaksi lähestymistapoja socket-ohjelmointi Java: perinteinen lähestymistapa käyttöön Java 1.0 ja uudemmat, ei-esto NIO NIO ja.2 lähestymistapoja käyttöön Java 1.4-ja Java 7, vastaavasti., Olet nähnyt useita toistojen Java socket asiakas-ja Java-socket server esimerkki, joka osoittaa sekä hyödyllisyys perus Java I/O ja joitakin tilanteita, joissa ei-esto I/O-parantaa Javan socket-ohjelmointi malli. Käyttämällä ei-esto I/O, voit ohjelmoida Java-verkottunut sovelluksia käsittelemään useita samanaikaisia yhteyksiä ilman, hallita useita lanka kokoelmat. Voit myös hyödyntää uuden palvelimen skaalautuvuus, joka on rakennettu NIO NIO ja.2.

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *