1 / 17

Komunikacja przez sieć z wykorzystaniem biblioteki WINSOCK

Komunikacja przez sieć z wykorzystaniem biblioteki WINSOCK. mgr.inż. Piotr Kaczmarek Instytut Automatyki i Inżynierii Informatycznej. TCP/IP. Stanowi połączenie dwóch protokołów

chaney
Download Presentation

Komunikacja przez sieć z wykorzystaniem biblioteki WINSOCK

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Komunikacja przez sieć z wykorzystaniem biblioteki WINSOCK mgr.inż. Piotr Kaczmarek Instytut Automatyki i Inżynierii Informatycznej

  2. TCP/IP • Stanowi połączenie dwóch protokołów • Umożliwia efektywne przesyłanie pakietów między sieciami (IP) oraz zapewnia kontrolę i niezawodność przesyłanie pakietów między dwoma komputerami (TCP) • Protokół ten działa również w sieciach lokalnych w których komputery posiadają adresy IP. • Mechanizm ten można również wykorzystywać do komunikacji między aplikacjami uruchomionymi na pojedynczym komputerze z wykorzystaniem adresu loop back 127.0.0.1 (localhost)

  3. Architektura Klient-Serwer • Architektura ta dotyczy warstwy aplikacji • Wszystkie zasoby zgromadzone są na serwerze i są udostępniane przez niego komputerom klientom wyłącznie w takim zakresie w jakim ich potrzebują, • Architektura ta umożliwia ograniczenie dostępu do pewnych zasobów, hermetyzację • W architekturze tej można stosować wolne komputery klientów z małą pamięcią dyskową, ponieważ większość zadań wykonywana jest w obrębie serwera, zaś komputer klienta służy wyłącznie do wyświetlania wyniku operacji • Komunikacja między serwerem a klientami może odbywać się z wykorzystaniem protokołu TCP/IP, lecz wymaga sprecyzowania interface’u komunikacji

  4. Algorytm komunikacji • Serwer oczekuje na żądania klientów i obsługuje je w określonej kolejności, sam jednak nie inicjuje połączenia • Należy ustalić (jeśli nie korzysta się ze standardowego protokołu (np. http lub ftp) w jaki sposób przekazywać żądania do servera • Należy ustalić jakie zadania leżą w kompetencji servera a jakie klienta • W celu aktualizacji swoich danych to aplikacja klienta musi zgłaszać odpowiednie żądanie

  5. Interface komunikacji • Żądanie przesyłane do serwera, wywołuje w aplikacji działającej na serwerze odpowiednią funkcję, której argumentami stają się dane przesłane przez klienta • Należy zdefiniować wszystkie możliwe typy żądań oraz dane przesyłane przy każdym z tych żądań i odpowiedzi serwera i umieścić je w dwóch klasach interface’u osobno dla klienta i dla serwera

  6. Przykładowa klasa interface’u Pomiędzy klientem i serwerem przesyłane są dane opisane strukturą: struct CSFRAME{ int ID; long DataSize void *Data}; Strona klienta Żądania:ID Opis dane1 PrześlijAktualneDane NULL2 SprawdzDane dane do sprawdzenia (np. Wykonany ruch) Strona serwera Odpowiedzi serveraID opis dane1 AkualneDane Aktualne dane (np. plansza) 2 Błąd kod błędu

  7. Interface - implementacja • Po stronie serwera i klienta powinny znajdować się dwie klasy które realizują komunikację • Powinny one posiadać metody nazwane tak jak żądania klienta (przesłanie żądania klienta wywołuje odpowiednią funkcję na serwerze) Strona klienta Strona serwera class CServerInterface{public: void OdbierzŻądanie(); CPlansza* PrzeslijAktualneDane(); int SprawdzDane(CPlansza* plansza)private: CSFRAME KomunikatOdebrany; CSFRAME KomunikatWysłany; }; class CClientInterface{public: CPlansza* PrzeslijAktualneDane(); int SprawdzDane(CPlansza* plansza)private: CSFRAME KomunikatOdebrany; CSFRAME KomunikatWysłany; };

  8. Strona klienta Interface – implementacja cd. Strona serwera CPlansza* CClientInterface::PrzeslijAktualneDane(){ KomunikatWyslany.ID=1; KomunikatWyslany.DataSize=0; KomunikatWyslany.Data=NULL;WyslijDoServera(KomunikatWyslany); OdbierzZSerwera(&KomunikatOdebrany); if(KomunikatOdebrany.ID==1) return KomunikatOdebrany. Data;else return NULL;}int CClientInterface:: SprawdzDane(CPlansza* plansza){ KomunikatWyslany.ID=2; KomunikatWyslany.DataSize=sizeof(CPlansza); KomunikatWyslany.Data=plansza;WyslijDoServera(KomunikatWyslany);OdbierzZSerwera(&KomunikatOdebrany); return (int*) KomunikatOdebrany. Data;} CPlansza* CServerInterface:: OdbierzŻądanie(){CPlansza *plansza;int KodBladu; CzekajNaDaneOdKlienta(&KomunikatOdebrany); switch(KomunikatOdebrany.ID){ case 1: plansza=PrzeslijAktualneDane(); KomunikatWyslany.ID=1; KomunikatWyslany.DataSize=sizeof(CPlansza); KomunikatWyslany.Data=plansza;case 2: KodBladu= SprawdzDane(KomunikatOdebrany.Data) KomunikatWyslany.ID=2; KomunikatWyslany.DataSize=sizeof(int); KomunikatWyslany.Data=&KodBladu;}WyslijDoKlienta(KomunikatWyslany);}

  9. Wykorzystanie gniazd Gniazda – usługi serwera • Standardowo stosuje się gniazda (odpowiadające numerom telefonów) w celu realizacji pewnych usług. Gniazda są identyfikowane przez ich numer, aplikacja klienta może połączyć się z określonym gniazdem serwera 80 – httpd, 21 – ftp, powyżej numeru 1024 znajdują się gniazda z których mogą korzystać inne aplikacje • Połączenie z gniazdem można uzyskać przez wpisanie adresu IP i nr gniazda w postaci xxx.xxx.xxx:gniazdo

  10. Inicjalizacja WinSock (klient/server) // Initialize Winsock. WSADATA wsaData; int iResult = WSAStartup( MAKEWORD(2,2), &wsaData ); if ( iResult != NO_ERROR ) printf("Error at WSAStartup()\n"); Ten kod musi zostać wywołany jednorazowo przy uruchomieniu aplikazcji wykorzystującej bibliotekę WinSock, dodatkowo należy dołączyć plik nagłowkowy #include "winsock2.h"

  11. Tworzenie nienazwanego gniazda (klient/server) // Create a socket. SOCKET m_socket; m_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); if ( m_socket == INVALID_SOCKET ) { printf( "Error at socket(): %ld\n", WSAGetLastError() ); WSACleanup(); return; } Port stworzony przez klienta otrzymuje numer w chwili połączenia z serwerem. Numer portu na którym serwer nasłuchuje musi zostać przydzielony w następnym kroku

  12. Połączenie z nazwanym portem (serwer) // Bind the socket. sockaddr_in service; service.sin_family = AF_INET; service.sin_addr.s_addr = inet_addr( "127.0.0.1" ); service.sin_port = htons( 27015 ); if ( bind( m_socket, (SOCKADDR*) &service, sizeof(service) ) == SOCKET_ERROR ) { printf( "bind() failed.\n" ); closesocket(m_socket); return; } Inet_addr(„IP”) przekształca ciąg znaków zwierających adres IP komputera do właściwej postaci (IN_ADDR) Do przypisania adresu można rwnież wykorzystać nazwę hosta (jeśli jest zarejestrowana w DNS: gethostbyname( „www.wp.pl”) htons konwertuje numer portu dany jako unsigned short na numer w formacie standardu TCP/IP (big-endian) Po wywołaniu funkcji bind na serwerze zostaje aktywowany port o wybranym numerze

  13. Serwer oczekuje na żądanie klienta // Listen on the socket. if ( listen( m_socket, 1 ) == SOCKET_ERROR ) printf( "Error listening on socket.\n"); Serwer „nasłuchuje” na wybranym porcie (m_sock)., drugi argument funkcji listen określa długość kolejki zgłoszeń, dla aplikacji z wieloma klientami należy ją ustawić na wartość >1 listen pozostaje zawieszona tak długo jak nie pojawi się żądanie ze strony klienta

  14. Połączenie klienta z serwerem (klient) sockaddr_in clientService; clientService.sin_family = AF_INET; clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" ); clientService.sin_port = htons( 27015 ); if ( connect( m_socket, (SOCKADDR*) &clientService,sizeof(clientService) ) == SOCKET_ERROR) { printf( "Failed to connect.\n" ); WSACleanup(); return; } Wywołanie connect powadzi do nawiązania połączenia z serwerem zlokalizowanym pod określonym adresem (clientService) i słuchającym na wybranym porcie (27015). Serwer dla celu tego połączenia dedykuje odrębny port (jego adres przypisany zostaje do m_sock). Port nasłuchu nie służy do komunikacji z klientami a jedynie do nawiązania połączenia!!!

  15. Akceptacja połączenia przychodzącego (serwer) // Accept connections. SOCKET AcceptSocket; printf( "Waiting for a client to connect...\n" ); while (1) { AcceptSocket = SOCKET_ERROR; while ( AcceptSocket == SOCKET_ERROR ) { AcceptSocket = accept( m_socket, NULL, NULL ); } printf( "Client Connected.\n"); break; } Po tym jak funkcja listen została przerwana przez żądanie ze strony klienta, accept aprobuje połączenie i dedykuje dla niego nowy port (AcceptSocket)

  16. Wysyłanie i odbiór danych (klient/server) Odbiór danych: #define BUFF_LEN 32int bytesRecv = SOCKET_ERROR; char recvbuf[BUFF_LEN] = ""; //bufor danych//Odbiera dane i zapisuje je do bufora. //Zwraca ilość odebranych bajtów (bytesRecv) bytesRecv = recv( m_socket, recvbuf, BUFF_LEN, 0 ); Wysyłanie danych: int bytesSent;char sendbuf[] = „ten tekst zostanie wyslany” bytesSent = send( m_socket, sendbuf, strlen(sendbuf), 0 ); Dla serwera należy zamiast m_sock wykorzystać port stworzony do komunikacji z klientem AcceptSocket !!!!

  17. WSAStartup(...)socket(...) WSAStartup(...)socket(...) bind(...) listen(...) accept(...) recv(...) Komunikacja raz jeszcze connect(...) send(...) send(...) recv(...) Czarne strzałki wskazują miejsca, w których powinny znaleźć się poszczególne funkcje wykorzystywane do komunikacji Czerwone strzałkipokazują przepływ danych między klientem a serwerem

More Related