Gniazdo i jego metody

Gniazda to punkty końcowe dwukierunkowego kanału komunikacyjnego. Mogą komunikować się w ramach procesu, między procesami na tej samej maszynie lub między procesami na różnych maszynach. Podobnie gniazdo sieciowe jest punktem końcowym w przepływie komunikacji między dwoma programami działającymi w sieci komputerowej, takiej jak Internet. Jest to rzecz czysto wirtualna i nie oznacza żadnego sprzętu. Gniazdo sieciowe można rozpoznać po unikalnej kombinacji adresu IP i numeru portu. Gniazda sieciowe mogą być implementowane w wielu różnych typach kanałów, takich jak TCP, UDP i tak dalej.

Różne terminy związane z gniazdem używanym w programowaniu sieciowym są następujące:

Domena

Domena to rodzina protokołów wykorzystywana jako mechanizm transportu. Te wartości są stałymi, takimi jak AF_INET, PF_INET, PF_UNIX, PF_X25 i tak dalej.

Rodzaj

Typ oznacza rodzaj komunikacji między dwoma punktami końcowymi, zwykle SOCK_STREAM dla protokołów zorientowanych na połączenie i SOCK_DGRAM dla protokołów bezpołączeniowych.

Protokół

Można to wykorzystać do identyfikacji wariantu protokołu w domenie i typu. Jego wartość domyślna to 0. Zwykle jest pomijana.

Nazwa hosta

Działa jako identyfikator interfejsu sieciowego. Nazwa hosta nie może być łańcuchem, adresem z kropkami lub adresem IPV6 w notacji z dwukropkiem (i prawdopodobnie kropką).

Port

Każdy serwer nasłuchuje klientów dzwoniących na co najmniej jednym porcie. Port może być numerem portu Fixnum, ciągiem znaków zawierającym numer portu lub nazwą usługi.

Moduł gniazd w Pythonie do programowania gniazd

Aby zaimplementować programowanie gniazd w Pythonie, musimy skorzystać z modułu Socket. Poniżej znajduje się prosta składnia tworzenia gniazda -

import socket
s = socket.socket (socket_family, socket_type, protocol = 0)

Tutaj musimy zaimportować bibliotekę gniazd, a następnie utworzyć proste gniazdo. Poniżej przedstawiono różne parametry używane podczas tworzenia gniazda -

  • socket_family - To jest AF_UNIX lub AF_INET, jak wyjaśniono wcześniej.

  • socket_type - To jest SOCK_STREAM lub SOCK_DGRAM.

  • protocol - Zwykle jest to pomijane, domyślnie 0.

Metody gniazd

W tej sekcji poznamy różne metody gniazd. Trzy różne zestawy metod gniazd opisano poniżej -

  • Metody gniazda serwera
  • Metody gniazda klienta
  • Ogólne metody gniazd

Metody gniazda serwera

W architekturze klient-serwer istnieje jeden scentralizowany serwer, który świadczy usługi, a wielu klientów otrzymuje usługi z tego scentralizowanego serwera. Klienci wysyłają również żądanie do serwera. Oto kilka ważnych metod gniazd serwera w tej architekturze -

  • socket.bind() - Ta metoda wiąże adres (nazwa hosta, numer portu) z gniazdem.

  • socket.listen()- Ta metoda zasadniczo nasłuchuje połączeń wykonanych z gniazdem. Uruchamia odbiornik TCP. Backlog to argument tej metody określający maksymalną liczbę połączeń w kolejce. Jego minimalna wartość to 0, a maksymalna to 5.

  • socket.accept()- To zaakceptuje połączenie klienta TCP. Para (conn, adres) jest parą wartości zwracanych w tej metodzie. W tym przypadku conn jest nowym obiektem gniazda używanym do wysyłania i odbierania danych dotyczących połączenia, a adres jest adresem powiązanym z gniazdem. Przed użyciem tej metody należy użyć metody socket.bind () i socket.listen ().

Metody gniazda klienta

Klient w architekturze klient-serwer żąda od serwera i odbiera usługi z serwera. W tym celu jest tylko jedna metoda dedykowana dla klientów -

  • socket.connect(address)- ta metoda aktywnie intymnie łączy się z serwerem lub w prostych słowach ta metoda łączy klienta z serwerem. Argument address reprezentuje adres serwera.

Ogólne metody gniazd

Oprócz metod wykorzystujących gniazda klienta i serwera, istnieją pewne ogólne metody wykorzystujące gniazda, które są bardzo przydatne w programowaniu za pomocą gniazd. Ogólne metody gniazd są następujące -

  • socket.recv(bufsize)- Jak sama nazwa wskazuje, ta metoda odbiera komunikat TCP z gniazda. Argument bufsize oznacza rozmiar bufora i określa maksymalne dane, które ta metoda może otrzymać w dowolnym momencie.

  • socket.send(bytes)- Ta metoda służy do wysyłania danych do gniazda, które jest połączone z komputerem zdalnym. Argument bajty podaje liczbę bajtów wysłanych do gniazda.

  • socket.recvfrom(data, address)- Ta metoda odbiera dane z gniazda. Ta metoda zwraca wartość dwóch par (dane, adres). Dane określają odebrane dane, a adres określa adres gniazda wysyłającego dane.

  • socket.sendto(data, address)- Jak sama nazwa wskazuje, ta metoda służy do wysyłania danych z gniazda. Ta metoda zwraca wartość dwóch par (dane, adres). Dane określają liczbę wysłanych bajtów, a adres określa adres zdalnego komputera.

  • socket.close() - Ta metoda zamknie gniazdo.

  • socket.gethostname() - Ta metoda zwróci nazwę hosta.

  • socket.sendall(data)- Ta metoda wysyła wszystkie dane do gniazda, które jest połączone z maszyną zdalną. Nieostrożnie przesyła dane do momentu wystąpienia błędu, a jeśli tak się stanie, używa metody socket.close (), aby zamknąć gniazdo.

Program do nawiązywania połączenia między serwerem a klientem

Aby ustanowić połączenie między serwerem a klientem, musimy napisać dwa różne programy w Pythonie, jeden dla serwera, a drugi dla klienta.

Program po stronie serwera

W tym programie używającym gniazd po stronie serwera użyjemy rozszerzenia socket.bind()metoda, która wiąże go z określonym adresem IP i portem, dzięki czemu może nasłuchiwać żądań przychodzących na tym IP i porcie. Później używamysocket.listen()metoda, która przełącza serwer w tryb nasłuchiwania. Liczba, powiedzmy 4, jako argument funkcjisocket.listen()metoda oznacza, że ​​4 połączenia są utrzymywane w oczekiwaniu, jeśli serwer jest zajęty i jeśli 5. gniazdo próbuje się połączyć, połączenie jest odrzucane. Wyślemy wiadomość do klienta za pomocą plikusocket.send()metoda. Pod koniec używamysocket.accept() i socket.close()metoda inicjowania i zamykania połączenia odpowiednio. Poniżej znajduje się program po stronie serwera -

import socket
def Main():
   host = socket.gethostname()
   port = 12345
   serversocket = socket.socket()
   serversocket.bind((host,port))
   serversocket.listen(1)
   print('socket is listening')
   
   while True:
      conn,addr = serversocket.accept()
      print("Got connection from %s" % str(addr))
      msg = 'Connecting Established'+ "\r\n"
      conn.send(msg.encode('ascii'))
      conn.close()
if __name__ == '__main__':
   Main()

Program po stronie klienta

W programie używającym gniazd po stronie klienta musimy utworzyć obiekt gniazda. Następnie połączymy się z portem, na którym działa nasz serwer - w naszym przykładzie 12345. Następnie nawiążemy połączenie za pomocąsocket.connect()metoda. Następnie za pomocąsocket.recv()klient otrzyma wiadomość z serwera. W końcusocket.close() metoda zamknie klienta.

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

host = socket.gethostname()
port = 12345

s.connect((host, port))
msg = s.recv(1024)

s.close()
print (msg.decode('ascii'))

Teraz po uruchomieniu programu po stronie serwera otrzymamy na terminalu następujące dane wyjściowe -

socket is listening
Got connection from ('192.168.43.75', 49904)

Po uruchomieniu programu po stronie klienta na innym terminalu otrzymamy następujące dane wyjściowe -

Connection Established

Obsługa wyjątków gniazd sieciowych

Istnieją dwa bloki, a mianowicie try i exceptktóry może służyć do obsługi wyjątków gniazd sieciowych. Poniżej znajduje się skrypt w Pythonie do obsługi wyjątków -

import socket
host = "192.168.43.75"
port = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

try:
   s.bind((host,port))
   s.settimeout(3)
   data, addr = s.recvfrom(1024)
   print ("recevied from ",addr)
   print ("obtained ", data)
   s.close()
except socket.timeout :
   print ("No connection between client and server")
   s.close()

Wynik

Powyższy program generuje następujące dane wyjściowe -

No connection between client and server

W powyższym skrypcie najpierw utworzyliśmy obiekt gniazda. Następnie podano adres IP hosta i numer portu, na którym działa nasz serwer - w naszym przykładzie 12345. Później używany jest blok try i wewnątrz niego za pomocąsocket.bind()spróbujemy powiązać adres IP i port. Używamysocket.settimeout()metoda ustawiania czasu oczekiwania klienta, w naszym przykładzie ustawiamy 3 sekundy. Używany jest blok except, który wypisuje komunikat, jeśli połączenie nie zostanie nawiązane między serwerem a klientem.