Tworzenie gniazda dla klienta
Po zainicjowaniu należy utworzyć wystąpienie obiektu SOCKET dla klienta.
Aby utworzyć gniazdo
Zadeklaruj obiekt addrinfo, który zawiera strukturę sockaddr i zainicjuj jego wartości. W przypadku tej aplikacji rodzina adresów internetowych jest nieokreślona, aby można było zwrócić adres IPv6 lub IPv4. Aplikacja żąda, aby typ gniazda był gniazdem strumienia dla protokołu TCP.
struct addrinfo *result = NULL, *ptr = NULL, hints; ZeroMemory( &hints, sizeof(hints) ); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP;
Wywołaj funkcję getaddrinfo żądającą adresu IP nazwy serwera przekazanej w wierszu polecenia. Port TCP na serwerze, z którego klient będzie się łączyć, jest zdefiniowany przez DEFAULT_PORT jako 27015 w tym przykładzie. Funkcja getaddrinfo zwraca wartość jako liczbę całkowitą sprawdzaną pod kątem błędów.
#define DEFAULT_PORT "27015" // Resolve the server address and port iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result); if (iResult != 0) { printf("getaddrinfo failed: %d\n", iResult); WSACleanup(); return 1; }
Utwórz obiekt SOCKET o nazwie ConnectSocket.
SOCKET ConnectSocket = INVALID_SOCKET;
Wywołaj funkcjęgniazdai zwróć jej wartość do zmiennej ConnectSocket. W przypadku tej aplikacji użyj pierwszego adresu IP zwróconego przez wywołanie getaddrinfo , który odpowiada rodzinie adresów, typowi gniazda i protokołowi określonemu w parametrze hints. W tym przykładzie określono gniazdo strumienia TCP z typem gniazda SOCK_STREAM i protokołem IPPROTO_TCP. Rodzina adresów nie została określona (AF_UNSPEC), więc zwrócony adres IP może być adresem IPv6 lub IPv4 serwera.
Jeśli aplikacja kliencka chce nawiązać połączenie przy użyciu tylko protokołu IPv6 lub IPv4, należy ustawić rodzinę adresów na AF_INET6 dla protokołu IPv6 lub AF_INET dla protokołu IPv4 w wskazówkach parametru.
// Attempt to connect to the first address returned by // the call to getaddrinfo ptr=result; // Create a SOCKET for connecting to server ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
Sprawdź błędy, aby upewnić się, że gniazdo jest prawidłowym gniazdem.
if (ConnectSocket == INVALID_SOCKET) { printf("Error at socket(): %ld\n", WSAGetLastError()); freeaddrinfo(result); WSACleanup(); return 1; }
Parametry przekazywane do gniazda funkcji można zmienić dla różnych implementacji.
Wykrywanie błędów jest kluczową częścią pomyślnego kodu sieciowego. Jeśli wywołanie gniazda za pomocą zakończy się niepowodzeniem, zostanie zwrócony INVALID_SOCKET. Instrukcja if w poprzednim kodzie służy do przechwytywania wszelkich błędów, które mogą wystąpić podczas tworzenia gniazda. WSAGetLastError zwraca numer błędu skojarzony z ostatnim błędem, który wystąpił.
Notatka
W zależności od aplikacji może być konieczne bardziej rozbudowane sprawdzanie błędów.
Na przykład ustawienie hints.ai_family do AF_UNSPEC może spowodować niepowodzenie podczas próby nawiązania połączenia. W takim przypadku należy użyć określonej wartości IPv4 (AF_INET) lub IPv6 (AF_INET6).
WSACleanup służy do kończenie korzystania z biblioteki DLL WS2_32.
Następny krok: nawiązywanie połączenia z gniazdem
Tematy pokrewne