sobota, 13 stycznia 2018

Raspberry pi - Python - Serwer TCP

W tym poście przedstawię w jaki sposób wykonać serwer TCP na Raspberry Pi w Pythonie.

Znalezione obrazy dla zapytania raspberry pi
[Źródło: https://www.element14.com/community/community/raspberry-pi]


Aplikacja została napisana bezpośrednio w Pythonie. Przy wykorzystaniu standardowych bibliotek. W związku z tym projekt można bez problemów przenieść na inny system czy komputer.

Kod programu:


Poniżej będą się znajdowały dwa rozwiązania do projektu. Pierwszy z nich jest dosyć prosty opiera się na funkcji akceptującej połączenie, drugi natomiast ma zdefiniowane stany połączenia oraz przygotowaną osobną klasę do nawiązywania komunikacji.

Rozwiązanie 1:

  1. def procesTCP():
  2.     import socket
  3.     import select
  4.     import sys
  5.     import os
  6.     import threading
  7.     TCP_IP = "192.254.168.2"
  8.     s = None;
  9.     TCP_PORT = 1025
  10.     BUFFER_SIZE = 1024
  11.     while 1:
  12.         s= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  13.         s.bind((TCP_IP, TCP_PORT))
  14.         s.listen(5)
  15.         conn, addr = s.accept()
  16.         print("Connection open")
  17.         while 1:
  18.             data = conn.recv(BUFFER_SIZE)
  19.             if not data: break
  20.             print("recivecede")
  21.             conn.send(data)
  22.         conn.close()
  23.         print("connectionClose")

Funkcja na początku dodaje potrzebne biblioteki, następnie definiuje adres IP serwera, port TCP oraz rozmiar buforu. Cała obsługa połączenia odbywa się w dwóch pętlach while.

Pierwsza instrukcja w pętli while tworzy gniazdo TCP/IP. Następnie poprzez instrukcję bind() tworzone jest połączenie gniazda z adresem serwera oraz portem.

Wywołanie funkcji listen() ustawia gniazdo w opcji serwera. Instrukcja accept() oczekuje na połączenie.

Kolejna pętla while zawiera obsługę odbierania oraz przesyłania danych do klienta.

Rozwiązanie 2:

Drugie rozwiązanie korzysta z tych samych metod co pierwsze. Różnica polega na przechodzeniu pomiędzy różnymi stanami połączenia.

Poniżej znajduje się klasa przechowująca możliwe stany połączenia w jakich serwer będzie się znajdował.

  1. class STATUS:
  2.     INIT = 1
  3.     CONNECT = 2
  4.     WAIT = 3

Poniżej klasa zawierająca informacje o adresie ip, porcie oraz rozmiar bufora:

  1. class NetworkConfig:
  2.     ADRES_TCP = "196.254.28.45"
  3.     PORT_TCP = 1025
  4.     BUFFER_SIZE = 1024

Teraz główna funkcja tworząca połączenie oraz obsługująca odebrane dane:

  1. class ServerTCP:
  2.     def __init__(self):
  3.         self.connection = STATUS.INIT
  4.         self.server = None
  5.         self.client = 0
  6.         self.data = []
  7.         self.client_address = 0
  8.         self.start = 0
  9.         self.end = 0
  10.     def __call__(self):
  11.         while True:
  12.             if self.connection == STATUS.CONNECT:
  13.                 try:
  14.                     self.data = self.client.recv(NetworkConfig.BUFFER_SIZE)
  15.                 except:
  16.                     self.connection = STATUS.CONNECT
  17.                 if self.data:
  18.                     response = self.data
  19.                     try:
  20.                         self.client.send(response)
  21.                     except:
  22.                         self.connection = STATUS.CONNECT
  23.                 else:
  24.                     self.connection = STATUS.WAIT
  25.             elif self.connection==STATUS.INIT:
  26.                 try:
  27.                     self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  28.                     self.server.bind((NetworkConfig.ADRES_TCP, NetworkConfig.PORT_TCP))
  29.                     self.connection = STATUS.WAIT
  30.                 except:
  31.                     self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  32.             elif self.connection==STATUS.WAIT:
  33.                 try:
  34.                     self.server.listen(5)
  35.                     self.client, self.client_address = self.server.accept()
  36.                     self.connection = STATUS.CONNECT
  37.                 except:
  38.                     self.client.close()
  39.                     self.server.close()
  40.                     self.connection = STATUS.INIT

Obie funkcje można wywołać w osobnym procesie:

  1. multiProcesJobs = []
  2. try:
  3.     serProces = multiprocessing.Process(target=ServerTCP(), args=())
  4.     multiProcesJobs.append(serProces)
  5.     serProces.start()
  6. except:
  7.     print("SERVER PROCESS ERROR!!")