1 of 25

2 of 25

Sieci

System operacyjny

3 of 25

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/IP a w nim:
    • HTTP (Hypertext Transfer Protocol)
    • HTTPS (HTTP Secure)
    • FTP (File Transfer Protocol)
    • TCP (Transmission Control Protocol)
    • UDP (User Datagram Protocol)
    • SMTP (Simple Mail Transfer Protocol)
    • POP3 (Post Office Protocol v. 3)
    • Telnet
    • SSH (Secure Shell)
    • DNS (Domain Name System)

4 of 25

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

5 of 25

TCP

Cechy:

  • połączeniowy (przed rozpoczęciem wymiany strony muszą nazwiązać połączenie)
    • full-duplex (kiedy jedno połączenie wysyła dane to drugie może odbierać)
    • dwa końce połączenia

  • strumieniowy (wysyła połączeniem ciągłą sekwencje bitów, TCP nie gwarantuje, że dane zostaną dostarczone do programu odbierającego w kawałkach tego samego rozmiaru co wysyłane przez program nadajacy)

  • niezawodne tworzenie połączenia (dwa programy musiały się zgodzić na połączenie, duplikaty pakietów z poprzednich połączeń nie mogą wyglądały na prawidłowe odpowiedzi)

  • niezawodność (dane wysyłane połączeniem są dostarczone dokładnie tak, jak były wysłane, bez żadnych braków czy dostarczania nie w kolejności)

  • łagodne kończnie połączenia (program użytkowy może otworzyć połączenie, wysłać dowolną ilość danych, a nastepnie prosić o zamknięcie połączenia.

Dość tych pierdów, czas na kod! :)

6 of 25

TCP

# Echo server programimport 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 programimport 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))

7 of 25

TCP

# Echo server programimport 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 programimport 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ść)

8 of 25

TCP - wiele połączeń

Mamy dwa możliwe rozwiązania podstawowe:

  • funkcja select()
  • wątki
  • forki

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()

9 of 25

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()

10 of 25

UDP

SERWER

KLIENT

socket()

socket()

Stworzenie gniazd

przydzielenie adresów

recvfrom()

sendto()

sendto()

recvfrom()

dane (zlecenie)

dane(odpowiedź)

bind()

11 of 25

UDP

Cechy:

  • bardzo prosty (w porównaniu z TCP)
  • bezpołączeniowy (nie następuje tutaj connect, nie śledzi się połączeń sesji)
  • datagramowy (każdy komunikat UDP nazywa się datagramem użytkownika, jest to nagłówek który określa port z którego wysłano komunikat, port odbiorcy, długość komunikatu oraz sumę kontrolną oraz obszar danych)
  • zawodny (może zgubić pakiety, zduplikować, mieć opóźnienia, dostarczać pakiety w niewłaściwej kolejności... dobrze sprawdza się w małych sieciach - np. lokalnych, ale zawodzic w intersieciach TCP/IP)

12 of 25

UDP - przykład

# Echo client programimport 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 programimport 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()

13 of 25

UDP - przykład

# Echo client programimport 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 programimport 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

14 of 25

Gotowe klasy serwera

ViScreen!!

Przykłady:

  • SocketServer
    • TCPServer
    • UDPServer
    • ThreadingUDPServer
    • ThreadingTCPServer
  • QT
    • QTcpSocket
    • QUdpSocket
  • Pyside
    • QTcpSocket
    • QUdpSocket
  • Twisted

15 of 25

Zadanie

Napisz kod klienta SMTP lub POP3 za pomocą dostępnych klas w pythonie (patrz dokumentacja) �http://docs.python.org

16 of 25

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:breakif 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()

17 of 25

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ścifor j in M.retr(i+1)[1]:print(j)

18 of 25

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()

19 of 25

System operacyjny

Jest kilka sposobów wywołania nowego programu, jednym z nich (takim bardzo c-like) jest execl. Ma kilka odmian:

  • os.execl(path, arg0, arg1, ...)
  • os.execle(path, arg0, arg1, ..., env)
  • os.execlp(file, arg0, arg1, ...)
  • os.execlpe(file, arg0, arg1, ..., env)
  • os.execv(path, args)
  • os.execve(path, args, env)
  • os.execvp(file, args)
  • os.execvpe(file, args, env)

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 :)

20 of 25

mini-bash

import os�if __name__ == '__main__':while(1):� czy_w_tyle = False� polecenie = input("$ ")if polecenie.lower() == "exit":breakelse:� pid = os.fork()� args = polecenie.split()if args[-1] == '&': � args = args[:-1]� czy_w_tyle=Trueif 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)

21 of 25

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)

22 of 25

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

23 of 25

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")

24 of 25

Pytania

?

25 of 25