W tym poście przedstawię w jaki sposób wykonać serwer TCP na Raspberry Pi w Pythonie.
[Ź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:
- def procesTCP():
- import socket
- import select
- import sys
- import os
- import threading
- TCP_IP = "192.254.168.2"
- s = None;
- TCP_PORT = 1025
- BUFFER_SIZE = 1024
- while 1:
- s= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.bind((TCP_IP, TCP_PORT))
- s.listen(5)
- conn, addr = s.accept()
- print("Connection open")
- while 1:
- data = conn.recv(BUFFER_SIZE)
- if not data: break
- print("recivecede")
- conn.send(data)
- conn.close()
- 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ł.
- class STATUS:
- INIT = 1
- CONNECT = 2
- WAIT = 3
Poniżej klasa zawierająca informacje o adresie ip, porcie oraz rozmiar bufora:
- class NetworkConfig:
- ADRES_TCP = "196.254.28.45"
- PORT_TCP = 1025
- BUFFER_SIZE = 1024
Teraz główna funkcja tworząca połączenie oraz obsługująca odebrane dane:
- class ServerTCP:
- def __init__(self):
- self.connection = STATUS.INIT
- self.server = None
- self.client = 0
- self.data = []
- self.client_address = 0
- self.start = 0
- self.end = 0
- def __call__(self):
- while True:
- if self.connection == STATUS.CONNECT:
- try:
- self.data = self.client.recv(NetworkConfig.BUFFER_SIZE)
- except:
- self.connection = STATUS.CONNECT
- if self.data:
- response = self.data
- try:
- self.client.send(response)
- except:
- self.connection = STATUS.CONNECT
- else:
- self.connection = STATUS.WAIT
- elif self.connection==STATUS.INIT:
- try:
- self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- self.server.bind((NetworkConfig.ADRES_TCP, NetworkConfig.PORT_TCP))
- self.connection = STATUS.WAIT
- except:
- self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- elif self.connection==STATUS.WAIT:
- try:
- self.server.listen(5)
- self.client, self.client_address = self.server.accept()
- self.connection = STATUS.CONNECT
- except:
- self.client.close()
- self.server.close()
- self.connection = STATUS.INIT
Obie funkcje można wywołać w osobnym procesie:
- multiProcesJobs = []
- try:
- serProces = multiprocessing.Process(target=ServerTCP(), args=())
- multiProcesJobs.append(serProces)
- serProces.start()
- except:
- print("SERVER PROCESS ERROR!!")