Interfejs programowy Windows Sockets 2. Aplikacja klient-serwer TCP Echo



Podobne dokumenty
Rodzina protokołów TCP/IP. Aplikacja: ipconfig.

Protokół ARP. dr Zbigniew Lipiński. Instytut Matematyki i Informatyki ul. Oleska Opole zlipinski@math.uni.opole.pl

Aplikacja Sieciowa. Najpierw tworzymy nowy projekt, tym razem pracować będziemy w konsoli, a zatem: File->New- >Project

3. Identyfikacja. SKŁADNIA #include <sys/socket.h> int getpeername(int socket, struct sockaddr *addr, int *addrlen);

Protokół DNS. Aplikacja dnsquery

Statystyka protokołów i połączeń sieciowych.

Oprogramowanie komunikacyjne dla Internetu rzeczy Laboratorium nr 4 komunikacja unicastowa IPv6

Literatura uzupełniająca: W. Richard Stevens, Programowanie zastosowań sieciowych w systemie Unix WNT 1998

Programowanie sieciowe

Gniazda BSD. Procesy w środowisku sieciowym. Gniazda podstawowe funkcje dla serwera. Gniazda podstawowe funkcje dla klienta

Internet Control Message Protocol Aplikacja ping

Programowanie Sieciowe 1

Komunikacja sieciowa - interfejs gniazd

Programowanie aplikacji równoległych i rozproszonych. Wykład 4

Wielozadaniowość w systemie Microsoft Windows

Gniazda - Wstęp. Oprogramowanie systemów równoległych i rozproszonych. Sposób komunikacji. Domena adresowa. olas@icis.pcz.pl

Aplikacja Sieciowa wątki po stronie klienta

Architektura typu klient serwer: przesyłanie pliku tekstowo oraz logowania do serwera za pomocą szyfrowanego hasła

Iteracyjny serwer TCP i aplikacja UDP

Programowanie przy użyciu gniazdek

Gniazda. S. Samolej: Gniazda 1

2. Interfejs gniazd Gniazdo

Architektura typu klient serwer: uproszczony klient POP3

Gniazda BSD implementacja w C#

Gniazda UDP. Bartłomiej Świercz. Łódź, 3 kwietnia Katedra Mikroelektroniki i Technik Informatycznych. Bartłomiej Świercz Gniazda UDP

socket(int domain, int type, int protocol)

Winsock. Sieci Komputerowe II Wyk ład 3

Programowanie sieciowe

Gniazda surowe. Bartłomiej Świercz. Łódź,9maja2006. Katedra Mikroelektroniki i Technik Informatycznych. Bartłomiej Świercz Gniazda surowe

Klient-Serwer Komunikacja przy pomocy gniazd

Gniazda BSD. komunikacja bezpołączeniowa

1. Model klient-serwer

Zdalne wywołania procedur. Jarosław Kuchta Programowanie Współbieżne

TCP - receive buffer (queue), send buffer (queue)

ZESZYTY ETI ZESPOŁU SZKÓŁ W TARNOBRZEGU Nr 1 Seria: Teleinformatyka 2013

Instrukcja do laboratorium Systemów Operacyjnych. (semestr drugi)

SEGMENT TCP CZ. II. Suma kontrolna (ang. Checksum) liczona dla danych jak i nagłówka, weryfikowana po stronie odbiorczej

MODEL WARSTWOWY PROTOKOŁY TCP/IP

Komunikacja międzyprocesowa. Krzysztof Banaś Systemy rozproszone 1

Krótkie wprowadzenie do korzystania z OpenSSL

Podstawowe typy serwerów

Programowanie współbieżne. Tworzenie i obsługa semaforów oraz wątków przy użyciu funkcji Windows API.

Sieci komputerowe. Wykład 7: Transport: protokół TCP. Marcin Bieńkowski. Instytut Informatyki Uniwersytet Wrocławski

Tunelowanie, kapsułkowanie, XDR. 1. Transmisja tunelowa i kapsułkowanie serwery proxy. 2. Zewnętrzna reprezentacja danych XDR.

Tworzenie aplikacji rozproszonej w Sun RPC

I - Microsoft Visual Studio C++

Schemat dla UDP. = możliwe zablokowanie aplikacji KLIENT SERWER. s=socket(...) bind(s,...) recvfrom(s,...) sendto(s,...) recvfrom(s,...

Komputery i Systemy Równoległe Jędrzej Ułasiewicz 1

SUMA KONTROLNA (icmp_cksum) NUMER KOLEJNY (icmp_seq)

RPC. Zdalne wywoływanie procedur (ang. Remote Procedure Calls )

Projektowanie oprogramowania systemów KOMUNIKACJA SIECIOWA I SYSTEMY RPC

Standardy programowania protokołów komunikacyjnych Laboratorium nr 5 komunikacja multicastowa IPv6

PROTOKOŁY WARSTWY TRANSPORTOWEJ

Instytut Teleinformatyki

Ćwiczenie 2. Obsługa gniazd w C#. Budowa aplikacji typu klient-serwer z wykorzystaniem UDP.

Mechanizmy pracy równoległej. Jarosław Kuchta

Tworzenie i zarządzanie wątkami

Sieci komputerowe Warstwa transportowa

Laboratorium - Używanie programu Wireshark do obserwacji mechanizmu uzgodnienia trójetapowego TCP

Laboratorium 1 Temat: Przygotowanie środowiska programistycznego. Poznanie edytora. Kompilacja i uruchomienie prostych programów przykładowych.

Stos protokołów TCP/IP (ang. Transmission Control Protocol/Internet Protocol)

Oprogramowanie systemów równoległych i rozproszonych. Wykład 6

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

Programowanie współbieżne i rozproszone

DR INŻ. ROBERT WÓJCIK DR INŻ. JERZY DOMŻAŁ

Politechnika Łódzka. Instytut Systemów Inżynierii Elektrycznej

Instytut Teleinformatyki

Transport. część 2: protokół TCP. Sieci komputerowe. Wykład 6. Marcin Bieńkowski

Transport. część 2: protokół TCP. Sieci komputerowe. Wykład 6. Marcin Bieńkowski

Sieci komputerowe - Protokoły warstwy transportowej

Programowanie sieciowe

Programowanie. Ćwiczenie Język C. Środowisko programowania Visual Studio

Adresy w sieciach komputerowych

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

Akademickie Centrum Informatyki PS. Wydział Informatyki PS

Sieci komputerowe. Wykład 5: Warstwa transportowa: TCP i UDP. Marcin Bieńkowski. Instytut Informatyki Uniwersytet Wrocławski

TRX API opis funkcji interfejsu

ZiMSK dr inż. Łukasz Sturgulewski, DHCP

Sockety TCP/IP - podstawy. Sieci Komputerowe II Wyk ład 2

Opis protokołu RPC. Grzegorz Maj nr indeksu:

Tryb bezpołączeniowy (datagramowy)

Programowanie Sieciowe 1

Programowanie współbieżne i rozproszone

Wykład 3 / Wykład 4. Na podstawie CCNA Exploration Moduł 3 streszczenie Dr inż. Robert Banasiak

Architektury systemów rozproszonych LABORATORIUM. Ćwiczenie 1

Zdalne wywoływanie procedur RPC 27. października 2010

Zdalne wywoływanie procedur RPC

Zdalne wywoływanie procedur RPC

Laboratorium - Przechwytywanie i badanie datagramów DNS w programie Wireshark

Monitorowanie Sieci nonblocking content packet filtering

Temat: Dynamiczne przydzielanie i zwalnianie pamięci. Struktura listy operacje wstawiania, wyszukiwania oraz usuwania danych.

Tytuł: Instrukcja obsługi Modułu Komunikacji internetowej MKi-sm TK / 3001 / 016 / 002. Wersja wykonania : wersja oprogramowania v.1.

Podstawowe elementy proceduralne w C++ Program i wyjście. Zmienne i arytmetyka. Wskaźniki i tablice. Testy i pętle. Funkcje.

Zdalne wywoływanie procedur RPC. Dariusz Wawrzyniak 1

Protokoły sieciowe - TCP/IP

IPC: Kolejki komunikatów

Wybrane działy Informatyki Stosowanej

Programy typu klient serwer. Programowanie w środowisku rozproszonym. Wykład 5.

ARP Address Resolution Protocol (RFC 826)

Transkrypt:

Interfejs programowy Windows Sockets 2. Aplikacja klient-serwer TCP Echo Zagadnienia Omówienie biblioteki Winsock. Specyfikacja klienta tcpecho. Specyfikacja serwera tcpecho. dr Zbigniew Lipiński Instytut Matematyki i Informatyki UO zlipinski@math.uni.opole.pl

Interfejs programowy Windows Sockets 2 Windows Sockets jest implementacja gniazd BSD (University of California-Berkeley Sockets API). 1993 - edycja WinSock wersja 1.1. 1996 - WinSock wersja 2.0. Windows Sockets jest interfejsem programowym warstwy transportowej modelu OSI, pozwalającym budować aplikacje sieciowe oparte o protokoły rodziny TCP/IP. Windows Sockets 2 definiuje interfejsy komunikacyjne do obsługi wielu standardów i usług: DNS, SAP, X.509, Quality of Service, transmisji w trybie multicast, multipoint. 2

W skład specyfikacji WinSock2 wchodzą: WinSock 2 API (budowa aplikacji). WinSock 2 Service Provider Interface, udostępnianie interfejsów WinSock 2 protokołom transportowym. Komponenty Windows Open System Architecture (WOSA): WinSock Service Provider Interface (SPI), nazwy funkcji zaczynają się od WSP, np. WSPBind(). WinSock Provider Upcall, nazwy funkcji zaczynają się od WPU, np. WPUCloseEvent(). WSC Windows Sockets Configuration, np. WSCDeinstallProvider(). NSP Namespace Provider, np. NSPInstallServiceClass(). Nazwy funkcji Windows Sockets 2 zaczynają się od WSA. Przykład: WinSock 1.1: connect() WinSock 2.0: WSAConnect() 3

Architektura Windows Sockets 2 Źródło: MS Platform SDK. 4

Funkcje WinSock 2 Funkcje BSD: accept() bind() closesocket() connect() getpeername() getsockname() getsockopt() inet_addr() inet_ntoa() ioctlsocket() listen() ntohl(), ntohs() recv(), recvfrom() select() send(), sendto() setsockopt() shutdown() socket() Funkcje Windows: WSAAccept() WSAAsyncGetHostByAddr(), WSAAsyncGetHostByName(), WSAAsyncGetProtoByName(), WSAAsyncGetProtoByNumber(), WSAAsyncGetHostByName(), WSAAsyncGetServByName(), WSAAsyncGetServByPort(), WSAAsyncSelect(), WSACancelAsyncRequest(), WSAAsyncGetXByY(), WSACloseEvent(), WSACleanup(), WSAConnect(), WSACreateEvent(), WSADuplicateSocket(), WSAEnumNetworkEvents(), WSAEnumProtocols(), WSAEventSelect(), WSAGetLastError(), WSAGetOverlappedResult(), WSAGetQOSByName(), WSAHtonl(), WSAHtons(), WSAIoctl(), WSAJoinLeaf(), WSANtohl(), WSANtohs(), WSAProviderConfigChange(), WSARecv(), WSARecvFrom(), WSAResetEvent(), WSASend(), WSASendTo(), WSASetEvent(), WSASetLastError(), WSAGetLastError(), WSASocket(), WSAStartup() 5

Funkcje WinSock 2 Funkcje Windows (cd): getservbyname(), getservbyport(), geth(), gethostbyaddr(), gethostname() gethostbyaddr(), getprotobyname(), gethostname(), get(), gets(), getservbyport(), inet_addr(), inet_ntoa() WSAAsyncGetHostByAddr(), WSAAsyncGetHostByName(), WSAAsyncGetProtoByName(), WSAAsyncGetProtoByNumber(), WSAAsyncGetServByName(), WSAAsyncGetServByPort(), WSACancelAsyncRequest() Funkcje konwersji nazw: WSAAddressToString(), WSAEnumNameSpaceProviders(), WSAGetServiceClassNameByClassId(), WSAInstallServiceClass(), WSALookupServiceBegin(), WSALookupServiceEnd(), WSALookupServiceNext(), WSARemoveServiceClass(), WSASetService(), WSAStringToAddress(), WSAGetServiceClassInfo() 6

Specyfikacja struktury WSADATA Nazwa struktury : WSADATA Opis : Atrybuty : Struktura WSADATA zawiera informacje o implementacji gniazd (Windows Sockets). Struktura WSADATA jest zadeklarowana w pliku Winsock2.h. Aplikacja nie powinna używać atrybutów imaxsockets, imaxudpdg, i lpvendorinfo struktury WSAData gdy wartość atrybutu wversion, po wywołaniu WSAStartup jest co najmniej 2. Wyjaśnienie: This is because the architecture of Windows Sockets has been changed in version 2 to support multiple providers, and WSAData no longer applies to a single vendor's stack. Two new socket options are introduced to supply provider- specific information: SO_MAX_MSG_SIZE (replaces the imaxudpdg element) and PVD_CONFIG (allows any other provider-specific configuration to occur). wversion - Wersja gniazd WinSock którą ma używać biblioteka Ws2_32.dll. whighversion - Najwyższa wersja WinSock jaką może używać biblioteka.dll. Standardowo, wartość taka sama, jak wversion. szdescription - Zerem zakończony string znaków ASCI (null-terminated ASCII string) do którego Ws2_32.dll kopiuje opis implementacji gniazd. Tekst (do 256 znaków) może być używany do opisów wiadomości. szsystemstatus - Zakończony zerem string znaków ASCI do którego WSs2_32.dll kopiuje informacje o statusie lub konfiguracji. Ws2_32.dll powinna używać tego atrybutu do tylko gdy informacje mogą być ważne dla użytkowników, atrybut nie powinien być traktowany jako rozszerzenie zmiennej szdescription. imaxsockets - Pozostawiony dla zgodności poprzednimi wersjami gniazd. Parametr powinien być ignorowany przez Windows Socketsv.2 i wersje późniejsze (nie ma już jednej wartości dla wszystkich dostarczycieli usług). imaxudpdg - Atrybut ignorowany przez gniazda wersji 2 i następne. imaxudpdg pozostawiony dla zgodności z wersją gniazd Windows Sockets 1.1. Nie powinien być używany przy budowaniu nowych aplikacji. Dla określenia wielkości wiadomości dostarczyciela usług dla gniazda i typu gniazda aplikacje powinny używać getsockopt aby uzyskać wartość opcji SO_MAX_MSG_SIZE. lpvendorinfo - Atrybut ignorowany przez Windows Sockets v.2 i następne. lpvendorinfo pozostawiono dla zgodności z wersją gniazd Windows Sockets 1.1. Dla określenia konfiguracji dostarczyciela usług dla gniazda powinny używać getsockopt aby uzyskać wartość opcji PVD_CONFIG. 7

Struktura WSADATA typedef struct WSAData { WORD wversion; WORD whighversion; char szdescription[wsadescription_len+1]; char szsystemstatus[wsasys_status_len+1]; unsigned short imaxsockets; unsigned short imaxudpdg; char FAR * lpvendorinfo; }WSADATA, *LPWSADATA; 8

Nazwa struktury: sockaddr_in Opis: Atrybuty: Specyfikacja struktury sockaddr_in Struktura sockaddr_in zawiera adres IP i numer portu odbiorcy danych. Struktura zadeklarowana w pliku Winsock2.h (dla IPv4), ws2tcpip.h (dla IPv6). sin_family sin_port sin_addr sin_zero Kod rodziny adresów TCP//IP (wartość musi być AF_INET). Numer portu (IP port). Adres IP hosta. Pole służy do uzupełniania tak, aby wielkość struktury była taka sama jak SOCKADDR. Implementacja struktury sockaddr_in: struct sockaddr_in { short unsigned short struct in_addr char }; sin_family; sin_port; sin_addr; sin_zero[8]; 9

Specyfikacja struktury in_addr Nazwa struktury : in_addr Opis: Struktura in_addr adres IP hosta. Struktura zdefiniowana w WINSOCK.H Atrybuty : S_un_b - adres hosta w formacie u_chars. S_un_w - adres hosta w formacie dwóch u_shorts. S_addr - adres hosta w formacie u_long. Implementacja struktury in_addr: struct in_addr { union { struct { unsigned char s_b1, s_b2, s_b3, s_b4; } S_un_b; struct { unsigned short s_w1, s_w2; } S_un_w; unsigned long S_addr; } S_un; }; 10

Nazwa struktury : hostent Opis: Atrybuty : Specyfikacja struktury hostent Struktura jest używana przez funkcje do przechowywania informacji o hoście. Zadeklarowana w pliku Winsock2.h h_name Nazwa hosta. Jeżeli jest używany system DNS (lub podobny) zmienna zawiera pełną nazwę DNS ową hosta FQDN (ang. Fully Qualified Domain Name). W pliku hosts, wartość zmiennej jest drugim wpisem, po adresie IP. h_aliases - Zerem zakończona tablica alternatywnych nazw hosta. h_addrtype - Typ adresu. h_length - Długość w bajtach każdego adresu. h_addr_list - Zerem zakończona lista adresów IP hosta. Adresy IP są zwracane w uporządkowaniu bajtów Big Endian. Makro h_addr zastępuje h_addr_list[0] w celu zgodności ze starszymi wersjami oprogramowania. Przykład. char *ServerName; LPHOSTENT hp; SOCKADDR_IN AdresIpSerwera; hp = gethostbyname(servername); AdresIpSerwera.sin_addr.S_addr = hp->h_addr; 11

Implementacja struktury hostent typedef struct hostent { char FAR* h_name; char FAR FAR** h_aliases; short h_addrtype; short h_length; char FAR FAR** h_addr_list; } hostent; 12

Specyfikacja funkcji WSAStartup() Nazwa funkcji : WSAStartup() Zwracana wartość: int WSAStartup() zwraca zero gdy wywołanie funkcji zakończyło się sukcesem. W innym przypadku zwraca następujące kody błędów: WSASYSNOTREADY Wskazuje, że sieć lub podsieć nie jest przygotowana do transmisji danych. WSAVERNOTSUPPORTED Żądana wersja WinSock nie jest obsługiwana przez implementację WinSock. WSAEINPROGRESS Trwa operacja blokowania WinSock 1.1. WSAEPROCLIM - WSAEFAULT - Osiągnięto granicę liczby żądań dopuszczalną przez WinSock. Błędna wartość wskaźnika lpwsadata (not a valid pointer). Argumenty: WORD wversionrequested - LPWSADATA lpwsadata - [in] Najwyższa obsługiwana wersja WinSock, którą nadawca (caler) może użyć. Bajt najwyższy określa minimalną wersję, najniższy bajt określa maksymalna wersję. [out] Wskaźnik do struktury WSADATA. Opis: Funkcja WSAStartup() inicjuje użycie przez proces biblioteki WS2_32.DLL. Funkcja WSAStartup() musi być pierwszą funkcja Windows Sockets wywołana przez aplikacje. 13

Specyfikacja funkcji WSACleanup() Nazwa funkcji: WSACleanup() Zwracana wartość: int WSACleanup() zwraca zero gdy wywołanie funkcji zakończyło się sukcesem. W innym przypadku zwraca SOCKET_ERROR, i określony kod błędu może być uzyskany poprzez wywołanie finkcji WSAGetLastError(): Argumenty: brak Opis: WSANOTINITIALISED - Przed wywołaniem tej funkcji WSACleanup() musi być wywołana z sukcesem funkcja WSAStartup(). WSAENETDOWN - Awaria sieci (network subsystem has failed). WSAEINPROGRESS - Trwa operacja blokowania WinSock 1.1 lub dostarczyciel usługi (service provider) obsługuje komunikat zwrotny (a callback function). Funkcja WSACleanup() kończy użycie biblioteki WS2_32.DLL. 14

Specyfikacja funkcji socket() Nazwa funkcji: socket() Zwracana wartość: SOCKET Jeżeli nie ma błędów, funkcja socket() zwraca referencje do nowego gniazda. W przeciwnym przypadku zwraca kod INVALID_SOCKET. Kod błędu można uzyskać przez wywołanie funkcji WSAGetLastError(). Argumenty: int af, int type, int protocol af - type - protocol- [in] Typ adresu stosu (address family specification). [in] Typ adresu dla nowych gniazd (SOCK_STREAM, SOCK_DGRAM). [in] Numer protokołu użytego przez gniazdo. Wartość parametru: IPPROTO_IP, IPPROTO_TCP, 0. Opis: Funkcja socket() tworzy gniazdo o określonym typie (specific service provider). Funkcja zadeklarowana w pliku winsock2.h, implementacja w pliku ws2_32.lib. 15

Specyfikacja funkcji WSAGetLastError() Nazwa funkcji: WSAGetLastError() Zwracana wartość: int Argumenty: brak Opis: Funkcja WSAGetLastError() zwraca status błędu ostatniej nieudanej operacji. 16

Specyfikacja funkcji htons() Nazwa funkcji: htons() Zwracana wartość: u_short Funkcja htons() zwraca wartość w uporządkowaniu big-endian (TCP/IP network byte order). Argumenty: u_short hostshort hostshort - [in] 16-bitowa liczba w uporządkowaniu bajtów hosta (Windows: little-endian, Unix: bigendian). Opis: Funkcja htons() konwertuje u_short z uporządkowania bajtów hosta na big-endian. 17

Specyfikacja funkcji inet_addr() Nazwa funkcji : inet_addr() Zwracana wartość: unsigned long Argumenty : const char* cp cp - [in] Zerem zakończony string znaków reprezentujący adres IP zapisany w notacji kropkowanej (np. 127.0.0.1). Opis : Funkcja inet_addr() konwertuje string zawierający adres IPv4 w wersji kropkowanej na odpowiedni adres w strukturze IN_ADDR. Przykład: użycie funkcji inet_addr() w strukturze sockaddr_in atrybut sin_addr.s_addr = inet_addr(nazwa_serwera); 18

Specyfikacja funkcji gethostbyname() Nazwa funkcji : gethostbyname() Zwracana wartość: struct hostent* FAR Argumenty : const char* name name - [in] Wskaźnik do zakończonej zerem nazwy hosta (odbiorcy danych). Opis : Funkcja gethostbyname() pobiera nazwę hosta z bazy hosta. Zamiast gethostbyname() zalecane jest używanie funkcji getaddrinfo(). 19

Specyfikacja funkcji CopyMemory() Nazwa funkcji : CopyMemory() Zwracana wartość: void Argumenty : PVOID Destination, const VOID* Source, SIZE_T Length Destination - [in] Wskaźnik zawierający początkowy adres docelowego bloku danych. Source - Length - [in] Wskaźnik zawierający początkowy adres źródłowego bloku danych. [in] Wielkość kopiowanego bloku danych (wielkość liczona w bajtach). Opis: Funkcja CopyMemory() służy do kopiowania bloków danych między obszarami pamięci. Funkcja zadeklarowana w pliku Winbase.h, Windows.h. 20

Specyfikacja funkcji connect() Nazwa funkcji : connect() Zwracana wartość: int Argumenty : SOCKET s, const struct sockaddr* name, int namelen s - [in] Obiekt identyfikujący niepołączone gniazdo. name - [in] Nazwa gniazda w strukturze SOCKADDR do którego powinno być zrealizowane połączenie. namelen - [in] Długość nazwy gniazda (liczona bajtach). Opis : Funkcja buduje połączenie do określonego gniazda. 21

Specyfikacja funkcji send() Nazwa funkcji : send() Zwracana wartość: int Argumenty : SOCKET s, const char* buf, int len, int flags s buf len flags [in] Obiekt identyfikujący połączone gniazdo. [in] Bufor zawierający dane do wysłania. [in] Długość danych w buforze (liczona w bajtach). [in] Wskaźnik określający typ wywołania funkcji. Flagi: MSG_DONTROUTE Dane nie powinny być rutowane. WinSock service provider może ignorować tą flagę. MSG_OOB Wysyła dane Out-of-Band Data (gniazdo typu TCP, np. SOCK_STREAM). Opis : Funkcja send() wysyła dane do połączonego gniazda. 22

Specyfikacja funkcji recv() Nazwa funkcji : recv() Zwracana wartość: int Jeśli nie ma błędów, funkcja recv() zwraca liczbę odebranych bajtów. Jeśli połączenie zostało zamknięte (gracefully closed), zwracaną wartością jest zero. W pozostałych przypadkach zwracana jest wartość SOCKET_ERROR. Kod błędu można uzyskać wywołując funkcję WSAGetLastError(). Argumenty : SOCKET s, char* buf, int len, int flags s - [in] Obiekt identyfikujący połączone gniazdo. buf - [out] Bufor na przychodzące dane. len - [in] Długość bufora (argumentu buf) w bajtach. flags - [in] Parametr określający typ wywołania funkcji. Opis : Funkcja recv() odbiera dane z połączonego (connected) gniazda lub z gniazda połączonego funkcją bind() (bound socket). 23

Specyfikacja funkcji closesocket() Nazwa funkcji : closesocket() Zwracana wartość: int Argumenty : SOCKET s s [in] Obiekt określający gniazdo do zamknięcia. Opis : Funkcja closesocket() zamyka gniazdo. 24

Nazwa funkcji : bind() Zwracana wartość: int Specyfikacja funkcji bind() W przypadku błędu funkcja zwraca SOCKET_ERROR z kodem który można uzyskać wywołując metodę WSAGetLastError(), w przeciwnym przypadku zwaraca zero. Argumenty : SOCKET s, const struct sockaddr* name, int namelen s - [in] Obiekt identyfikujący niepołączone gniazdo (unbound socket). name - [in] Adres IP do przypisania do gniazda (brany ze struktury SOCKADDR). namelen - [in] Długość (w bajtach) wartości parametru name. Opis : Funkcja kojarzy adres lokalny hosta z gniazdem. 25

Nazwa funkcji : listen() Zwracana wartość: int Specyfikacja funkcji listen() Jeśli nie ma błędów funkcja listen() zwraca zero. W pozostałych przypadkach zwracana jest wartość SOCKET_ERROR. Kod błędu można uzyskać wywołując funkcję WSAGetLastError(). Argumenty : SOCKET s, int backlog s - backlog - [in] Obiekt identyfikujący połączone (bound), nierozłączone (unconnected) gniazdo. [in] Maksymalna długość kolejki czekających połączeń. Jeżeli wartość parametru jest ustawiona na SOMAXCONN, serwer ustawia wartość tego parametru na maksymalnym, ale rozsądnym poziomie. Nie ma standardowej procedury określania wartości tego parametru. Opis : Funkcja listen() ustawia gniazdo w stan nasłuchiwania. 26

Specyfikacja funkcji accept() Nazwa funkcji : accept() Zwracana wartość: SOCKET Jeżeli nie ma błędu funkcja accept() zwraca typ SOCKET. Zwrócona wartość jest uchwytem do gniazda do którego jest tworzone połączenie. W pozostałych przypadkach jest zwracana wartości INVALID_SOCKET. Kod błędu można uzyskać wywołując funkcję WSAGetLastError(). Argumenty : SOCKET s, struct sockaddr* addr, int* addrlen s - addr - [in] Obiekt identyfikujący gniazdo, które przeszło w stan nasłuchiwania poprzez wywołanie funkcji listen(). [out] Parametr opcjonalny, wskaźnik do bufora, który przechowuje adres łączącego się hosta. Format parametru addr jest wyznaczany na podstawie wartości parametru sa_family ze struktury SOCKADDR. addrlen - [out] Opcjonalny wskaźnik do liczby zawierającej długość parametru addr. 27

Specyfikacja funkcji htonl() Nazwa funkcji : htonl() Zwracana wartość: u_long Argumenty : u_long hostlong hostlong [in] 32-bitowa liczba w uporządkowaniu little endian (windows). Opis : Funkcja htonl() konwertuje u_long z uporządkowania little endian na big endian. 28

Specyfikacja funkcji ntohs() Nazwa funkcji : ntons() Zwracana wartość: u_short Funkcja ntons() zwraca wartość w uporządkowaniu hosta. Argumenty : u_short netshort netshort - [in] 16-bit liczba w uporządkowaniu big-endian (TCP/IP network byte order). Opis : Funkcja ntons() konwertuje liczbę u_short z uporządkowania bajtów big-endian na uprządkowanie hosta. Aplikacja decyduje czy konwersja musi być dokonana. Przykład: local.sin_port = ntons((short)iport); 29

Specyfikacja funkcji inet_ntoa() Nazwa funkcji: inet_ntoa() Zwracana wartość: char* FAR Jeżeli nie ma błędów inet_ntoa() zwraca wskaźnik char* do statycznego bufora zawierającego adres w standardzie kropkowanym. W pozostałych przypadkach funkcja zwraca NULL. Argumenty : struct in_addr in in - [in] Wskaźnik do struktury in_addr reprezentującej adres IP hosta. Opis : Funkcja inet_ntoa() konwertuje adres IPv4 na adres w formacie kropkowanym (dotted format). 30

Specyfikacja funkcji CreateThread() Nazwa funkcji : CreateThread() Zwracana wartość: HANDLE Argumenty: Funkcja zwraca uchwyt do nowego wątku. LPSECURITY_ATTRIBUTES lpthreadattributes - [in] Wskaźnik do struktury SECURITY_ATTRIBUTES która określa czy zwrócony uchwyt może być dziedziczony (przez proces potomny). Gdy wartość lpthreadattributes = NULL, uchwyt nie może być dziedziczony. SIZE_T dwstacksize - [in] Początkowa wartość stosu liczona w bajtach. System zaokrągla wartość wielkość strony. Jeżeli parametr ma wartość zero nowy wątek używa domyślnej wartość. LPTHREAD_START_ROUTINE lpstartaddress - [in] Wskaźnik do funkcji aplikacji typu LPTHREAD_START_ROUTINE która ma być wywołana przez wątek. Wskaźnik zawiera początkową (startową) wartość adresu wątku. LPVOID lpparameter - [in] Wskaźnik do zmiennej która ma być przekazana do wątku. DWORD dwcreationflags - [in] Flaga która służy do kontroli tworzenia wątku. Gdy flaga ma wartość CREATE_SUSPENDED, wątek jest po utworzeniu zawieszony, nie zostanie uruchomiony do czasu wywołania funkcji ResumeThread(). Gdy flaga ma zwartość zero wątek jest uruchamiany zaraz po utworzeniu. LPDWORD lpthreadid - [out] Wskaźnik do zmiennej zawierającej informacje o identyfikatorze wątku (thread identifier). 31

Specyfikacja funkcji CreateThread(), cd. Wartości Arg: lpthreadattributes = NULL dwstacksize = 0 lpstartaddress = ClientThread lpparameter = (LPVOID)sClient dwcreationflags = 0 lpthreadid = &dwthreadid Opis : Funkcja CreateThread() tworzy wątek wykonywany wewnątrz wirtualnej przestrzeni adresowej wywołanego procesu. 32

Specyfikacja funkcji CloseHandle() Nazwa funkcji : CloseHandle() Zwracana wartość: BOOL Funkcja zwraca TRUE gdy zamknięcie uchwytu zakończyło się sukcesem. W sytuacji błędnej funkcja zwraca zero. Argumenty : HANDLE hobject hobject - [in, out] Uchwyt do otwartego obiektu. Opis : Funkcja CloseHandle() zamyka otwarty uchwyt obiektu. 33

Nazwa funkcji : ClientThread() Zwracana wartość: DWORD WINAPI Argumenty : LPVOID Implementacja funkcji ClientThread(): Specyfikacja funkcji ClientThread() DWORD WINAPI ClientThread(LPVOID lpparam) { SOCKET sock = (SOCKET)lpParam; char chbuff[default_buffer]; int iret, inumleft, iidx; while(1) { iret = recv(sock, chbuff, DEFAULT_BUFFER, 0); if (iret == 0) return 0; else if (iret == SOCKET_ERROR) { cout << "recv() error no: " << WSAGetLastError() << endl; return 0; } 34

chbuff[iret] = '\0'; Specyfikacja funkcji ClientThread() cout << "Liczba odebranych bajtów: " << chbuff << endl; inumleft = iret; iidx = 0; while(inumleft > 0) { iret = send(sock, &chbuff[iidx], inumleft, 0); if (iret == 0) return 0; else if (iret == SOCKET_ERROR) { cout << "send() error: " << WSAGetLastError() << endl; return 0; } inumleft -= iret; iidx += iret; } // koniec while(inumleft > 0) } // koniec while(1) } return 0; 35

Protokół TCP TCP, ang. Transmission Control Protocol. Specyfikacja RFC 793. TCP jest protokołem warstwy transportowej modelu OSI. Protokół TCP jest protokołem połączeniowym umożliwiającym wykrywanie błędów transmisji. Cechy protokołu TCP: stosuje pozytywne potwierdzanie odbioru danych (pole ACK=1) ma możliwość ustalania priorytetu przesyłania segmentów ma możliwość kontroli i usuwania błędów (np. retransmisji niepotwierdzonych pakietów). 36

Protokół TCP W procesie synchronizacji 'połączenia TCP' między nadawcą (A) i odbiorcą (B) wymieniane są trzy segmenty TCP. Uzgadnianie są wartości w polu 'Sequence number' w wysyłanych i potwierdzanych pakietach: (1) A ----> B flaga SYN=1, pole Sequence number=x, ISN nadawcy (A), Np. SEQ=X=100 (2) A <---- B flagi ACK=1, pole Sequence number=y, ISN odbiorcy (B), SYN=1 pole Acknowledgement number=x+1 Np. SEQ=Y=300, ACK=X+1=101 (3) A ----> B flaga ACK=1 pole Acknowledgement number=y+1, Np. SEQ=X+1=101, ACK=Y+1=301 37

Specyfikacja projektu Serwer TCP Echo Nazwa projektu: tcpserver Typ projektu: Win32 console application Lista plików: tcpserver.cpp Metoda kompilacji: Microsoft Visual C++ 2008. Utworzyć projekt typu 'Win32 console application w menu (-)File-> New -> Project-> Other languages-> Visual C++ -> win32 -> Win32 console application -> wpisać nazwę: tcpserver -> przycisk (OK) -> Okno Win32 application wizard tcpserver-> wybrać: Application settings -> wybrać: Empty project-> Przycisk (Finish). Konfiguracja projektu: (-)Project-> nazwa_projektu Properies... -> Configuration Properies-> Linker-> Input -> Additional Dependecies, wpisać: ws2_32.lib. Funkcjonalność: Aby uruchomić serwer należy w linii komend (Run-> cmd) wpisać: \> tcpserver Aby uruchomić klienta należy w linii komend (Run-> cmd) wpisać: \> tcpclient 38

Specyfikacja projektu. Serwer TCP Echo Pliki nagłówkowe: winsock2.h, iostream Funkcje programu: Funkcje API: Funkcja użytkownika: WSAStartup(), socket(), inet_addr(), bind(), listen(), accept(), recv(), send(), closesocket(), htonl(), ntohs(), inet_ntoa(), CloseHandle(), WSAGetLastError(), WSACleanup(). CreateThread() 39

Specyfikacja projektu. Serwer TCP Echo Zmienne programu: #define DEFAULT_PORT 5150 #define DEFAULT_BUFFER 4096 #define DEFAULT_IP_ADDRESS "127.0.0.1" WSADATA wsd; SOCKET slisten, sclient; int iaddrsize; HANDLE hthread; DWORD dwthreadid; struct sockaddr_in local, client; int iport = DEFAULT_PORT; // numer portu do nasluchiwania BOOL binterface = FALSE; // nasluchiwanie na okreslonej karcie char szaddress[128] = DEFAULT_IP_ADDRESS; // adres IP karty do nasłuchowania 40

(1) Sprawdzenie czy zostały otwarte biblioteki WinSock. Czy WSAStartup(MAKEWORD(2,2), &wsd)!= 0? (2) Utworzenie gniazda. slisten = socket(af_inet, SOCK_STREAM,, IPPROTO_TCP ); (3) Inicjowanie obiektu local struktury sockaddr_in. local.sin_addr.s_addr = inet_addr(szaddress); local.sin_family = AF_INET; local.sin_port = htons(iport); (4) Kojarzenie adresu lokalnego hosta z gniazdem. bind(slisten, (struct sockaddr *)&local, sizeof(local)); (5) Nasłuchiwanie na połączenie i akceptacja połączenia. listen(slisten, 8); // 8 - maksymalna długość kolejki czekających połączeń sclient = accept(slisten, (struct sockaddr *)&client, &iaddrsize); (6) Utworzenie wątku dla połączenia z klientem. hthread = CreateThread(NULL, 0, ClientThread, (LPVOID)sClient, 0, &dwthreadid); (7) Zamknięcie wątku i sesji CloseHandle(hThread); closesocket(slisten); WSACleanup(); 41

Specyfikacja projektu. Klient TCP Echo Nazwa projektu: Typ projektu: Lista plików: tcpclient Win32 console application tcpclient.cpp Metoda kompilacji: Microsoft Visual C++ 2008. Utworzyć projekt typu 'Win32 console application w menu (-)File-> New -> Project-> Other languages-> Visual C++ -> win32 -> Win32 console application -> wpisać nazwę: tcpclient -> przycisk (OK) -> Okno Win32 application wizard tcpclient-> wybrać: Application settings -> wybrać: Empty project-> Przycisk (Finish). Konfiguracja projektu: (-)Project-> nazwa_projektu Properies... -> Configuration Properies-> Linker-> Input -> Additional Dependecies, wpisać: ws2_32.lib. Funkcjonalność: tcpclient łączy się z serwerem za pomcą protokołu TCP, wysyła wiadomość do serwer. Serwer odpowiada, odsyłając tą samą wiadomość (odpowiedź echa). Uruchomienie serwera: \>tcpserver Uruchomienie klienta: \>tcpclient 42

Specyfikacja projektu. Klient TCP Echo Pliki nagłówkowe: winsock2.h, iostream Funkcje programu: Funkcje API: Struktury programu: WSAStartup(), WSAGetLastError(), socket(), htons(), inet_addr(), gethostbyname(), connect(), send(), recv(), closesocket(), WSACleanup(). WSDATA, sockaddr_in, hostent 43

Specyfikacja projektu. Klient TCP Echo Zmienne programu: #define DEFAULT_COUNT 1 #define DEFAULT_SERVER_PORT 5150 #define DEFAULT_BUFFER 2048 #define DEFAULT_MESSAGE Test serwera TCP #define DEFAULT_SERVER 127.0.0.1 //#define DEFAULT_SERVER host_name WSADATA SOCKET char int wsd; sclient; chbuffer[default_buffer]; iretsend; struct sockaddr_in struct hostent server; *host = NULL; char chserver[128] = DEFAULT_SERVER, // nazwa serwera chmessage[1024] = DEFAULT_MESSAGE; // tekst wiadomosci do wyslania int iport = DEFAULT_SERVER_PORT; // numer portu serwera do polaczenia DWORD dwcount = DEFAULT_COUNT; // liczba wyslanych wiadomosci 44

Klient TCP Echo. Struktura programu. (1) Sprawdzenie poprawności argumentów przekazywanych do programu. (2) Sprawdzenie czy zostały otwarte biblioteki WinSock Czy WSAStartup(MAKEWORD(2,2), &wsd)!= 0 (3) Utworzenie gniazda. sclient = socket(af_inet, SOCK_STREAM, IPPROTO_TCP); (4) Inicjowanie obiektu server struktury sockaddr_in. server.sin_family = AF_INET; server.sin_port = htons(iport); server.sin_addr.s_addr = inet_addr(chserver); (5) Pobranie adresu IP serwera gdy podano jego nazwę host = gethostbyname(chserver); 45

Klient TCP Echo. Struktura programu. (6) Przekazanie adresu IP serwera do obiektu server CopyMemory(&server.sin_addr, host->h_addr_list[0], host->h_length); (7) Połączenie i sprawdzenie czy połączenie zostało utworzone connect(sclient, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR (8) Wysłanie danych na serwer, ret liczba wysłanych bajtów. iret = send(sclient, chmessage, strlen(chmessage), 0); (9) Odebranie danych z serwera. iret = recv(sclient, chbuffer, DEFAULT_BUFFER, 0); (10) Zamkniecie gniazda i sesji closesocket(sclient); WSACleanup(); 46

///////////////////////////////// // TCP serwer ///////////////////////////////// #include <winsock2.h> #include <iostream> using namespace std; #define DEFAULT_SERVER_PORT 5150 #define DEFAULT_BUFFER 4096 #define DEFAULT_IP_ADDRESS "127.0.0.1" int main() { WSADATA wsd; SOCKET slisten, sclient; int iaddrsize; HANDLE hthread; DWORD dwthreadid; struct sockaddr_in local, client; int iport = DEFAULT_SERVER_PORT; // numer portu do nasluchiwania BOOL binterface = FALSE; // nasluchiwanie na okreslonej karcie char szaddress[128] = DEFAULT_IP_ADDRESS; // adres IP karty do nasluchowania if (WSAStartup(MAKEWORD(2,2), &wsd)!= 0) { cout << "WSAStartup() error" << endl; return 0; } 47

slisten = socket(af_inet, SOCK_STREAM, IPPROTO_IP); if (slisten == SOCKET_ERROR) { cout << "socket() error: " << WSAGetLastError() << endl; closesocket(slisten); WSACleanup(); return 0; } if (binterface) { local.sin_addr.s_addr = inet_addr(szaddress); } else local.sin_addr.s_addr = htonl(inaddr_any); local.sin_family = AF_INET; local.sin_port = htons(iport); if (bind(slisten, (struct sockaddr *)&local, sizeof(local)) == SOCKET_ERROR) { cout << "bind() error: " << WSAGetLastError() << endl; closesocket(slisten); WSACleanup(); return 0; } listen(slisten, 8); 48

while (1) { iaddrsize = sizeof(client); sclient = accept(slisten, (struct sockaddr *)&client, &iaddrsize); if (sclient == INVALID_SOCKET) { cout << "accept() error: " << WSAGetLastError() << endl; closesocket(slisten); WSACleanup(); return 0; } cout << "Accepted client: " << inet_ntoa(client.sin_addr) << ":" << ntohs(client.sin_port) << endl; hthread = CreateThread(NULL, 0, ClientThread,(LPVOID)sClient, 0, &dwthreadid); if (hthread == NULL) { cout << "CreateThread() error: " << GetLastError() << endl; return 0; } CloseHandle(hThread); } // koniec while (1) closesocket(slisten); WSACleanup(); return 0; } // koniec main() 49

///////////////////////////// // TCP Echo client ///////////////////////////// #include <winsock2.h> #include <iostream> using namespace std; #define DEFAULT_COUNT 1 #define DEFAULT_SERVER_PORT 5150 #define DEFAULT_BUFFER 2048 #define DEFAULT_MESSAGE "Test serwera TCP" #define DEFAULT_SERVER "127.0.0.1" // #define DEFAULT_SERVER "builder" //mozna wpisac nazwe hosta int main() { WSADATA SOCKET char int wsd; sclient; chbuffer[default_buffer]; iretsend; struct sockaddr_in server; struct hostent *host = NULL; char chserver[128] = DEFAULT_SERVER, // nazwa serwera chmessage[1024] = DEFAULT_MESSAGE; // tekst wiadomosci do wyslania na serwer int iport = DEFAULT_SERVER_PORT; // numer portu serwera do polaczenia DWORD dwcount = DEFAULT_COUNT; // liczba wyslanych wiadomosci 50

if (WSAStartup(MAKEWORD(2,2), &wsd)!= 0) { cout << "WSAStartup() error" << endl; return 0; } sclient = socket(af_inet, SOCK_STREAM, IPPROTO_TCP); if (sclient == INVALID_SOCKET) { cout << "socket() error no: " << WSAGetLastError() << endl; return 0; } server.sin_family = AF_INET; server.sin_port = htons(iport); server.sin_addr.s_addr = inet_addr(chserver); if (server.sin_addr.s_addr == INADDR_NONE) { host = gethostbyname(chserver); if (host == NULL) { cout << "Unable to resolve: " << chserver << endl; return 0; } CopyMemory(&server.sin_addr, host->h_addr_list[0], host->h_length); } if (connect(sclient, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) { cout << "connect() error no: " << WSAGetLastError()<< endl; return 0; } 51

for(unsigned int i=0; i<dwcount; i++) { iretsend = send(sclient, chmessage, strlen(chmessage), 0); if (iretsend == 0) return 0; else if (iretsend == SOCKET_ERROR) { cout << "send() error no: " << WSAGetLastError() << endl; return 0; } cout << "Wyslano bajtow: " << iretsend << endl; iretsend = recv(sclient, chbuffer, DEFAULT_BUFFER, 0); if (iretsend == 0) return 0; else if (iretsend == SOCKET_ERROR) { cout << "recv() error no: " << WSAGetLastError() << endl; return 0; } chbuffer[iretsend] = '\0'; cout << "Odebrano " << iretsend << " bajtow. Msg: " << chbuffer << endl; } // end for() closesocket(sclient); WSACleanup(); return 0; } // end main() 52