logo

Programowanie gniazd w C/C++

W dzisiejszym świecie sieci komputerowe odgrywają ważną rolę w dziedzinie przesyłania danych. Jest to temat, który powinien znać każdy programista. W sieci komputerowej programowanie gniazd jest jednym z najważniejszych tematów w świecie programowania. W tym temacie omówimy programowanie za pomocą gniazd i różne metody programowania za pomocą gniazd zaimplementowane w C++.

W C++ programowanie przez gniazda to metoda, która łączy ze sobą dwa lub więcej węzłów w sieci, dzięki czemu węzły mogą współdzielić dane bez ich utraty. W tym przypadku jeden węzeł nasłuchuje jednego portu, który jest podłączony do określonego adresu IP. Gdy klient dotrze do serwera, serwer tworzy odbiornik gniazda.

Co to jest gniazdo?

Przyjrzyjmy się gniazdu, omawiając przykład w czasie rzeczywistym. Gniazdo to rodzaj medium zapewniającego połączenie między dwoma urządzeniami. Gniazdkiem może być ładowarka do telefonu zapewniająca połączenie między gniazdkiem a telefonem lub telefonem i laptopem. Za pomocą gniazda różne aplikacje są podłączane do sieci lokalnej za pomocą różnych portów. Za każdym razem, gdy tworzone jest gniazdo, serwer określa program, a ten program określa gniazdo i adres domeny.

Gniazdo to rodzaj mechanizmu służącego do wymiany danych pomiędzy różnymi procesami. W tym przypadku procesy te występują albo w różnych urządzeniach, albo w tym samym urządzeniu podłączonym do sieci. Po utworzeniu połączenia dla gniazda dane mogą być przesyłane w obu kierunkach i kontynuowane do momentu, aż jeden z punktów końcowych zamknie połączenie.

Programowanie gniazd w C/C++

Procedura w komunikacji klient-serwer

Aby nawiązać komunikację klient-serwer, musimy przestrzegać pewnych procedur. Są one następujące.

    Gniazdo elektryczne:Za pomocą gniazda możemy stworzyć nową komunikację.Wiązać:Za pomocą tego możemy dołączyć adres lokalny do gniazda.Słuchać:Z tą pomocą; możemy zaakceptować połączenie.Zaakceptować:Z tą pomocą; możemy zablokować połączenie przychodzące do czasu nadejścia żądania.Łączyć:Z tą pomocą; możemy spróbować nawiązać połączenie.Wysłać:Za pomocą tego; możemy przesyłać dane przez sieć.Odbierać:Z tą pomocą; możemy odbierać dane przez sieć.Zamknąć:Za pomocą tego możemy zwolnić połączenie z sieci.

Etapy tworzenia gniazda serwera

Istnieje kilka etapów, w których możemy utworzyć gniazdo dla serwera. Są one następujące.

    int gniazdocr:Gniazdo (domena, typ, protokół)Gniazdokr:Jest to typ całkowity i działa jak procedura obsługi plików.Domena:Jest to domena komunikacyjna i jest typu całkowitego.Typ:Jest to rodzaj komunikacji.SOCK_DGRAM:Jest to rodzaj protokołu UDP, który jest zawodny i bezpołączeniowy.Protokół:Służy do przypisania wartości protokołu do adresu IP, która wynosi 0. Wartość protokołu jest podobna do wartości występującej w polu protokołu nagłówka IP kieszeni.

Co to jest połączenie?

Połączenie to rodzaj relacji między dwoma maszynami, w przypadku której oba programy są o sobie znane. Te dwa programy wiedzą, jak nawiązać połączenie między sobą; innymi słowy, możemy powiedzieć, że te dwa programy wiedzą, jak przesyłać bity przez sieć. Połączenie gniazda oznacza, że ​​obie maszyny powinny znać wszystkie informacje między sobą, takie jak numer telefonu, adres IP i port TCP.

Gniazdo to typ obiektu podobny do pliku, który umożliwia programowi akceptowanie połączenia przychodzącego i umożliwianie mu wysyłania lub odbierania połączenia przychodzącego. Jest to także rodzaj zasobu przypisanego do procesu serwera.

Serwer może utworzyć gniazdo za pomocą funkcji Socket(). Gniazdo to nie może być współdzielone z żadnym innym procesorem.

    Ustawia opcję:Za pomocą Setsockopt możemy manipulować różnymi opcjami gniazda, do których odwołuje się deskryptor pliku gniazda. Ten proces jest całkowicie opcjonalny. Za pomocą Setsockopt możemy ponownie wykorzystać port i adres klienta i serwera. Gdy serwer podaje błąd „adres już używany”, możemy temu zapobiec za pomocą Setsockopt.Wiązać:Za pomocą funkcji bind możemy powiązać gniazdo z adresem i portem. Operację tę wykonuje się po utworzeniu gniazda. Na przykład, jeśli spróbujemy powiązać serwer z hostem lokalnym, wówczas użyjemy INADDR_ANY do zdefiniowania adresu IP serwera.Słuchać:Gniazdo trybu połączenia możemy wykonać za pomocą funkcji nasłuchiwania (). Przykładem gniazda trybu połączenia jest SOCK_STREAM. Można to zdefiniować za pomocą argumentu gniazda. Służy do akceptowania połączenia przychodzącego, wykonywania operacji w kolejce dla połączenia przychodzącego i wykonywania zaległości połączenia przychodzącego. Kiedy połączenie przychodzące żąda potwierdzenia od serwera, gniazdo przechodzi w tryb pasywny. Parametr backlog serwera odnosi się do faktu, że nie może on pozwolić na więcej niż jedno połączenie jednocześnie z serwerem. Jeśli nadeszło połączenie przychodzące i kolejka jest pełna, serwer zgłasza błąd ze wskazaniem „ ECONNREFUSED”. Za pomocą funkcji Listen() połączenie przychodzące jest wstrzymywane, a gdy kolejka jest pusta, wywołuje wszystkie połączenia przychodzące do serwera.Zaakceptować:Za pomocą wywołania systemowego Accept(); możemy wykonać gniazdo oparte na połączeniu. Niektóre gniazda oparte na połączeniach to SOCK_STREAMan i SOCK_SEQPACKET. Wyodrębnia wszystkie połączenia przychodzące, które przychodzą jako pierwsze i pozwala, aby ich żądania trafiły do ​​serwera. Nowo połączona lista nie jest w stanie nasłuchiwać za pomocą innego argumentu utworzenia nowego gniazda.

Etapy dla Klienta

    Podłączenie do gniazda:Jest to dokładnie to samo, co metoda tworzenia serwera.Łączyć:Połączenie z gniazdem możemy zainicjować za pomocą wywołania systemowego connect(). Jeżeli parametrem gniazda jest typ SOCK_DGRAM, to za pomocą funkcji connect() możemy zdefiniować datagram jako trwały. Jeżeli gniazdo jest typu SOCK_STREAM, to możemy podjąć próbę wykonania kolejnego połączenia z serwerem. Za pomocą funkcji connect() możemy utworzyć połączenie również dla stowarzyszenia zagranicznego. Jeśli gniazdo jest niezwiązane, system przypisuje unikalną wartość lokalnemu powiązaniu. Kiedy system pomyślnie zakończy wywołanie, gniazdo jest gotowe do wysyłania i odbierania dowolnego typu danych.Wyślij/Odbierz:Funkcje send() i recv() mogą wykonać poniższą operację.
  • Gniazdo, na którym mogą być przesyłane między sobą dane.
  • Bufor pamięci może przechowywać dane o adresie, takie jak adres_danych i adres_bufora.
  • Zajmuje się rozmiarem bufora, np. len_of_data i len_of_buffer.
  • Zajmuje się flagą, która mówi, w jaki sposób dane zostaną wysłane.

Kroki ustanawiania połączenia w gnieździe

Ustanawia połączenie pomiędzy różnymi klientami i serwerem. Ale zarówno klient, jak i serwer mogą obsłużyć połączenie przez gniazdo. Każdy proces musi ustanowić połączenie dla swojego własnego gniazda.

Etapy tworzenia gniazda po stronie klienta są następujące:

  • Tworzy gniazdo za pomocą wywołania systemowego Socket().
  • Następnie musimy połączyć się z adresem gniazda serwera za pomocą wywołania system().
  • Następnie musimy wysłać i odebrać dane. Możemy to zrobić na różne sposoby. możemy wykonać tę funkcję read() i write().

Etapy tworzenia gniazda po stronie serwera są następujące:

  • Najpierw tworzy gniazdo za pomocą wywołania systemowego Socket().
  • Następnie wiąże gniazdo z adresem za pomocą wywołania systemowego bind(). Adres składa się z numeru portu gniazda serwera na komputerze hosta.
  • Następnie nasłuchuje połączenia za pomocą wywołania systemowego nasłuchującego ().
  • Następnie serwer akceptuje połączenie przychodzące za pomocą wywołania systemowego Accept(). Blokuje także wszystkie przychodzące polecenia, dopóki klient nie zostanie podłączony do serwera.
  • Następnie rozpoczyna się proces wysyłania i odbierania danych.

Łączenie wielu klientów bez wielowątkowości

Istnieją różne przykłady, w których widzimy, jak pojedynczy użytkownik może połączyć się z serwerem. W dzisiejszym świecie programowania wielu użytkowników jest podłączonych do serwera za pomocą różnych gniazd.

Można to osiągnąć na różne sposoby. Jednym z nich jest wielowątkowość. Możemy to osiągnąć za pomocą wielowątkowości. Proces wielowątkowy możemy zaimplementować za pomocą funkcjiselect().

Przykład:

Kod dla klienta:

 // Client side C/C++ program to demonstrate Socket // programming #include #include #include #include #include #define PORT 8080 int main(int argc, char const* argv[]) { int sock = 0, valread, client_fd; struct sockaddr_in serv_addr; char* hello = &apos;Hello from client&apos;; char buffer[1024] = { 0 }; if ((sock = socket(AF_INET, SOCK_STREAM, 0)) <0) 0 8080 { printf('
 socket creation error 
'); return -1; } serv_addr.sin_family="AF_INET;" serv_addr.sin_port="htons(PORT);" convert ipv4 and ipv6 addresses from text to binary form if (inet_pton(af_inet, '127.0.0.1', &serv_addr.sin_addr) <="0)" printf( '
invalid address not supported ((client_fd="connect(sock," (struct sockaddr*)&serv_addr, sizeof(serv_addr))) 0) printf('
connection failed send(sock, hello, strlen(hello), 0); printf('hello message sent
'); valread="read(sock," buffer, 1024); printf('%s
', buffer); closing the connected close(client_fd); 0; code for server: server side c c++ program demonstrate programming #include #define port int main(int argc, char const* argv[]) server_fd, new_socket, valread; struct sockaddr_in address; opt="1;" addrlen="sizeof(address);" buffer[1024]="{" }; char* hello="Hello from server" ; creating file descriptor ((server_fd="socket(AF_INET," sock_stream, 0)) perror('socket failed'); exit(exit_failure); forcefully attaching (setsockopt(server_fd, sol_socket, so_reuseaddr | so_reuseport, &opt, sizeof(opt))) perror('setsockopt'); address.sin_family="AF_INET;" address.sin_addr.s_addr="INADDR_ANY;" address.sin_port="htons(PORT);" (bind(server_fd, sockaddr*)&address, sizeof(address)) perror('bind (listen(server_fd, 3) perror('listen'); ((new_socket="accept(server_fd," (socklen_t*)&addrlen)) perror('accept'); send(new_socket, close(new_socket); listening shutdown(server_fd, shut_rdwr); pre> <p> <strong>Compiling:</strong> </p> <img src="//techcodeview.com/img/c-tutorial/33/socket-programming-c-c-2.webp" alt="Socket Programming in C/C++"> <p> <strong>Output:</strong> </p> <img src="//techcodeview.com/img/c-tutorial/33/socket-programming-c-c-3.webp" alt="Socket Programming in C/C++"> <h2>Uses of Socket Programming</h2> <p>Socket programs are used to communicate between various processes, usually running on different systems. It is mostly used to create a client-server environment. This post provides the various functions used to create the server and client program and an example program.</p> <p>In the example, the client program sends a file name to the server, and the server sends the contents of the file back to the client. Socket programming usually pertains to basic communication protocols like TCP/UDP and raw sockets like ICMP. These protocols have a small communication overhead when compared to underlying protocols such as HTTP/DHCP/SMTP etc.</p> <p> <strong>Some of the basic data communications between the client and server are:</strong> </p> <ul> <li>File Transfer: Sends name and gets a file.</li> <li>Web Page: Sends URL and gets a page.</li> <li>Echo: Sends a message and gets it back.</li> </ul> <h2>Disadvantages</h2> <ul> <li>C++ can establish communication only with the machine requested and not with any other machine on the network.</li> <li>Sockets allow only raw data to be sent. This means that the client and server need mechanisms to interpret the data.</li> </ul> <hr></0)>