Sieci
System operacyjny
Protokoły sieciowe
Protokoły sieciowe - jest to zestaw reguł według których jest możliwa komunikacja pomiędzy co najmniej dwoma urządzeniami sieciowymi. Aby połączenie było możliwe przez dwie strony musi być użyty ten sam protokół. Zdarza się że np. komputery korzystają z kilku protokołów w ramach jednej sieci jednak nie jest optymalne rozwiązanie.
Najważniejsze to:
TCP
SERWER
KLIENT
socket()
socket()
Stworzenie gniazd
bind()
przywiązanie do adresów
listen()
accept()
connect()
nawiązanie połączenia
read()
write()
write()
read()
przesyłanie danych
TCP
Cechy:
Dość tych pierdów, czas na kod! :)
TCP
# Echo server program�import socket��HOST = '' # Symbolic name meaning all available interfaces�PORT = 50007 # Arbitrary non-privileged port�s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)�s.bind((HOST, PORT))�s.listen(1)�conn, addr = s.accept()�print('Connected by', addr)�while True:� data = conn.recv(1024)� if not data: break� conn.sendall(data)�conn.close()
# Echo client program�import socket��HOST = '127.0.0.1' # The localhost�PORT = 50007 # The same port as used by the server�s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)�s.connect((HOST, PORT))�s.sendall(b'Hello, world')�data = s.recv(1024)�s.close()�print('Received', repr(data))
TCP
# Echo server program�import socket��HOST = '' # Symbolic name meaning all available interfaces�PORT = 50007 # Arbitrary non-privileged port�s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)�s.bind((HOST, PORT))�s.listen(1)�conn, addr = s.accept()�print('Connected by', addr)�while True:� data = conn.recv(1024)� if not data: break� conn.sendall(data)�conn.close()
# Echo client program�import socket��HOST = '127.0.0.1' # The localhost�PORT = 50007 # The same port as used by the server�s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)�s.connect((HOST, PORT))�s.sendall(b'Hello, world')�data = s.recv(1024)�s.close()�print('Received', repr(data))
Stworzenie gniazda
TCP
Address family ustawiamy na Internet Protocol
związuje socket'a z adresem i portem
Nasłuchiwanie (z ustawieniem maksymalnej ilości zakolejkowanych połączeń na 1)
Akceptacja połączenia, zwraca połaczenie z klientem, oraz jego adres
nawiązanie połączenia
przesyła całe dane(bez wzgledu na ilość)
TCP - wiele połączeń
Mamy dwa możliwe rozwiązania podstawowe:
Funkcja select znajduje się w module select:
select.select(rlist, wlist, xlist[, timeout])
Jej argumentami są lista wejścia, lista wyjścia, lista wyjątków, zwraca 'wykolejkowane' zdarzenia w kolejnosci takiej samej jak argumenty wejsciowe.
Przykład:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)�inputready,outputready,exceptready = select.select([s],[],[])
Wątki dziedziczą po klasie Thread z modułu threading. Muszą nadpisywać metodę run. Są wywoływane za pomocą metody start()
class MyTCPServerConn(Thread):� def __init__(self, sock):� Thread.__init__(self)� self.sock = sock� def run(self):� while True:� data = self.sock.recv(1024)� if not data: break� self.sock.sendall(data)��s = socket.socket(secket.AF_INET, socket.SOCK_STREAM)�...(bind, listen)�MyTCPServerConn(s.accept()[0]).start()
Select - przykład
import select �import socket �import sys ��host = '' �port = 50000 �backlog = 5 �size = 1024 �server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) �server.bind((host,port)) �server.listen(backlog) �input = [server,sys.stdin] �running = 1 �
while running: � inputready,outputready,exceptready = select.select(input,[],[]) �� for s in inputready: �� if s == server: � # handle the server socket � client, address = server.accept() � input.append(client) �� elif s == sys.stdin: � # handle standard input � junk = sys.stdin.readline() � running = 0 �� else: � # handle all other sockets � data = s.recv(size) � if data: � s.send(data) � else: � s.close() � input.remove(s) �server.close()
UDP
SERWER
KLIENT
socket()
socket()
Stworzenie gniazd
przydzielenie adresów
recvfrom()
sendto()
sendto()
recvfrom()
dane (zlecenie)
dane(odpowiedź)
bind()
UDP
Cechy:
UDP - przykład
# Echo client program�import socket��HOST = '127.0.0.1' # The localhost�PORT = 50008 # The same port as used by the server�s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)�addr = (HOST, PORT)�s.sendto(b'Hello, world', addr)�data, addr = s.recvfrom(1024)�s.close()�print('Received', repr(data), 'from', addr)
# Echo server program�import socket��HOST = '' # Symbolic name meaning all available interfaces�PORT = 50008 # Arbitrary non-privileged port�s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)�s.bind((HOST, PORT))�data, addr = s.recvfrom(1024)�print("Received from ", addr)�s.sendto(data, addr)�s.close()
UDP - przykład
# Echo client program�import socket��HOST = '127.0.0.1' # The localhost�PORT = 50008 # The same port as used by the server�s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)�addr = (HOST, PORT)�s.sendto(b'Hello, world', addr)�data, addr = s.recvfrom(1024)�s.close()�print('Received', repr(data), 'from', addr)
# Echo server program�import socket��HOST = '' # Symbolic name meaning all available interfaces�PORT = 50008 # Arbitrary non-privileged port�s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)�s.bind((HOST, PORT))�data, addr = s.recvfrom(1024)�print("Received from ", addr)�s.sendto(data, addr)�s.close()
UDP
Związanie się z adresem
Podajemy adres na który wysłamy
Aby otrzymać dane korzystamy z metody recvfrom, która zwraca krotkę z danymi oraz adres skąd one przyszły
Gotowe klasy serwera
ViScreen!!
Pełna dokumentacja:
http://docs.python.org/3.3/library/socket.html#module-socket
http://docs.python.org/3.3/library/socketserver.html
http://pyqt.sourceforge.net/Docs/PyQt4/
https://deptinfo-ensip.univ-poitiers.fr/ENS/pyside-docs/contents.html
Przykłady:
Zadanie
Napisz kod klienta SMTP lub POP3 za pomocą dostępnych klas w pythonie (patrz dokumentacja) �http://docs.python.org
SMTP
import smtplib, getpass��def prompt(prompt):� return input(prompt).strip()��fromaddr = "twoj_emal@gmail.com"�toaddrs = prompt("To: ").split()�print("Enter message, end with ^D (Unix):")��# Add the From: and To: headers at the start!�msg = ("From: %s\r\nTo: %s\r\n\r\n"� % (fromaddr, ", ".join(toaddrs)))�while 1:� try:� line = input()� except EOFError:� break� if not line:� break� msg = msg + line��print("Message length is " + repr(len(msg)))�
login = "twoj_email@gmail.com"�password = getpass.getpass() �server = smtplib.SMTP('smtp.gmail.com:587')�server.ehlo() #wymagane przez tls�server.starttls() #dla bezpieczeństwa�server.login(login, password)�server.sendmail(fromaddr, toaddrs, msg)�server.quit()
POP3
import getpass, poplib��M = poplib.POP3_SSL('pop.gmail.com', '995')�M.user("username")�M.pass_(getpass.getpass())�numMessages = len(M.list()[1])�for i in range(numMessages): #wyświetli wszystkie wiadomości� for j in M.retr(i+1)[1]:� print(j)
System Operacyjny
System operacyjny (ang. Operating System, skrót OS) – oprogramowanie zarządzające systemem komputerowym, tworzące środowisko do uruchamiania i kontroli zadań użytkownika.
Każdy proces ma swoje id które nazywa się PID (Process ID)
możemy je pobrać za pomocą os.getpid()
os.fork() - służy do tworzenia nowych kopii siebie samego. Zwraca numer PID. Jeśli jesteśmy w dziecku zwraca 0, w a PID w rodzicu.
Co istotne tutaj są przydzielane nowe zasoby. (dokładna kopia zasobu macierzystego)
os.getppid() - zwraca numer PID rodzica.
os.wait() - czeka na zakończenie procesu dziecka, zwraca jego PID i wartość z którą zakończył się proces.
os.waitpid() - czeka na zakończenie konkretnego procesu, można podać tutaj dodatkowe opcje.
os.kill()
System operacyjny
Jest kilka sposobów wywołania nowego programu, jednym z nich (takim bardzo c-like) jest execl. Ma kilka odmian:
My skupimy się na os.execvp(file,args), czyli podajemy nazwę pliku który musi być w scieżkach systemowych ( $PATH w unixach, w konsoli wpisz echo $PATH, żeby zobaczyć), oraz argumenty z którymi ma być wykonany program.
Czas na przykład w kodzie :)
mini-bash
import os�if __name__ == '__main__':� while(1):� czy_w_tyle = False� polecenie = input("$ ")� if polecenie.lower() == "exit":� break� else:� pid = os.fork()� args = polecenie.split()� if args[-1] == '&': � args = args[:-1]� czy_w_tyle=True� if pid == 0:� try:� os.execvp(args[0], args)� except OSError:� print("Błędne dane wejściowe")� elif czy_w_tyle:� print("PID = %s" % pid)� else:� os.waitpid(pid, 0)
Systemy operacyjne
Są też inne sposoby uruchamiania programów, jedna bardzo szybka robiąca wręcz za nas wszystko to:
os.system("ls -l"), zwraca nam odpowiedź programu oraz wartość wyjściową.
Oraz bardziej skomplikowany moduł subprocess, stworzy do wiekszej komunikacji z daną aplikacją.
subprocess.call(['ls', '-l'])
subprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None,universal_newlines=False, startupinfo=None, creationflags=0)
Ma metody taki jak: communicate, send_singal, terminate, wait, poll...
Jednak do bardziej skomplikowanych rozmów między aplikacjami polecam pexpect - dodatkowy moduł oferujący bardziej zaawanase zastosowania - proste w użyciu :)
child = pexpect.spawn('git pull')�child.expect("Username*", timeout=2)�child.expect("Password*", timeout=2)
Zabawy z plikami
os.walk(path) - przechodzi po całym drzewie katalogów
os.path.isdir() - sprawdza czy dany string jest katalogiem
os.path.join() - łączy stringi w scieżkę
os.mkdir() - tworzy nowy katalog
Pozatym kopiowanie etc. moduł shutil, a w nim:
shutil.copy() - kopiuje plik
shutil.copy2() - kopiuje wraz z metadanymi
shutil.rmtree() - usuwa drzewo katalogów od podanego
shutil.move() - przenosi pliki
Przykład
Przeglądanie drzewa katalogów i plików od jednego wyżej niż bieżący
from os import walk�from os.path import join�for dirname, dirnames, filenames in walk("../"):� print("In: ", dirname)� for dirn in dirnames: print(join(dirname,dirn))� for filen in filenames: print("\t.", filen)� print("\n")
Pytania
?