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()
.
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:
- luo pistorasia www-palvelimelle kuunteluun portissa 80.
- Saada
PrintStream
palvelimelle ja lähettää pyynnönGET PATH HTTP/1.0
, jossaPATH
on pyydetty resurssi palvelimelle., Jos esimerkiksi haluaisimme avata verkkosivuston juuren, polku olisi/
. - Saada
InputStream
palvelimeen, kääri seBufferedReader
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:
- Luoda
ServerSocket
, jossa määritellään sataman kuunnella. - Vedota
ServerSocket
’saccept()
tapa kuunnella määritetty portti asiakas-yhteys. - Kun asiakas ottaa yhteyden palvelimeen,
accept()
metodi palauttaaSocket
jonka kautta palvelin voi kommunikoida asiakkaan kanssa., Tämä on samaSocket
luokkaa, että me käytetään meidän asiakas, niin prosessi on sama: saadaInputStream
lukea asiakasta jaOutputStream
kirjoittaa asiakkaan. - Jos server on skaalautuva, haluat siirtää
Socket
toiseen lanka prosessia niin, että palvelin voi jatkaa kuuntelemalla muita yhteyksiä. - Kutsu
ServerSocket
’saccept()
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ää ServerSocketFactory
s. 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:
- Kirjoita tiedot puskuriin
- Soita buffer
flip()
tapa valmistaa sitä lukeminen - Lue tietoja buffer
- Soita buffer
clear()
taicompact()
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.