Sunteți pe pagina 1din 11

Programarea n reea Socket-uri

1. Scopul lucrrii Scopul acestei lucrri este insuirea tehnicilor de programare n reea utiliznd socket-uri. 2. onsideraii teoretice alculatoarele conectate in reea comunic ntre ele utiliznd protocoalele ! P "!ransport ontrol Protocol# i $%P "$ser %atagram Protocol# con&orm diagramei'

(igura 1. )i*elele de omunicare n reea Pentru realizarea unor programe care comunic in reea n +a*a, se utilizeaz clasele din pachetul +a*a.net . -cest pachet o&er clasele necesare pentru realizarea unor programe de reea independente de sistemul de operare. .n ta/elul urmtor sunt prezentate principalele clase care sunt utilizate pentru construirea unor programe de reea. Class
URL URLConnection Socket ServerSocket DatagramSocket DatagramPacket InetAddress

Scop 0eprezint un $01 0eturneaz continutul adresat de o/iectele URL reaz un socket ! P reaz un socket ser*er ! P reaz un socket $%P 0eprezint o datagrama trimis printr-un o/iect
DatagramSocket

0eprezint numele unui pc din reea, respecti* .P-ul corespunztor

2a*a o&er dou a/ordri di&erite pentru realizarea de programe de reea. ele dou a/ordri sunt asociate cu clasele' - Socket, %atagramSocket i Ser*erSocket - $01, $013ncoder i $01 onnection Programarea prin socket-uri reprezint o a/ordare de ni*el +os, prin care, dou calculatoare pot &i conectate pentru a realiza schim/ de date. a principiu de /aza, programarea prin socketuri &ace posi/il comunicarea n mod &ull-duple4 ntre client i ser*er. omunicarea se &ace prin &lu4uri de octei. Pentru ca comunicarea s se des&oare corespunztor, programatorul *a tre/ui s implementeze un protocol de comunicaie "reguli de dialog#, pe care clientul i ser*erul l *or urma. Definitia socket-ului: $n socket reprezint un punct de cone4iune ntro reea ! P5.P. nd dou programe a&late pe dou calculatoare n reea doresc s comunice, &iecare dintre ele utilizeaz un socket. $nul dintre programe "ser*erul# *a deschide un socket si *a atepta cone4iuni, iar cellalt program "clientul#, se *a conecta la ser*er i ast&el schim/ul de in&ormaii poate ncepe. Pentru a sta/ili o cone4iune, clientul *a tre/ui s cunoasc adresa destinaiei " a pc-ului pe care este deschis socket-ul# i portul pe care socketul este deschis. Principalele operaii care sunt &acute de socket-uri sunt' - conectare la un alt socket - trimitere date - recepionare date - inchidere cone4iune - acceptare cone4iuni 3. Desfurarea lucrrii 3.1. Program client-server Pentru realizarea unui program client-ser*er se utilizeaz clasele Ser*erSocket i Socket. Programul ser*er *a tre/ui s deschid un port i s atepte cone4iuni. .n acest scop este utilizat clas Ser*erSocket. .n momentul n care se creaz un o/iect Ser*erSocket se speci&ic portul pe care se *a iniia ateptarea. .nceperea ascultrii portuli se &ace apelnd metoda accept"#. .n momentul n care un client s-a conectat, metoda accept"# *a returna un o/iect Socket. 1a rndul su clientul pentru a se conecta la un ser*er, *a tre/ui s creeze un o/iect de tip Socket, care *a primi ca parametri adresa ser*erului i portul pe care acesta ateapt cone4iuni. -tt la ni*elul ser*erului ct i la ni*elul clientului, odat create o/iectele de tip Socket, se *or o/ine &lu4urile de citire i de scriere. .n acest scop se utilizeaza metodele get.nputStream"# i get6uptuStream"#. .n listingul urmtor este prezentat programul ser*er.
import +a*a.net.78

import +a*a.io.78 pu/lic class Ser*erSimplu 9 pu/lic static *oid main"String:; args# thro<s .634ception9 Ser*erSocket ss=null8 Socket socket=null8 tr>9 String line=??8 ss = ne< Ser*erSocket"1@AA#8 BBcreaza o/iectul ser*ersocket socket = ss.accept"#8 BBincepe asteptarea peportul 1@AA BBin momentul in care un client s-a conectat ss.accept"# returneaza BBun socket care identi&ica cone4iunea BBcreaza &lu4urile de intrare iesire Cu&&ered0eader in = ne< Cu&&ered0eader" ne< .nputStream0eader"socket.get.nputStream"###8 PrintDriter out = ne< PrintDriter" ne< Cu&&eredDriter"ne< 6utputStreamDriter" socket.get6utputStream"###,true#8 <hile"Eline.eFuals"?3)%?##9 line = in.read1ine"#8 BBciteste datele de la client out.println"?3 G6 ?Hline#8 BBtrimite date la client I Icatch"34ception e#9e.printStack!race"#8I &inall>9 ss.close"#8 i&"socketE=null# socket.close"#8 I I I

Programul client este prezentat n listingul urmtor'


import +a*a.net.78 import +a*a.io.78 pu/lic class lientSimplu 9 pu/lic static *oid main"String:; args#thro<s 34ception9 Socket socket=null8 tr> 9 BBcreare o/iect address care identi&ica adresa ser*erului .net-ddress address =.net-ddress.getC>)ame"?localhost?#8 BBse putea utiliza *arianta alternati*a' .net-ddress.getC>)ame"?12J.A.A.1?# socket = ne< Socket"address,1@AA#8 Cu&&ered0eader in = ne< Cu&&ered0eader" ne< .nputStream0eader" socket.get.nputStream"###8

BB 6utput is automaticall> &lushed BB /> PrintDriter' PrintDriter out = ne< PrintDriter" ne< Cu&&eredDriter" ne< 6utputStreamDriter" socket.get6utputStream"###,true#8 &or"int i = A8 i K 1A8 i HH# 9 out.println"?mesa+ ? H i#8 String str = in.read1ine"#8 BBtrimite mesa+ S>stem.out.println"str#8 BBasteapta raspuns I out.println"?3)%?#8 BBtrimite mesa+ care determina ser*erul sa inchida cone4iunea I catch "34ception e4# 9e4.printStack!race"#8I &inall>9 socket.close"#8 I I I

Pentru *eri&icare se *a starta ser*erul, dup care se *a starta clientul. 3.2 Server multifir -naliznd programul ser*er prezentat n seciunea anterioarm se o/ser* c acesta poate ser*i doar un singur client la un moment dat. Pentru ca ser*erul s poat ser*i mai muli clieni simultan, se *a utiliza programarea multi&ir. .deea de /az este simpl, i anume, ser*erul *a atepta cone4iuni prin apelarea metodei accept"#. .n momentul in care un client s-a conectat i metoda accept"# a returnat un Socket, se *a crea un &ir de e4ecuie care *a ser*i respecti*ul clientul, iar se*erul *a re*eni n ateptare. .n listingul urmtor este prezentat un ser*er multi&ir capa/il de a ser*i mai multi clieni simultan.
import +a*a.io.78 import +a*a.net.78 pu/lic class Ser*erLulti&ir 9 pu/lic static &inal int P60! = 1@AA8 *oid startSer*er"# 9 Ser*erSocket ss=null8 tr> 9 ss = ne< Ser*erSocket"P60!#8 <hile "true#

9 Socket socket = ss.accept"#8 ne< !ratare lient"socket#8 I Icatch".634ception e4# 9 S>stem.err.println"?3roare '?He4.getLessage"##8 I &inall> 9 tr>9ss.close"#8Icatch".634ception e42#9I I I pu/lic static *oid main"String args:;# 9 Ser*erLulti&ir sm& = ne< Ser*erLulti&ir"#8 sm&.startSer*er"#8 I I class !ratare lient e4tends !hread 9 pri*ate Socket socket8 pri*ate Cu&&ered0eader in8 pri*ate PrintDriter out8 !ratare lient"Socket socket#thro<s .634ception 9 this.socket = socket8 in = ne< Cu&&ered0eader"ne< .nputStream0eader"socket.get.nputStream"###8 out = ne< PrintDriter" ne< Cu&&eredDriter" ne< 6utputStreamDriter" socket.get6utputStream"####8 I pu/lic *oid run"# 9 tr> 9 <hile "true# 9 String str = in.read1ine"#8 i& "str.eFuals"?3)%?## /reak8 S>stem.out.println"?3choing' ? H str#8 out.println"str#8 IBB.<hile S>stem.out.println"?closing...?#8 I catch".634ception e# 9S>stem.err.println"?.6 34ception?#8I &inall> 9 tr> 9 socket.close"#8 Icatch".634ception e# 9S>stem.err.println"?Socket not closed?#8I I

IBB.run I

3.3. Server HTTP .n aceast sectiune este creat un ser*er G!!P care poate rspunde la cereri M3!. (unctia main"# din cadrul clasei GttpSer*er startaeaz un &ir de e4ecuie. .n cadrul acestui &ir se instaniaz un o/iect Ser*erSocket i se incepe ascultarea portului NA, care este portul standard pentru protocolul G!!P. .n momentul n care apare o cerere "un client se conecteaz pe portul NA# metoda accept"# *a returna un o/iect Socket. .n continuare se creaz un o/iect Preces0eFuest "care este de tip &ir de e4cutie#, care *a primi ca parametru, o/iectul Socket returnat de metoda accept"#. %up crearea o/iectului Proces0eFuest, ser*erul re*ine n ateptare i *a putea ser*i ali clieni. lasa Proces0eFuest implementeaz o *ersiune simpli&icat a protocolului G!!P. .n cadrul constructorului clasei Proces0eFuest se creaz &lu4urile de intrare 5 ieire, dup care este startat &irul de e4ecuie. .n cadrul &irului de e4ecuie este analizat cererea primit de la client , i n cazul n care aceasta este o cerere *alid de tip M3!, atunci se *a transmite ctre client resursa solicitat.
import +a*a.io.78 import +a*a.net.78 class GttpSer*er e4tends !hread 9 BBportul standard pri*ate &inal static int P60! = NA8 pri*ate &inal String ini onte4t=?c'BtempBSer*erG!!PB<e/docs?8 pri*ate /oolean ali*e8 pri*ate Ser*erSocket ss8 BBconstructor GttpSer*er"#thro<s 34ception9 S>stem.out.println"?Start ser*er http.?#8 ss = ne< Ser*erSocket"P60!#8 ali*e=true8 start"#8 I pu/lic *oid run"#9 <hile"ali*e#9 BBasteapta cone4iuni tr>9 S>stem.out.println"?Ser*er asteapta...?#8 ne< Proces0eFuest"ss.accept"#,ini onte4t#8 Icatch".634ception e#9S>stem.err.println"?306-03 6)3 !-03'?He.getLessage"##8I BB..reia /ucla de asteptare dupa ce am creat un &ir pentru client I

S>stem.out.println"?S!6P S30O30?#8 I pu/lic static *oid main"String:; args#thro<s 34ception 9 tr>9 ne< GttpSer*er"#8 Icatch"34ception e#9e.printStack!race"#8I I I import +a*a.net.78 import +a*a.io.78 import +a*a.util.78 class Proces0eFuest e4tends !hread 9 pri*ate PrintDriter outStr8 pri*ate Cu&&ered0eader inStr8 pri*ate Socket s8 pri*ate %ata6utputStream dout8 pri*ate String ini onte4t8 Proces0eFuest"Socket s, String i onte4t#9 tr>9 outStr = ne< PrintDriter"ne< 6utputStreamDriter"s.get6utputStream"##,true#8 inStr = ne< Cu&&ered0eader"ne< .nputStream0eader"s.get.nputStream"###8 dout = ne< %ata6utputStream"s.get6utputStream"##8 ini onte4t = i onte4t8 this.s = s8 start"#8 Icatch".634ception e# 9S>stem.err.println"?306-03 6)3 !-03' ?He.getLessage"##8I I pu/lic *oid run"#9 tr>9 String &ile)ame=null8 String reFuest = inStr.read1ine"#8 S>stem.out.print"reFuest#8 i&"reFuest.last.nde46&"?M3!?#==A# &ile)ame = interpretM3!"reFuest#8 else thro< ne< 34ception"?C-$?#8 />te:; data = read(ile"&ile)ame#8 dout.<rite"data#8 dout.&lush"#8 I catch".634ception e#9outStr.println"?KG!L1PKC6%QPKPPRAS (or/iddenKPPKBC6%QPKBG!L1P?#8I catch"34ception e2#9outStr.println"?KG!L1PKC6%QPKPP?He2.getLessage"# H?KPPKBC6%QPKBG!L1P?#8I &inall>9 tr>9s.close"#8Icatch"34ception e#9I I I

pri*ate String interpretM3!"String rFst# thro<s 34ception9 String!okenizer str! = ne< String!okenizer"rFst#8 String tmp=??8 String &ile)=ini onte4t8 tmp=str!.ne4t!oken"#8 i&"Etmp.eFuals"?M3!?## thro< ne< 34ception"? omanda M3! in*alida .?#8 tmp=str!.ne4t!oken"#8 i&""tmp.eFuals"?B?## TT "tmp.endsDith"?B?### 9 &ile) = &ile)HtmpH?inde4.htm?8 S>stem.err.println"? 30303'?H&ile)#8 return &ile)8 I &ile) = &ile)H tmp8 S>stem.err.println"? 30303'?H&ile)#8 return &ile)8 I pri*ate />te:; read(ile"String &ile)# thro<s 34ception9 &ile).replace"UBU,U55U#8 (ile & = ne< (ile"&ile)#8 i&"E&.can0ead"## thro< ne< 34ception"?(isierul ?H&ile)H? nu poate &i citit?#8 (ile.nputStream &str = ne< (ile.nputStream"&#8 />te:; data = ne< />te:&str.a*aila/le"#;8 &str.read"data#8 return data8 I I

Pentru *eri&icarea programului anterior se *a modi&ica *aria/ila ini onte4tm din cadrul clasei G!!PSer*er, ast&el nct aceasta s indice calea corect catre conte4tul iniial "directorul unde se a&l toate resursele pe care clientul le poate accesa#. 3.5 Trimiterea obiectelor prin soc et-uri Lecanismul de serializare pune la dispoziia programatorului o metod prin care un o/iect poate &i sal*at pe disc i restaurat atunci cand este ne*oie. !ot prin acelai mecanism un o/iect poate &i transmis la distanta catre o alt main utiliznd socketurile. Pentru a putea serializa un o/iect acesta *a tre/ui s implementeze inter&aa Serializable. Pentru scrierea i citirea o/iectelor serializate se utilizeaz &lu4urile de intrare B ieire ' ObjectInputStream si ObjectOutputStream. 1istingul urmtor prezint modul in care se poate serializa B deserializa un o/iect.
import +a*a.io.78 import +a*a.net.78 pu/lic class Serial!est e4tends !hread9

pu/lic *oid run"#9 tr>9 Ser*erSocket ss = ne< Ser*erSocket"1@JJ#8 Socket s = ss.accept"#8 6/+ect.nputStream ois = ne< 6/+ect.nputStream"s.get.nputStream"##8 Pers p = "Pers#ois.read6/+ect"#8 S>stem.out.println"p#8 s.close"#8 ss.close"#8 Icatch"34ception e#9e.printStack!race"#8I I pu/lic static *oid main"String:; args# thro<s 34ception9 BBtrimite o/iect prin socket "ne< Serial!est"##.start"#8 Socket s = ne< Socket".net-ddress.getC>)ame"?localhost?#,1@JJ#8 6/+ect6utputStream oos = ne< 6/+ect6utputStream"s.get6utputStream"##8 Pers p = ne< Pers"?-lin?,1R#8 oos.<rite6/+ect"p#8 s.close"#8 I I class Pers implements Serializa/le9 String nume8 int *arsta8 Pers"String n, int *#9 nume = n8 *arsta = *8 I pu/lic String toString"#9 return ?Persoana' ?HnumeH? *asrta' ?H*arsta8 I I

34ist situaii n care n momentul in care se sel*eaza starea unui o/iect prin serializare, nu se dorete sal*are tuturor starilor o/iectului, respecti* nu se dorete sal*area sau transmiterea anumitor parametri ai o/iectului. Pentru a /loca serializarea unui atri/ut al unui o/iect serializa/il se utilizeaz cu*antul cheie transient. a. Plecnd de la listingul anterior relizati un program client i un program ser*er care transmit ntre ele o/iecte de tip Pers. b. -dugai n cadrul clasei Pers n &aa liniei V String nume; V cu*ntul cheie transient i o/ser*ai e&ectul acestei modi&icri.

3.!. Server "e timp #$DP% .n cadrul acestei seciuni este construit un ser*er de timp care *a trimite la cerere data curent ctre clienii care solicit acest lucru. %e asemenea este construit i clientul care acceseaz ser*iciile ser*erului de timp. 1a ni*elul ser*erului se creeaz un o/iect %atagramSocket, care *a primi ca parametru portul pe care ser*erul *a ncepe ascultarea. DatagramSocket socket = new DatagramSocket !"##$; .n continuare se construiete un o/iect %atagramPacket, care *a &i utilizat de ctre ser*er pentru a recepiona cererea de la client. 6 dat construit o/iectul %atagramPacket, ser*erul *a ncepe ascultarea portului 1@JJ, prin in*ocarea metodei recei*e"#. b%te&' buf = new b%te&()*'; Datagram+acket packet = new Datagram+acket buf,buf.lengt-$; socket.recei.e packet$; .n momentul n care un client dorete s apeleze la ser*iciile ser*erului, acesta *a trimite un pachet ctre ser*er. Ser*erul citete din cadrul pachetului portul i adresa clientului, i i *a trimite acestuia un pachet ce conine data curent. Inet/00ress a00ress = packet.get/00ress $; int port = packet.get+ort $; buf = new Date $$.toString $$.get1%tes $; packet = new Datagram+acket buf,buf.lengt-,a00ress,port$; socket.sen0 packet$; $n client, pentru a se conecta la ser*er, tre/uie s creeze un o/iect %atagramSocket, i s trimit un pachet ctre ser*er. Spre deose/ire de ser*er, clientul nu este o/ligat s speci&ice nici un port n momentul creierii o/iectului %atagramSocket, ntruct se atri/uie automat un port li/er respecti*ului o/iect.
import +a*a.io.78 import +a*a.net.78 import +a*a.util.78 pu/lic class !imeSer*er e4tends !hread9 /oolean running=true8 pu/lic !imeSer*er"# 9start"#8I pu/lic *oid run"#9 tr>9 %atagramSocket socket = ne< %atagramSocket"1@JJ#8 <hile"running#9 BBasteapta client />te:; /u& = ne< />te:2WX;8 %atagramPacket packet = ne< %atagramPacket"/u&,/u&.length#8 socket.recei*e"packet#8 BBciteste adresa si portul clientului .net-ddress address = packet.get-ddress"#8

int port = packet.getPort"#8 BBtrimite un repl> catre client /u& = ""ne< %ate"##.toString"##.getC>tes"#8 packet = ne< %atagramPacket"/u&,/u&.length,address,port#8 socket.send"packet#8 I Icatch"34ception e4#9e4.printStack!race"#8I I pu/lic static *oid main"String:; args# 9 !imeSer*er timeSer*er1 = ne< !imeSer*er"#8 I I import +a*a.io.78 import +a*a.net.78 import +a*a.util.78 pu/lic class lient 9 pu/lic static *oid main"String:; args# 9 tr>9 %atagramSocket socket = ne< %atagramSocket"#8 />te:; /u& = ne< />te:2WX;8 %atagramPacket packet = ne< %atagramPacket"/u&,/u&.length, .net-ddress.getC>)ame"?localhost?#,1@JJ#8 socket.send"packet#8 packet = ne< %atagramPacket"/u&,/u&.length#8 socket.recei*e"packet#8 S>stem.out.println"ne< String"packet.get%ata"###8 Icatch"34ception e4#9e4.printStack!race"#8I I I

&. 'ntrebri si probleme a. .n ce scop sunt utilizate clasele Ser*erSocket i SocketY /. e clas este utilizat n +a*a pentru a identi&ica un calculator din reea Y c. $tiliznd programarea prin socketuri construii un program simplu de tip chat.

S-ar putea să vă placă și