Cum se configurează smartphone-uri și PC-uri. Portal informativ
  • Acasă
  • Fier
  • Aplicație tcp ip client server. Aplicație client-server pe un socket de flux TCP

Aplicație tcp ip client server. Aplicație client-server pe un socket de flux TCP

Aplicație client-server pe un socket de flux TCP

Următorul exemplu utilizează TCP pentru a furniza fluxuri de octeți bidirecționale ordonate și fiabile. Să construim o aplicație completă care să includă un client și un server. Mai întâi, demonstrăm cum să construim un server folosind socket-uri de flux TCP și apoi o aplicație client pentru a testa serverul nostru.

Următorul program creează un server care primește cereri de conectare de la clienți. Serverul este construit sincron, prin urmare, execuția firului este blocată până când serverul acceptă să se conecteze cu clientul. Această aplicație demonstrează un server simplu care răspunde unui client. Clientul încheie conexiunea prin trimiterea unui mesaj către server .

Server TCP

Crearea structurii serverului este prezentată în următoarea diagramă funcțională:

Iată codul complet pentru programul SocketServer.cs:

// SocketServer.cs folosind System; folosind System.Text; folosind System.Net; folosind System.Net.Sockets; namespace SocketServer ( clasa Program ( static void Main(string args)) ( // Setați punctul final local pentru socket IPHostEntry ipHost = Dns.GetHostEntry("localhost"); IPAddress ipAddr = ipHost.AddressList; IPEndPoint ipEndPoint = nou IPEndPoint(ipAddr, 11000); // Creați un socket Tcp/Ip Socket sListener = new Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp); // Atribuiți socket-ul la punctul final local și ascultați socketurile de intrare încercați ( sListener.Bind( ipEndPoint); sListener. Listen(10); // Începe să asculte pentru conexiuni în timp ce (adevărat) ( ​​Console.WriteLine ("Se așteaptă o conexiune pe portul (0)", ipEndPoint); // Programul se întrerupe, așteptând o conexiune de intrare Socket handler = sListener.Accept(); string data = null; // Am așteptat clientul care încearcă să se conecteze la noi byte bytes = new byte; int bytesRec = handler.Receive(bytes); data += Encoding. UTF8.GetString(bytes, 0, bytesRec); // Afișează datele pe consola Console.Write("Text primit: " + date + "\n\n"); // Trimiteți un răspuns către client\ string reply = "Vă mulțumim pentru cerere în " + data.Length.ToString() + " caractere"; byte msg = Encoding.UTF8.GetBytes(răspuns); handler.Send(msg); if (data.IndexOf(" ") > -1) ( Console.WriteLine("Serverul a încheiat conexiunea cu clientul."); break; ) handler.Shutdown(SocketShutdown.Both); handler.Close(); ) ) catch (Excepție ex) ( Console.WriteLine (ex.ToString()); ) în cele din urmă ( Console.ReadLine(); ) ) ) )

Să ne uităm la structura acestui program.

Primul pas este să setați socket-ul la un punct final local. Înainte de a deschide o priză pentru a asculta conexiuni, trebuie să pregătiți o adresă de punct final local pentru aceasta. O adresă unică de service TCP/IP este determinată de combinația dintre adresa IP a gazdei cu numărul portului de service, care creează punctul final de service.

Clasa Dns oferă metode care returnează informații despre adresele de rețea acceptate de un dispozitiv din rețeaua locală. Dacă un dispozitiv LAN are mai multe adrese de rețea, clasa Dns returnează informații despre toate adresele de rețea, iar aplicația trebuie să selecteze adresa corespunzătoare pentru a o servi din matrice.

Să creăm un IPEndPoint pentru server combinând prima adresă IP a computerului gazdă obținută din metoda Dns.Resolve() cu numărul portului:

IPHostEntry ipHost = Dns.GetHostEntry("localhost"); IPAddress ipAddr = ipHost.AddressList; IPEndPoint ipEndPoint = nou IPEndPoint(ipAddr, 11000);

Aici clasa IPEndPoint reprezintă localhost pe portul 11000. În continuare, creăm un socket de flux cu o nouă instanță a clasei Socket. După ce am configurat un punct final local pentru a asculta conexiunile, putem crea un socket:

Socket sListener = socket nou (ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

Transfer AdresăFamilie specifică schemele de adresare pe care o instanță a clasei Socket le poate folosi pentru a rezolva o adresă.

În parametru SocketType Socketurile TCP și UDP sunt diferite. În el puteți defini, printre altele, următoarele valori:

Dgram

Suporta datagrame. Valoarea Dgram necesită specificarea Udp pentru tipul de protocol și InterNetwork în parametrul familiei de adrese.

Brut

Acceptă accesul la protocolul de transport de bază.

Curent

Suportă prize de flux. Valoarea Stream necesită ca Tcp să fie specificat pentru tipul de protocol.

Al treilea și ultimul parametru specifică tipul de protocol necesar pentru soclu. În parametru ProtocolType Puteți specifica următoarele valori cele mai importante - Tcp, Udp, Ip, Raw.

Următorul pas ar trebui să fie alocarea prizei folosind metoda Lega(). Când un socket este deschis de către un constructor, nu i se atribuie un nume, doar un handle este rezervat. Metoda Bind() este apelată pentru a atribui un nume socket-ului serverului. Pentru ca un socket client să identifice un socket de flux TCP, programul server trebuie să dea socket-ului un nume:

SListener.Bind(ipEndPoint);

Metoda Bind() leagă un socket la un punct final local. Metoda Bind() trebuie apelată înainte de orice încercare de a apela metodele Listen() și Accept().

Acum, după ce ai creat un socket și i-ai asociat un nume, poți asculta mesajele primite folosind metoda Asculta(). În starea de ascultare, socket-ul va asculta încercările de conectare de intrare:

SListener.Listen(10);

Parametrul definește restante, indicând numărul maxim de conexiuni care așteaptă în coadă. În codul de mai sus, valoarea parametrului permite să se acumuleze până la zece conexiuni în coadă.

În starea de ascultare, trebuie să fiți gata să acceptați să vă conectați cu clientul, pentru care este folosită metoda Accept(). Această metodă obține o conexiune client și finalizează asocierea numelui client și server. Metoda Accept() blochează firul de execuție al programului apelant până când ajunge o conexiune.

Metoda Accept() elimină prima cerere de conexiune din coada de cereri în așteptare și creează un nou socket pentru a o procesa. Deși este creat un nou socket, soclul original continuă să asculte și poate fi utilizat cu multi-threading pentru a accepta mai multe cereri de conexiune de la clienți. Nicio aplicație server nu ar trebui să închidă un soclu de ascultare. Trebuie să continue să funcționeze alături de socket-urile create prin metoda Accept pentru a procesa cererile primite de la clienți.

While (true) ( ​​​​Console.WriteLine("Se așteaptă o conexiune pe portul (0)", ipEndPoint); // Programul se întrerupe în timp ce așteaptă o conexiune de intrare Socket handler = sListener.Accept();

Odată ce clientul și serverul au stabilit o conexiune unul cu celălalt, mesajele pot fi trimise și primite folosind metodele Trimite()Și A primi() Clasa Priză.

Metoda Send() scrie datele de ieșire în soclul conectat. Metoda Receive() citește datele primite în soclul de flux. Când utilizați un sistem bazat pe TCP, trebuie stabilită o conexiune între socketuri înainte de a executa metodele Send() și Receive(). Protocolul exact dintre cele două entități care comunică trebuie definit în prealabil pentru ca aplicațiile client și server să nu se blocheze reciproc neștiind cine ar trebui să-și trimită mai întâi datele.

Când schimbul de date între server și client este finalizat, trebuie să închideți conexiunea folosind metodele Închide()Și Închide():

Handler.Shutdown(SocketShutdown.Both); handler.Close();

SocketShutdown este o enumerare care conține trei valori de oprit: Ambii- oprește trimiterea și primirea de date prin priză, A primi- oprește soclul să primească date și Trimite- oprește trimiterea de date prin socket.

Socket-ul este închis prin apelarea metodei Close(), care setează și proprietatea Connected a socket-ului la false.

Client TCP

Funcțiile care sunt folosite pentru a crea o aplicație client sunt mai mult sau mai puțin similare cu o aplicație server. Ca și în cazul serverului, aceleași metode sunt utilizate pentru a determina punctul final, a instanția socket-ul, a trimite și a primi date și a închide socket-ul.

Serverele care implementează aceste protocoale într-o rețea corporativă oferă clientului o adresă IP, gateway, mască de rețea, servere de nume și chiar o imprimantă. Utilizatorii nu trebuie să își configureze manual gazdele pentru a utiliza rețeaua.

Sistemul de operare QNX Neutrino implementează un alt protocol de auto-configurare numit AutoIP, care este un proiect al IETF Auto-Configuration Committee. Acest protocol este utilizat în rețelele mici pentru a atribui adrese IP locale de legătură gazdelor. Protocolul AutoIP determină independent adresa IP locală la legătura, folosind o schemă de negociere cu alte gazde și fără a contacta un server central.

Folosind protocolul PPPoE

Abrevierea PPPoE înseamnă Point-to-Point Protocol over Ethernet. Acest protocol încapsulează date pentru transmisie printr-o rețea Ethernet cu o topologie cu punte.

PPPoE este o specificație pentru conectarea utilizatorilor Ethernet la Internet printr-o conexiune în bandă largă, cum ar fi o linie digitală de abonat închiriată, un dispozitiv fără fir sau un modem prin cablu. Utilizarea protocolului PPPoE și a unui modem în bandă largă oferă utilizatorilor rețelelor locale de computere acces individual, autentificat la rețelele de date de mare viteză.

Protocolul PPPoE combină tehnologia Ethernet cu protocolul PPP, creând efectiv o conexiune separată la un server la distanță pentru fiecare utilizator. Controlul accesului, contabilitatea conexiunii și selectarea furnizorului de servicii sunt determinate pentru utilizatori, nu pentru gazde. Avantajul acestei abordări este că nici compania de telefonie, nici furnizorul de servicii de internet nu trebuie să ofere suport special pentru aceasta.

Spre deosebire de conexiunile dial-up, conexiunile DSL și modem prin cablu sunt întotdeauna active. Deoarece conexiunea fizică la un furnizor de servicii de la distanță este partajată între mai mulți utilizatori, este necesară o metodă de contabilitate care să înregistreze expeditorii și destinațiile traficului și să taxeze utilizatorii. Protocolul PPPoE permite utilizatorului și gazdei de la distanță care participă la o sesiune de comunicare să învețe reciproc adresele de rețea în timpul unui schimb inițial numit detectare(descoperire). Odată ce o sesiune a fost stabilită între un utilizator individual și o gazdă la distanță (de exemplu, un furnizor de servicii Internet), sesiunea poate fi monitorizată în scopuri de acumulare. Multe case, hoteluri și corporații oferă acces public la Internet prin linii digitale de abonat folosind tehnologia Ethernet și protocolul PPPoE.

O conexiune prin protocolul PPPoE constă dintr-un client și un server. Clientul și serverul funcționează folosind orice interfață care este apropiată de specificațiile Ethernet. Această interfață este utilizată pentru a emite adrese IP clienților și pentru a asocia acele adrese IP cu utilizatorii și, opțional, cu stațiile de lucru, mai degrabă decât pentru autentificarea bazată pe stația de lucru. Serverul PPPoE creează o conexiune punct la punct pentru fiecare client.

Configurarea unei sesiuni PPPoE

Pentru a crea o sesiune PPPoE, ar trebui să utilizați serviciulpppoed. Modulio-pkt-*nOferă servicii de protocol PPPoE. Mai întâi trebuie să fugiio-pkt-*Cușofer potrivit. Exemplu:

Călătorie prin protocoale de rețea.

TCP și UDP sunt ambele protocoale de nivel de transport. UDP este un protocol fără conexiune cu livrare de pachete negarantată. TCP (Transmission Control Protocol) este un protocol orientat spre conexiune cu livrarea de pachete garantată. Mai întâi are loc o strângere de mână (Bună. | Bună. | Să discutăm? | Să mergem.), după care conexiunea se consideră stabilită. Apoi pachetele sunt trimise înainte și înapoi prin această conexiune (o conversație este în curs) și se verifică dacă pachetul a ajuns la destinatar. Dacă pachetul este pierdut sau a sosit, dar cu o sumă de control ruptă, atunci este trimis din nou („repetă, nu am auzit”). Astfel, TCP este mai fiabil, dar este mai complex din punct de vedere al implementării și, în consecință, necesită mai multe cicluri de ceas/memorie, ceea ce nu este cel mai puțin important pentru microcontrolere. Exemple de protocoale de aplicație care utilizează TCP includ FTP, HTTP, SMTP și multe altele.

TL;DR

HTTP (Hypertext Transfer Protocol) este un protocol de aplicație prin care serverul trimite pagini către browserul nostru. HTTP este acum utilizat pe scară largă pe World Wide Web pentru a prelua informații de pe site-uri web. Imaginea prezintă o lampă pe un microcontroler cu un sistem de operare la bord, în care culorile sunt setate printr-un browser.

Protocolul HTTP este bazat pe text și destul de simplu. De fapt, așa arată metoda GET, trimisă de utilitarul netcat la adresa IPv6 locală a serverului cu lumini:

~$ nc fe80::200:e2ff:fe58:b66b%mazko 80<

Metoda HTTP este de obicei un cuvânt scurt englezesc scris cu majuscule și ține seama de majuscule. Fiecare server trebuie să accepte cel puțin metodele GET și HEAD. Pe lângă metodele GET și HEAD, se folosesc adesea metodele POST, PUT și DELETE. Metoda GET este folosită pentru a solicita conținutul unei resurse specificate, în cazul nostru aici GET /b HTTP/1.0 unde calea /b este responsabilă pentru culoare (albastru). Răspunsul serverului:

HTTP/1.0 200 OK Server: Contiki/2.4 http://www.sics.se/contiki/ Conexiune: închide Cache-Control: no-cache, no-store, must-revalidate Pragma: no-cache Expire: 0 Content- tip: text/html Contiki RGB

Roșu este OPRIT

Verdele este OPRIT

Albastrul este pornit

Codul de stare (avem 200) face parte din prima linie a răspunsului serverului. Este un număr întreg de trei cifre. Prima cifră indică clasa afecțiunii. Codul de răspuns este de obicei urmat de o frază explicativă în limba engleză, separată de un spațiu, care explică persoanei motivul acestui răspuns particular. În cazul nostru, serverul a funcționat fără erori, totul a fost bine (OK).

Atât cererea, cât și răspunsul conțin anteturi (fiecare linie este un câmp de antet separat, perechea nume-valoare este separată prin două puncte). Anteturile se termină cu o linie goală, după care pot urma datele.

Browserul meu refuză să deschidă adresa IPv6 locală, așa că o adresă suplimentară este scrisă în firmware-ul microcontrolerului și același prefix trebuie, de asemenea, atribuit interfeței de rețea virtuală a simulatorului:

~$ sudo ip addr add abcd::1/64 dev mazko # linux ~$ netsh interface ipv6 set address mazko abcd::1 # windows ~$ curl http://

Cele mai bune articole pe această temă