Programare Php Socket

Prizele sunt extrem de convenabile, dar în același timp înțelese puțin tehnologia de interacțiune dintre două procese din rețea. Aceste procese pot exista pe aceeași mașină, comunicând între ele printr-o priză locală, concepute pentru interacțiunea dintre procese sau pe diferite mașini prin Internet. Deși tema socketurilor este foarte extinsă, acest articol prezintă elementele de bază care sunt necesare pentru a utiliza extensii PHP pentru scrierea propriilor servere și a clienților socket.







Pentru a utiliza socluri, PHP trebuie să fie compilat cu opțiunea ./configure --enable-sockets sau trebuie să încărcați dinamic extensiile de suport socket.

Rețineți că exemplele prezentate mai târziu în acest articol sunt proiectate să ruleze direct din mediul shell folosind versiunea de linie de comandă PHP. Deși pot fi difuzate într-un browser Web, acest lucru nu este recomandat. În cazul scripturilor create de serverele socket, aplicația lor poate fi demonstrată folosind orice program care poate stabili o conexiune de rețea prin intermediul unor prize, de exemplu, telnet (care este de fapt recomandat).

Noțiuni de bază despre prize

Deși există mai multe tipuri de prize, toate funcțiile de prize bazate pe același principiu de bază - programul de achiziție a datelor în programul A. Acest program poate rula pe aceeași mașină, folosind IPC (Interprocess Communication - IPC), sau telecomanda (cum ar fi un server Web și browsere).

Prizele pot fi fiabile, realizând tot ceea ce este necesar pentru a asigura transferul de date de la punctul A la punctul B (TCP). sau nesigure atunci când datele sunt transmise fără o garanție de livrare (UDP).

Prizele sunt, de asemenea, "blocante" și "non-blocante". Blocarea soclurilor determină ca aplicația dvs. să aștepte până când datele sunt disponibile, în timp ce prizele de blocare nu se blochează. Deși, după cum se va arăta mai târziu, toate soclurile sunt bidirecționale, există încă o diferență între prizele client și server.

Vom considera soclurile TCP de Internet, deoarece acestea sunt cele mai utilizate astăzi. Cu toate acestea, conceptele și exemplele de cod furnizate aici sunt aplicabile majorității operațiunilor de socket-uri.

Crearea unui nou soclu

Indiferent de tipul de soclu care este creat (client sau server), toate sunt inițializate în același mod - folosind funcția socket_create (). Sintaxa acestei funcții este după cum urmează:

socket_create ($ domain, $ type, $ protocol);

Domeniul $ este tipul de soclu care este creat și trebuie să ia una dintre valorile enumerate în tabelul de constante de domeniu pentru conexiuni socket

$ type - tipul de interacțiune care va fi implementat prin socket; valorile admise sunt date în tabelul constantelor tipurilor de soclu

Protocolul $ este protocolul utilizat de acest soclu. Acest parametru poate fi orice număr de protocol valid (vezi. Getprotobyname Funcția ()) sau SOL_UDP constantă sau SOL_TCP pentru conexiuni TCP / UDP.

Ca rezultat, această funcție returnează fie o resursă reprezentând soclul creat, fie o valoare booleană false în cazul unei erori.

Funcția socket_create () este primul apel pentru orice interacțiune socket. care inițializează resursa socket-ului utilizată în operațiile ulterioare. Astfel, prizele pot fi utilizate atât local - pentru IPC, cât și de la distanță - în stil client / server. Contextul unei anumite aplicații socket se numește domeniul său. Domeniile disponibile în PHP care sunt transmise funcției socket_create () în parametrul $ domain sunt specificate prin constante din tabel:

Citiți datele pentru lungimea specificată sau până când se întâlnește caracterul de linie nouă (\ r sau \ n).

Următorul exemplu arată modul de utilizare a soclurilor pentru a prelua pagina index a unui site Web, tot ceea ce a fost discutat mai sus este inclus. Extragerea paginii index se face prin trimiterea unei cereri simple HTTP HTTP GET, urmată de citirea rezultatului într-o variabilă.

După examinarea acestui exemplu simplu de soclu client, acum să ne uităm la cealaltă parte a conexiunii - un server bazat pe socket-uri simple.







Crearea socketurilor pentru server

socket_bind ($ socket, $ adresa [, $ port]);

Al doilea pas: configurați soclul pentru a asculta traficul pentru a încerca să se conecteze la acesta. Acest lucru se face cu funcția socket_listen ():

În cazul în care $ socket este un soclu anterior legat, care trebuie să fie activat pentru ascultare. Parametrul opțional de backlog $ este utilizat pentru a crea o coadă specificând numărul maxim permis de conexiuni de intrare la coadă. Dacă acest parametru nu este specificat, atunci socket-ul care încearcă să se conecteze va primi o refuzare a serviciului până când socketul pentru server este disponibil. Ca rezultat, această funcție returnează o valoare booleană indicând succesul configurației socketului pentru ascultare.

Al treilea și ultimul pas în crearea unui soclu de server este de a da o comandă pentru a accepta conexiunile primite. Acest lucru este realizat de socket_accept ():

Unde socketul $ este un soclu legat, inclus în sesiunea de ascultare, care trebuie să accepte conexiuni.

În timpul funcționării, această funcție nu va reveni la control până când conexiunile de intrare nu sunt complete. Odată instalat, funcția va returna noua resursă socket folosită pentru conexiune. Dacă socketul specificat în parametrul $ socket este configurat ca non-blocant, socket_accept () întoarce întotdeauna false imediat.

Resursa socket-ului returnată de funcția socket_accept () nu poate fi reutilizată deoarece servește doar o conexiune curentă specifică. Un soclu trecut la el în parametrul $ socket, cu toate acestea, poate fi refolosit.

Listarea de mai jos creează un server socket simplu care acceptă o singură conexiune, un maxim de 1024 octeți din fluxul de intrare și afișează acest flux către utilizator.

Crearea unui server bazat pe socket-uri simple

Pe calculatorul meu, acest script se află în dosarul Denver pe drum: C: \ webservere \ acasă \ app.loc \ www \ prize \ test.php
Acum, dacă rulați scriptul din linia de comandă, astfel încât Makar: C: \ webservere \ acasă \ app.loc \ www \ prize> test.php PHP, vom vedea în următoarea linie de comandă:

Serverul ne va trimite solicitarea și antetele în răspuns:

La linia de comandă, vom vedea noile date

Și, de asemenea, un nou prompt de intrare - o mărturie că procesul a fost întrerupt. De asemenea, puteți să o verificați cu comanda netstat -a și asigurați-vă că portul 4545 nu este prezent în listă.

Pentru a crea un server al cărui socluri ascultă în porturi numerotate sub 1000, acest utilizator trebuie să aibă drepturi administrative în sistem. Trebuie de asemenea remarcat faptul că scenariul de mai sus nu se finalizează până când nu se creează o conexiune, ceea ce poate crea impresia de a "închide".

Lucrați simultan cu mai multe prize

În listarea de pe pagina anterioară, a fost prezentat un server pe bază de prize. Cu toate acestea, nu este foarte convenabil pentru scopuri reale, deoarece se poate face o singură conexiune în același timp. Pentru a crea un server socket mai convenabil, trebuie să învățați cum să lucrați simultan cu mai multe prize. Pentru aceasta, aveți nevoie de funcția socket_select (), a cărei sintaxă arată astfel:

socket_select ($ read, $ write, $ eroare, $ sec [, $ usec]);

Aici $ read, $ write și $ error - variabilele trecute prin referință (mai precis, matrice). Aceste matrice trebuie să conțină o listă cu toate prizele de care aveți nevoie pentru a monitoriza citirea, scrierea și interceptarea erorilor. De exemplu, plasarea unui soclu activ într-o matrice trecută în parametrul $ read determină PHP să verifice dacă există date citite în acest soclu. Ultimii doi parametri, $ sec și opțional $ usec, sunt valorile timeout-ului care controlează cât timp funcția socket_select () va aștepta înainte de a reveni la controlul PHP.

Ca rezultat al socket_select () returnează un număr întreg care specifică numărul total de prize modificate (din lista transmisă) și modifică matrice $ citire, scriere $ și $ eroare, eliminarea lor din elementele care nu au fost modificate. Ca urmare, fiecare dintre aceste matrice va conține doar o listă de prize care îndeplinesc următoarele cerințe:

Prizele listate în matricea de citire $ conțin date care trebuie citite de la acestea sau conexiuni primite către ele.

Prizele listate în matricea de scriere $ conțin datele care trebuie scrise în ele.

Prizele listate în matricea de erori $ conțin erori care trebuie procesate.

În cazul unei erori, socket_select () returnează o valoare booleană a false.

Acest soclu va fi adăugat și în matricea de citire $, iar buclă infinită gestionată va fi pornită. Apoi, utilizând funcția socket_select (), mufa principală va fi monitorizată pentru conexiuni noi. Atunci când apare o conexiune nouă, funcția socket_accept () se numește automat, ceea ce creează un nou socket de server utilizat pentru a comunica cu clientul conectat.

Acest nou soclu conectat fie apoi monitorizate prin același socket_select apel () (prin adăugarea la aceeași matrice, care a fost deja adăugat nostru priza principală) și logica specifică aplicației, care asigură funcționalitatea serverelor noastre. Următorul exemplu prezintă un exemplu de lucru al unui server simplu care acceptă un număr configurabil de conexiuni.

Crearea unui multi-server pe PHP

Lista de mai sus prezintă câteva limitări ale mecanismului de script PHP, care necesită o soluție oarecum mai complexă sub forma socket_select ():

$ num_changed = socket_select ($ citește, $ NULL, $ NULL, 0, 10);

Rețineți utilizarea unei variabile numite $ NULL. În PHP, pentru funcțiile care acceptă parametrii prin referință (așa cum face socket_select () în prima aproximare), NULL este o valoare nevalidă. Cu toate acestea, trecerea NULL ca unul sau mai mulți parametri de listă este complet corectă. Prin urmare, o soluție este de a seta variabila $ NULL la NULL:

Și transferul ulterior al funcției socket_select ().







Articole similare

Trimiteți-le prietenilor: