|
Home
> Inginerie > Calculatoare
> Ghid retele > PAI
> Continuare
Ştim acum suficient
pentru a construi aplicaţii client/server sofisticate:
Implementare: structura de date
a socketului
Iată o
astfel de structură de date per socket īn cadrul SO:
|
Cāmpurile structurii socketului |
| tipul
socketului |
|
opţiunile socketului (de la socket()) |
| timpul
de "īntārziere" |
| starea
socketului (ISCONNECTED, ISCONNECTING,
) |
|
indicatorul pentru informaţii privind protocolul de nivel inferior |
|
indicatorul pentru socketul accept() |
| şir,
numărul de conexiuni parţial formate |
|
numărul maxim de conexiuni īn aşteptare |
| şir,
numărul de conexiuni sosite aflate īn aşteptare |
|
evenimentul amānat dacă nu există nicio conexiune care să sosească |
|
flagurile de eroare |
|
informaţii de semnalare |
|
indicator de depăşire a limitei de bandă |
|
bufer de transmisie |
cāmpuri/caracteristici |
| |
numărul de byţi īn bufer |
| |
marcator al nivelului de sus |
| |
marcator al nivelului de jos |
| |
indicator către zona buferelor (mbufs) |
| |
transmisia/recepţia |
| |
flaguri |
| bufer
de recepţie |
aceleaşi cāmpuri ca la cel de transmisie |
Implementare: acţiunile SO
asupra sendto()

Implementare: acţiunile SO
asupra rcvfrom()
UNIX SVR4: Interfaţa TLI
Interfaţa Nivelului de Transport (TLI) pentru Sistemul Unix V,
Release 4 (svr4)
Ca
sockeţi:
-
independent de transport
-
două
modele: orientat pe conexiuni, datagrame
-
"terminalul
de transport endpoint'' se aseamănă cu un
socket
TLI
este implementată ca rutine de bibilotecă C la nivel utilizator, mai
degrabă decāt apeluri de sistem.
Comparaţie pentru unele
TLI versus socket
|
Funcţia TLI |
Apelul BSD cel
mai apropiat |
Comentarii |
| t_open() |
socket() |
|
| t_bind() |
bind(), listen() |
|
| t_listen() |
accept() |
aşteaptă
solicitarea dar nu o acceptă. Returnează informaţia la client |
| t_snddis() |
|
refuză clientul
fără accept |
| t_accept() |
accept() |
TLI nu va crea un
nou terminal. BSD accept()=t_list+t_open+t_accept
|
| t_connect() |
connect() |
|
| t_send() |
send() |
|
| t_recv() |
recv() |
|
| t_sendudata() |
sendto() |
|
| t_recvudata() |
rcvfrom() |
|
| t_look() |
|
ia evenimentul
curent de la conexiunea transport |
| t_getstate() |
|
ia starea curenă
de la conexiunea transport |
Se
bazează pe sockeţii BSD:
Cāteva
diferenţe/incompatibilităţi:
-
extensii pentru programarea asincronă
-
coduri de retur pentru eroarea de diferenţă: -1
nu este codul de retur al erorii!
-
identificatorul socketului este diferit de identificatorul fişierului
-
read(), write(),
close() nu trebuie utilizaţi
-
folosiţi īn schimb echivalenţii specifici socketului.
Sockeţii Windows;
apeluri de sistem
Specificaţiile pentru sockeţii Windows includ
următoarele rutine de socket tip Berkeley:
| accept() * |
O conexiune la
intrare este recunoscută şi asociată cu un socket creat imediat.
Socketul original este returnat īn starea de ascultare.
|
| bind() |
Asignează un nume
local unui socket nenumit. |
| closesocket() * |
Īnlătură un socket
din tabela de referinţă a procesului. Numai blocurile dacă
SO_LINGER este ajustat. |
| connect() * |
Iniţiază o
conexiune pe socketul specificat. |
| getpeername() |
Restabileşte
numele perechii conectate la socketul specificat.
|
| getsockname() |
Restabileşte
numele curent pentru socketul specificat. |
| getsockopt() |
Restabileşte
opţiunile asociate cu socketul specificat. |
| htonl() |
Converteşte o
cantitate de 32 bit din ordinea de byte a gazdei īn cea a reţelei.
|
| htons() |
Converteşte o
cantitate de 16 bit din ordinea de bit a gazdei īn cea a reţelei.
|
| inet_addr() |
Converteşte un şir
de caractere reprezentānd un număr īn notaţia Internet "." standard
īntr-o valoare de adresă pe Internet. |
| inet_ntoa() |
Converteşte o
valoare de adresă pe Internet īntr-un şir ASCII īn notaţia ".", de
ex. "a.b.c.d". |
| ioctlsocket() |
Oferă controlul
sockeţilor. |
| listen() |
Ascultă
conexiunile de intrare pe un socket specificat. |
| ntohl() |
Converteşte o
cantitate de 32 bit din ordinea bzte de reţea īn cea de gazdă.
|
| ntohs() |
Converteşte o
cantitate de 16 bit din ordinea bzte de reţea īn cea de gazdă
|
| recv() * |
Primeşte date de
la un socket conectat. |
| recvfrom() * |
Primeşte date de
la un socket conectat sau neconectat. |
| select() * |
Realizează
multiplexarea sincronă I/O. |
| send() * |
Transmite date la
un socket conectat. |
| sendto() * |
Transmite date la
un socket conectat sau neconectat. |
| setsockopt() |
Stochează
opţiunile asociate cu socketul specificat. |
| shutdown() |
Īnchide parţial o
conexiune full-duplex. |
| socket() |
Crează un terminal
pentru comunicaţie şi retirnează un socket. |
* =
Rutina poate bloca dacă acţionează asupra unui socket de blocare.acting
on a blocking socket.
Sockeţi Windows:
funcţii pentru baza de date
| gethostbyaddr() *
|
Restabileşte
numele şi adresa corespunzătoare unei adrese de reţea.
|
| gethostbyname() * |
Restabileşte
numele şi adresa corespunzătoare unui nume de gazdă.
|
| gethostname() |
Restabileşte
numele gazdei locale. |
| getprotobyname() * |
Restabileşte
numele şi numărul de protocol corespunzător unui nume de protocol. |
| getprotobynumber() * |
Restabileşte
numele şi numărul de protocol corespunzător unui număr de protocol. |
| getservbyname() * |
Restabileşte
numele de serviciu şi portul corespunzător unui nume de serviciu.
|
| getservbyport() * |
Restabileşte
numele de serviciu şi portul corespunzător unui port.
|
* = Rutina poate
bloca īn anumite circumstanţe.
Sockeţi Windows:
asincronie
Suportul asincron
permite programatorului să specifice rutina care trebuie apelată cānd se
petrec evenimente care au legătură cu socketul:
- socketul gata
pentru citire/scriere
- datele care
depăşesc limita de bandă gata pentru a fi citite
- socketul gata
pentru a accepta conexiunea
- conexiune
īnchisă:
Aceste
extensii sunt de ajutor cu
programarea concurentă, multifir
| WSAAsyncGetHostByAddr()
|
Un set de funcţii
care oferă versiuni asincrone ale funcţiilor Berkeley standard
getXbyY(). De exemplu, funcţia
WSAAsyncGetHostByName() dă un mesaj asincron
bazat pe implementarea funcţiei Berkeley standard
gethostbyname(). |
| WSAAsyncGetHostByName() |
|
| WSAAsyncGetProtoByName() |
|
| WSAAsyncGetProtoByNumber() |
|
| WSAAsyncGetServByName() |
|
| WSAAsyncGetServByPort() |
|
| WSAAsyncSelect() |
Execută versiunea
asincronă a lui select() |
| WSACancelAsyncRequest() |
Anulează o
solicitare a unei funcţii WSAAsyncGetXByY().
|
| WSACancelBlockingCall() |
Anulează o
"blocare" a apelului IPA. |
| WSACleanup() |
Ieşire din
substratul DLL al sockeţilor Windows. |
| WSAGetLastError() |
Obţine detalii
despre ultima eroare IPA a sockeţilor Windows. |
| WSAIsBlocking() |
Află dacă
substratul DLL al sockeţilor Windows blochează deja un apel existent
pentru acest fir. |
| WSASetBlockingHook() |
"Agaţă"
(hook) metoda de blocare folosită de
substratul implementare al sockeţilor Windows. |
| WSASetLastError() |
Ajustează eroarea
care trebuie returnată de următoarea WSAGetLastError()
|
| WSAStartup() |
Iniţializează
substratul DLL al sockeţilor Windows. |
| WSAUnhookBlockingHook() |
Restaurează
funcţia de blocare originală. |
Abstractizarea IPA a reţelei: socket
Clasele
de servicii de transport sunt aceleaşi cu sockeţii:
O
interfaţă de nivel puţin mai īnalt decāt īn cazul sockeţilor UNIX.
Unele
consideraţii specifice Java:
Referinţe:
Java in a Nutshell, D. Flanagan, O'Reily and Associates, 1996
Transmiterea unei datagrame īn
Java
Crează un pachet
DatagramPacket, specificānd date, lungimea, adresa IP şi portul
destinatarului.
Invocă metoda
(procedura) send() a socketului
DatagramSocket
// This example is from the book _Java
in a Nutshell_ by David Flanagan.
// Written by David Flanagan. Copyright (c) 1996 O'Reilly & Associates.
// You may study, use, modify, and distribute this example for any
purpose.
// This example is provided WITHOUT WARRANTY either expressed or
implied.
import java.io.*;
import java.net.*;
// This class sends the specified text as a datagram to port 6010 of the
// specified host.
public class UDPSend {
static final int port = 6010;
public static void main(String args[]) throws Exception {
if (args.length != 2) {
System.out.println("Usage: java UDPSend
");
System.exit(0);
}
// Get the internet address of the specified host
InetAddress address = InetAddress.getByName(args[0]);
// Convert the message to an array of bytes
int msglen = args[1].length();
byte[] message = new byte[msglen];
args[1].getBytes(0, msglen, message, 0);
// Initilize the packet with data and address
DatagramPacket packet = new DatagramPacket(message, msglen,
address, port);
// Create a socket, and send the packet through it.
DatagramSocket socket = new DatagramSocket();
socket.send(packet);
}
}
Recepţia unei datagrame īn
Java
Crează un pachet
DatagramPacket cu un bufer pentru a recepţiona pachetul.
Crează
un socket DatagramSocket care va "aştepta"pachetul.
Invocă
metoda (procedura) receive() a
socketului DatagramSocket
// This example is from the book _Java in a Nutshell_ by David Flanagan.
// Written by David Flanagan. Copyright (c) 1996 O'Reilly & Associates.
// You may study, use, modify, and distribute this example for any purpose.
// This example is provided WITHOUT WARRANTY either expressed or implied.
import java.io.*;
import java.net.*;
// This program waits to receive datagrams sent to port 6010.
// When it receives one, it displays the sending host and port,
// and prints the contents of the datagram as a string.
public class UDPReceive {
static final int port = 6010;
public static void main(String args[]) throws Exception
{
byte[] buffer = new byte[1024];
String s;
// Create a packet with an empty buffer to receive data
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
// Create a socket to listen on the port.
DatagramSocket socket = new DatagramSocket(port);
for(;;) {
// Wait to receive a datagram
socket.receive(packet);
// Convert the contents to a string
s = new String(buffer, 0, 0, packet.getLength());
// And display them
System.out.println("UDPReceive: received from " +
packet.getAddress().getHostName() + ":" +
packet.getPort() + ": " + s);
}
}
}
Adoptă paradigma
client-server.
Transportul de date:
datagrama este nesigură (IPX),
orientarea pe conexiune este sigură (SPX)]
SAP: Protocolul
de Avertizare a Serviciului (Service Advertising Protocol)
folosit pentru servicii de
avertizare/solicitare.
NCP: Protocolul
Principal de Reţea (Netware Core Protocol)
folosit pentru interacţii client server definite
Netware.
Servicii definite
Netware de nivel superior:
- servicii de director
- suport pentru
tranzacţii
- controlul resurselor
- servicii de
īnchidere.
Protocolul SAP Novell
Permite clienţilor/serverelor
să localizeze serviciile de avertizare.
Ruterele şi porţile
menţin tabela de servicii cunoscute.
Serviciu periodic de
difuzare a informaţiilor.
Diferit
faţă de modelul Internet: reţeaua (ruterele) interne Novell au
informaţii la nivel de aplicaţie.
SAP difuzează pachetele
IPX. Model de format:
| operaţie |
tip
serviciu |
nume
server |
adresă
reţea |
adresă
gazdă |
adresă
socket |
salturi |
Tipurile de servicii sunt definite prin Novell.
Operaţii posibile:
|
tip serviciu |
semnificaţie |
| 1 |
solicită
numele/adresa tuturor serverelor din tipul specificat
|
| 2 |
răspuns la
solicitarea de tip 1, periodic difuzat de server şi ruter
|
| 3 |
la fel ca la 1,
dar pentru serviciul cel mai apropiat |
| 4 |
răaspuns la
solicitarea de tip 3 |
Aplicaţiile pot apela (comunica cu) entităţi existente predefinite care
oferă un serviciu.
Elemente de siguranţă ale serviciului de transfer:
-
punct de control şi recuperare: transfer
sigur de date faţă de vulnerabilităţile conexiunii de reţea
-
comunicare cu două moduri de alternanţă:
confirmă transferul şi recepţionează īnainte de a transmite următorul
mesaj.
Obligativitatea, concurenţa şi recuperarea
oferă o acţiune la nivel atomic:
-
ajustarea schimburilor de mesaje şi prelucrarea tuturor garanţiilor
pentru a realiza completitudinea sau altceva daca nu se realizează
nici o acţiune
-
nicio
instabilitate nu trebuie să deregleze reţeaua
|