Úvod Jednoduchá komunikace Sockety Konec
Programování v C# Síťová komunikace Petr Vaněček
1 / 33
Úvod Jednoduchá komunikace Sockety Konec
Obsah přednášky
I
Jednoduchá komunikace
I
Sockety
2 / 33
Úvod Jednoduchá komunikace Sockety Konec
System.Net
I I
Namespace poskytuje jednoduché rozhraní ke standardním protokolům Třída WebClient I
příjmání a odesílání dat pro různé protokoly I
I
I
Třídy *WebRequest I
I
třídy pro vznesení požadavku
Třídy *WebResponse I
I
http, https, ftp, file
směrování pomocí URI (Uniform Resource Identifier)
třídy pro získání odpovědi
Třída HttpListener I
jednoduchý posluchač HTTP protokolu
3 / 33
Úvod Jednoduchá komunikace Sockety Konec
System.Net
I I
Další podpůrné třídy pro práci se sítí Třída Cookies I
I
Třída DNS I
I
podpora pro práci s cookies práce s Domain Name Systémem
Třída *EndPoint I
umožňuje popsat cílový bod síťové komunikace
4 / 33
Úvod Jednoduchá komunikace Sockety Konec
Třída WebRequest I
Abstraktní třída I I I
I
Pro vytvoření instance I I
I
WebException
Výsledek se získá pomocí odezvy I
I
WebRequest Create(URI) typ, který se vrátí určuje URI
Při chybě se vyvolá chyba I
I
HttpWebRequest (http://, https://) FtpWebRequest (ftp://) FileWebRequest (file:// souborový sytém)
WebResponse GetResponse()
Možnost asynchronního přenosu I
metody BeginGetResponse a EndGetResponse
5 / 33
Úvod Jednoduchá komunikace Sockety Konec
Třída WebResponse
I
Abstraktní třída I I I
I
Pro vytvoření instance I
I
HttpWebResponse FtpWebResponse FileWebResponse WebRequest.GetResponse()
Výsledek čitelný pomocí proudu I
Stream GetResponseStream()
6 / 33
Úvod Jednoduchá komunikace Sockety Konec
Synchronní komunikace WebRequest pozadavek = WebRequest . Create ( " http :// home . pf . jcu . cz /~ vanecek / " ); HttpWebResponse odpoved = ( HttpWebResponse ) pozadavek . GetResponse (); Encoding encode = System . Text . Encoding . GetEncoding ( " windows -1250 " ); Stream proud = odpoved . GetRe spons eStre am (); StreamReader ctenar = new StreamReader ( proud , encode ); string stranka = ctenar . ReadToEnd (); Console . Write ( stranka ); odpoved . Close (); ctenar . Close (); 7 / 33
Úvod Jednoduchá komunikace Sockety Konec
Třída DNS I I
Statická třída pro práci s Internet Domain Name System Metody
I
IPHostEntry GetHostByName(string) IPHostEntry GetHostByIP(IPAdress) IPHostEntry Resolve(string)
I
string GetHostName()
I I
I
I
I
vrací DNS informace vrací jméno lokálního počítače
Příklad IPHostEntry hostInfo = Dns . GetHostByName ( " home . pf . jcu . cz " ); Console . WriteLine ( " Host name : " + hostInfo . HostName ); Console . WriteLine ( " IP address List : " + hostInfo . AddressList [0]);
8 / 33
Úvod Jednoduchá komunikace Sockety Konec
Namespace System.Net.Socket
I I
Umožňuje vyšší kontrolu kontrolu síťového přístupu Přenos dat jedním z protokolů ProtocolType I
I I
IP, IPv6, TCP, UDP, . . .
Synchronní i asynchronní komunikace Odlehčené verze I
I I
TcpClient, TcpListener, UdpClient, IrDAClient, IrDAListener jen synchronní verze (blokující) jednodušší interface
9 / 33
Úvod Jednoduchá komunikace Sockety Konec
Třída Socket
I
Socket (AddressFamily, SocketType, ProtocolType) I
AddressFamily I I
I
SocketType I I
I
typ socketu Stream, Dgram, Raw, ...
ProtocolType I
I
adresovací schéma InterNetwork, InterNetworkV6, IrDa
viz. předchozí slide
Musí být správná kombinace adresy, typu a protokolu I
SocketException
10 / 33
Úvod Jednoduchá komunikace Sockety Konec
Typy socketů
I
Datagram I I I I
krátké zprávy pevné délky nepotřebují navázané spojení při posílání není zajištěna bezpečnost protokol UDP
11 / 33
Úvod Jednoduchá komunikace Sockety Konec
Typy socketů
I
Datagram I I I I
I
krátké zprávy pevné délky nepotřebují navázané spojení při posílání není zajištěna bezpečnost protokol UDP
Stream I I I
navazované obousměrné spojení před odesláním musí být spojení navázané protokol TCP
11 / 33
Úvod Jednoduchá komunikace Sockety Konec
Typy socketů
I
Datagram I I I I
I
Stream I I I
I
krátké zprávy pevné délky nepotřebují navázané spojení při posílání není zajištěna bezpečnost protokol UDP navazované obousměrné spojení před odesláním musí být spojení navázané protokol TCP
Raw I I
nutno doplnit IP hlavičku protkoly ICMP, IGMP
11 / 33
Úvod Jednoduchá komunikace Sockety Konec
Způsob komunikace
I
Synchronní I I I
I
obsluha jedním vláknem blokující Send, Receive, Accept, . . .
Asynchronní I
obsluha v odděleném vlákně IAsyncResult Begin...(..., AsyncCallback, object)
I
...End...(IAsyncReslut)
I
I
I
delegát pro obsluhu + uživatelský parametr blokující
12 / 33
Úvod Jednoduchá komunikace Sockety Konec
Navázání komunikace
I
void Listen(int) I I I I
I
neblokující pouze pro spojově orientované protokoly nastaví socket do naslouchacího režimu parametr určuje délku fronty požadavků o spojení
void Bind(EndPoint) I I
před voláním Listen se musí volat propojí socket s lokálním koncovým bodem spojení
13 / 33
Úvod Jednoduchá komunikace Sockety Konec
Navázání komunikace
I
Socket Accept() I I I
I
přijme požadavek o připojení z fronty blokující socket čeká na požadavek v případě prázdné fronty neblokující socket vyvolá výjimku SocketException v případě prázdné fronty
void Connect(EndPoint) I I
vytvoří spojení se vzdáleným koncem EndPoint metoda se musí volat pro spojované protokoly
14 / 33
Úvod Jednoduchá komunikace Sockety Konec
Příklad navázání komunikace – server
Socket s = new Socket ( AddressFamily . InterNetwork , SocketType . Stream , ProtocolType . IP ); IPEndPoint local = new IPEndPoint ( IPAddress . Parse ( " 127.0.0.1 " ) , 6666); // bude se poslouchat na portu 6666 s . Bind ( local ); // délka fronty je 100 s . Listen (100); // čeká dokud se někdo nepřipojí Socket connection = s . Accept ();
15 / 33
Úvod Jednoduchá komunikace Sockety Konec
Příklad navázání komunikace – klient
Socket s = new Socket ( AddressFamily . InterNetwork , SocketType . Stream , ProtocolType . IP ); IPEndPoint local = new IPEndPoint ( IPAddress . Parse ( " 127.0.0.1 " ) , 6666); s . Connect ( local );
16 / 33
Úvod Jednoduchá komunikace Sockety Konec
Posílání dat
I
int Send(byte[]) I I
I
I
pošle data připojenému socketu vrací počet odeslaných bytů pokud se používá nespojovaný protokol, pak každému volání musí předcházet volání Connect pro spojované protokoly stačí volat Connect nebo Accept jen jednou pro každou relaci
int SendTo(byte[], EndPoint) I I I I
zaměřeno pro nespojované protokoly nemusí se volat Connect není třeba volat Bind – použije se nejvhodnější nastavení lze použít i pro spojované protokoly I I
musí se volat Connect EndPoint se ignoruje
17 / 33
Úvod Jednoduchá komunikace Sockety Konec
Příjímání dat
I
int Recieve(byte[]) I I I
I
I I
přijme data od připojeného socketu funguje pro oba typy protokolů při použití spojovaného protokolu musí být před voláním navázáno spojení – Connect nebo Accept při použití nespojovaného protokolu se přečte datagram poslaný ze zdroje uvedeného v Connect blokující soket čeká na data, neblokující vyhodí SocketException property Available I
I
obsahuje počet dostupných bytů
vrací počet přečtených bytů
18 / 33
Úvod Jednoduchá komunikace Sockety Konec
Příjímání dat
I
int RecieveFrom(byte[], ref EndPoint) I I I
I
přijme data a zdroj dat uloží do EndPoint je zamýšlena pro nespojované protokoly metodou Connect lze vytvořit implicitního vzdáleného hostitele a data pak budou přijímána pouze od něj lze použít i pro spojované protokoly I
I I
vrací počet přečtených bytů blokující soket čeká na data, neblokující vyhodí SocketException I
I
nutno vytvořit spojení metodou Connect nebo Accept
property Available obsahuje počet dostupných bytů
pokud buffer nestačí - SocketException
19 / 33
Úvod Jednoduchá komunikace Sockety Konec
Posílání/příjímání dat
I
klient byte [] msg = Encoding . ASCII . GetBytes ( " Posilam ti zpravu " ); Console . WriteLine ( Encoding . ASCII . GetString ( msg )); int i = s . Send ( msg );
I
serever byte [] msg = new byte [100]; connection . Receive ( msg ); Console . WriteLine ( Encoding . ASCII . GetString ( msg ));
20 / 33
Úvod Jednoduchá komunikace Sockety Konec
Ukončení spojení
I
void Shutdown(SocketShutdown) I
I
ukončení komunikace (pouze send, pouze recieve, obojí)
void Close() I
uvolnění systémových prostředků
21 / 33
Úvod Jednoduchá komunikace Sockety Konec
Asynchronní komunikace I
Metody Begin... a End...
I
Volá se delegát, který je automaticky spuštěn v jiném vlákně
I
Příklad ... { Socket s = new Socket ( AddressFamily . InterNetwork , SocketType . Stream , ProtocolType . IP ); s . Bind ( local ); s . Listen (100); Socket connection = s . Accept (); msg = new byte [100]; connection . BeginReceive ( msg ,0 ,100 , SocketFlags . None , new AsyncCallback ( Prijem ) , connection ); ... }
22 / 33
Úvod Jednoduchá komunikace Sockety Konec
Asynchronní komunikace
I
Příklad (pokračování) static void Prijem ( IAsyncResult ar ) { Socket socket = ar . AsyncState as Socket ; int bytesRead = socket . EndReceive ( ar ); Console . WriteLine ( Encoding . ASCII . GetString ( msg )); }
23 / 33
Úvod Jednoduchá komunikace Sockety Konec
Použití streamu
I I
Slouží pro posílání dat sockety typu stream v blokujícím režimu Podporuje I I
I
Nepodporuje náhodný přístup k datům I
I
property CanSeek má hodnotu false
K fungování vyžaduje spojený socket I
I
int Read(byte[], int, int) void Write(byte[], int, int)
NetworkStream ns = new NetworkStream(Socket);
Je potomkem Stream I
lze aplikovat třídy Stream/Binnary/Reader/Writer
24 / 33
Úvod Jednoduchá komunikace Sockety Konec
Použití streamu I
klient s . Connect ( local ); NetworkStream ns = new NetworkStream (s , true ); StreamWriter sw = new StreamWriter ( ns ); while ( c != ( char )13) { c = Console . ReadKey (). KeyChar ; sw . Write ( c ); sw . Flush (); } sw . Close ();
I
server Socket connection = s . Accept (); NetworkStream ns = new NetworkStream ( connection ); StreamReader reader = new StreamReader ( ns , true ); while ( c != ( char )13) { c = ( char ) reader . Read (); Console . WriteLine ( c ); } 25 / 33
Úvod Jednoduchá komunikace Sockety Konec
Socket TCP
I
Třída TCPClient
I
obsahuje jednoduché metody pro posílání a příjímání pomocí protokolu TCP void Connect(IPEndPoint)
I
NetworkStream GetStream()
I
I
I I I I I
spojení může být navázáno i v konstruktoru získá stream určený pro příjmání i posílání dat musí být navázané spojení metody Write i Read jsou blokující blokující Read lze obejít testováním DataAvailable
void Close() I
uzavře sopjení a uvolní zdroje
26 / 33
Úvod Jednoduchá komunikace Sockety Konec
Socket TCP
I
Třída TcpListenner I
nastavení lokálního koncového bodu se provádí již při konstrukci void Start()
I
void Stop()
I
I
I
začne naslouchat končí naslouchání
I
bool Pending()
I
TcpClient AcceptTcpClient()
I
I
vrátí zda se někdo pokouší o spojení naváže spojení
27 / 33
Úvod Jednoduchá komunikace Sockety Konec
Socket TCP – server IPEndPoint local = new IPEndPoint ( IPAddress . Parse ( " 127.0.0.1 " ) , 6666); TcpListener tcpListener = new TcpListener ( local ); tcpListener . Start (); while (! tcpListener . Pending ()) ; TcpClient client = tcpListener . AcceptTcpClient (); NetworkStream s = client . GetStream (); StreamReader r = new StreamReader ( s ); StreamWriter w = new StreamWriter ( s ); w . Write ( c ); c = r . Read (); client . Close (); tcpListener . Stop (); 28 / 33
Úvod Jednoduchá komunikace Sockety Konec
Socket TCP – klient IPEndPoint local = new IPEndPoint ( IPAddress . Parse ( " 127.0.0.1 " ) , 6666); TcpClient client = new TcpClient (); client . Connect ( local ); NetworkStream s = client . GetStream (); StreamReader r = new StreamReader ( s ); StreamWriter w = new StreamWriter ( s ); w . Write ( c ); c = r . Read (); client . Close ();
29 / 33
Úvod Jednoduchá komunikace Sockety Konec
Práce s IrDA zařízeními
I
Třída IrDAClient I I
I
Třída IrDAListener I
I
podobně jako TCPClient umožňuje zjistit jméno vzdáleného zařízení RemoteMachineName podobně jako TCPListener
Třída IrDADeviceInfo I
informace o dostupných zařízeních I I I I
jméno id znaková sada typ – počítač, tiskárna, telefon, . . .
30 / 33
Úvod Jednoduchá komunikace Sockety Konec
UDP protokol
I
Třída UDPClient
I
nespojovaný protokol metody Connect, Send a Receive navíc možnost používat multicast metoda void JoinMulticastGroup(IPAddress)
I
metoda void DropMulticastGroup(IPAddress)
I I I
I
I
přidá klienta k multicastové skupině opustí multicast skupinu
31 / 33
Úvod Jednoduchá komunikace Sockety Konec
UDP protokol I
posluchač UdpClient client = new UdpClient (6666); client . Jo in Mu lt ic as tG ro up ( IPAddress . Parse ( " 127.0.0.1 " ) ,2); IPEndPoint ep = null ; byte [] buffer = client . Receive ( ref ep ); Console . WriteLine ( Encoding . ASCII . GetString ( buffer ));
I
odesílatel IPEndPoint local = new IPEndPoint ( IPAddress . Parse ( " 127.0.0.1 " ) , 6666); UdpClient client = new UdpClient (); client . Send ( Encoding . ASCII . GetBytes ( " ahoj " ) ,4 , local );
32 / 33
Úvod Jednoduchá komunikace Sockety Konec
Konec
33 / 33