Python cung cấp sẵn cho chúng ta hai cấp độ truy cập để lập trình mạng. Cấp độ này đó là, cấp độ truy cập thấp và cấp truy cập độ cao.

  • Cấp độ truy cập thấp: Ở cấp độ thấp, bạn có thể truy cập hỗ trợ socket cơ bản trong hệ điều hành cơ bản, cho phép bạn triển khai các máy khách và máy chủ cho cả giao thức hướng kết nối và không kết nối.
  • Cấp độ truy cập cao: Ở mức cao cho phép triển khai các giao thức như HTTP, FTP, v.v.

Trong bài này, chúng ta sẽ lập trình mạng Python với cấp độ truy cập thấp. Và chủ yếu ta sẽ cùng nhau tìm hiểu chính về các khái niệm liên quan đến Socket có trong Python.

1. Khái niệm Socket trong Python

Trong một kênh có sự giao tiếp hai chiều, các Socket chính là điểm cuối của kênh giao tiếp này. Các socket (điểm cuối) này có thể giao tiếp trong một quá trình, giữa các quá trình trên cùng một máy hoặc giữa các quá trình trên các máy khác nhau. Sockets sử dụng các giao thức khác nhau để xác định loại kết nối cho giao tiếp port-to-port  giữa máy khách (clients) và máy chủ (servers). Sockets có thể được triển khai trên một số loại kênh khác nhau: socket miền Unix, TCP, UDP, v.v.

Socket có một số thuật ngữ thông tin được liệt kê ở dưới bảng này:

Thuật ngữ Mô tả
Domain Là họ các giao thức được sử dụng làm cơ chế vận chuyển. Các giá trị này là các hằng số như AF_INET, PF_INET, PF_UNIX, PF_X25, v.v.
Type Là kiểu giao tiếp giữa các Socket. Thường là SOCK_STREAM cho các giao thức hướng kết nối và SOCK_DGRAM cho các giao thức không kết nối.
Protocol Xác định loại giao thức được sử dụng cho DomainType. Thông thường, nó bằng 0
Port Máy chủ (servers) lắng nghe các máy khách (clients) gọi trên một hoặc nhiều cổng nó có thể là một chuỗi chứa số cổng, tên của dịch vụ hoặc cổng Fixnum
Hostname Xác định giao diện mạng – nó có thể như là:

  • Một chuỗi chứa tên máy chủ, địa chỉ IPv6 hoặc địa chỉ kép.
  • Một số nguyên
  • Một chuỗi có độ dài bằng 0
  • Một chuỗi “<brodcast>”

2. Mô-đun socket trong Python

Mô-đun socket là một phần được tích hợp sẵn trong Python. Để sử dụng được mô-đun này ta cần nhập chúng vào chương trình Python như sau:

import socket

Để khởi tạo một socket, bạn phải sử dụng hàm socket.socket() có sẵn trong mô-đun socket, cú pháp khởi tạo như sau:

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

Tham số:

  • socket_family – Đây là AF_UNIX hoặc AF_INET
  • socket_type – Đây là SOCK_STREAM hoặc SOCK_DGRAM.
  • protocol – Điều này thường bị bỏ qua, mặc định là 0.

2.1 Các hàm socket tạo server trong Python

Khi bạn đã có đối tượng socket , thì bạn có thể sử dụng các hàm cần thiết để tạo server và client của mình. Dưới đây là một số hàm cần thiết sử dụng trong chương trình tạo server.

Cú pháp hàm Mô tả
s.bind() Phương thức này liên kết địa chỉ (hostname, port) với socket.
s.listen() Phương thức này thực hiện lắng nghe trên cổng (port) và hostname đã được liên kết ở hàm s.bind(). Việc lắng nghe được thực hiện trên giao thức TCP
s.accept() Phương thức này sẽ thiết lập kết nối và chấp nhận thụ động kết nối máy khách TCP, đợi cho đến khi kết nối đến

2.2 Các hàm socket tạo client trong Python

Khi một server được tạo ra, nó sẽ luôn lắng nghe và chấp nhận thụ động các kết nối của client tới server. Để một client có thể kết nối đến một server thì cần sử dụng phương thức:

Cú pháp hàm Mô tả
s.connect() Phương thức này thực hiện kết nối từ client tới một server thông qua hostnameport.

2.3 Các hàm socket sử dụng trong client và server trong Python

Các hàm dưới đây được sử dụng cả trong khu vực máy chủ (server) và trong các máy khách (client). Các hàm này chủ yếu là các hàm thực hiện truyền thông các thông điệp mà từ server gửi về clinet hay các thông điệp mà client gửi lên server.

Cú pháp hàm Mô tả
s.recv() Phương thức này về nhận bản tinTCP
s.send() Phương thức này thực hiện truyền đi thông điệp TCP
s.recvfrom() Phương thức này nhận về bản tin UDP
s.sendto() Phương thức này thực hiện truyền đi thông điệp UDP
s.close() Phương thức này đóng lại các socket
socket.gethostname() Phương thức này trả về tên máy chủ.

3. Lập trình mạng với mô-đun socket trong Python

Socket giúp cho các tầng TCP hay TCP Layer định danh ứng dụng mà dữ liệu sẽ được gửi tới thông qua cổng port (trong đó cổng port là một hằng số), sau đó tiến hành kết nối giữa client và server. Dưới đây là mô hình hoạt động giữa client và server sau khi được khởi tạo:

Mô tả các bước khởi tạo, kết nối và trao đổi thông tin giữa client và server ở trong mô hình trên như sau:

  1. Khởi tạo một máy chủ (server) thông qua hàm socket()
  2. Liên kết máy chủ với hostport thông qua hàm bind()
  3. Cho phép máy chủ (server) lắng nghe trên port đó thông qua hàm listen()
  4. Tạo yêu cầu kết nối từ máy khách (client) tới máy chủ thông qua hàm connect()
  5. Từ phía máy chủ (server) sẽ chấp nhận yêu cầu kết nối của máy khách (client) thông qua hàm accept()
  6. Sau khi máy khách đã kết nối được tới máy chủ, khi đó có thể thực hiện trao đổi thông tin giữa client – server thông qua hàm read()/write()
  7. Việc trao đổi tin hoàn thành có thể đóng kết nối giữa client – server thông qua hàm close()

Để hiểu rõ hơn các bước trên, chúng ta sẽ cùng nhau đi vào thực hiện code các phần liên quan đến máy chủ và máy khách trong Python bằng cách sử dụng mô-đun có sẵn socket.

3.1 Tạo một máy chủ (server) trong Python

Để viết các máy chủ trong Python, chúng ta sẽ sử dụng hàm socket có sẵn trong mô-đun socket để khởi tạo một đối tượng socket.

Sau khi một đối tượng socket được khởi tạo, ta có thể sử dụng hàm s.bind() để liên kết giữa hostport vào trong server. Sau khi liên kết thành công, ta gọi hàm s.listen() để lắng nghe các kết nối từ phía client vào server.

Tiếp theo, gọi phương thức s.accept() để chấp thuận kết nối giữa client tới server và thực hiện trao đổi thông tin giữa client – server bằng các hàm s.read()/s.write() (việc trao đổi thông tin sẽ chỉ thực hiện sau khi việc chấp thuận kết nối giữa client tới server hoàn tất)

Bước cuối cùng, khi việc trao đổi thông tin hoàn thành ta sẽ đóng kết nối lại bằng hàm s.close()

  • File server.py sẽ trông như sau:
#server.py
import socket              

#Tao doi tuong socket cho server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#Lay ra ten host tren may (localhost)
host = socket.gethostname() #host = "localhost"
#Chi dinh cong cho ket noi
port = 8080   
# Lien ket host va port voi may chu             
s.bind((host, port))
# Lang nghe cac ket noi tu clien toi server (chi chap nhan 5 ket noi)
s.listen(5)     
# Tao mot thong diep de truyen ve client
message = "Chao mung ban den voi server cua laptrinhtudau.com"
message1 = "Hoc lap trinh tai laptrinhtudau.com"
while True:
    # Chap thuan ket noi giua client toi server
    c, addr = s.accept()    
    print ("Mot may khach dang thuc hien ket noi tu:", addr)
    # Truyen thong diep tu server ve client
    c.send(message.encode())
    c.send(message1.encode())
    # Dong ket noi
    c.close()

3.2 Tạo một máy khách (client) trong Python

Để viết chương trình máy khách trong Python, ta cần tạo một đối tượng socket. Và điều kiện để client kết nối tới server chính là cần có được thông tin của host port của server cần kết nối tới. Sau đó sẽ gọi kết nối tới server thông qua hàm s.connect() – truyền vào hostport

Hàm s.connect(host, port) sẽ mở một kết nối TCP với tên máy chủ trên cổng . Khi bạn đã thực sự kết nối tới server – khi đó bạn sẽ nhận được các bản tin mà server sẽ gửi về cho bạn bằng cách sử dụng hàm s.recv(1024) để nhận tin nhắn với độ dài 1024 byte mà mỗi lần server gửi tin về cho client. Để hiện thị ra các thông điệp của server gửi cho client – khi đó ta cần gọi hàm s.recv(1024).decode() để giải mã và thực hiện hiển thị các thông điệp mà server gửi về client.

Bước cuối cùng, khi việc trao đổi thông tin hoàn thành ta sẽ đóng kết nối lại bằng hàm s.close()

  • File client.py sẽ trông như sau:
# client.py
import socket 

# Tao doi tuong socket cho client
s = socket.socket()
#Lay ra ten host cua server (localhost)
host = socket.gethostname() #host = "localhost"
# Lay ra port cua server
port = 8080
# Thuc hien ket noi tu client toi server
s.connect((host, port)) 

# Nhan lai tin nhan duoc gui tu server toi client
msg = s.recv(1024) # 1024 la so byte ma client co the nhan duoc tin nhan cua server gui ve trong mot lan

# Duyet va hien thi cac phan tin nhan tiep theo
while msg:
  print("Ban tin nhan tu server: ", msg.decode())
  msg = s.recv(1024)

# Dong ket noi toi server
s.close()

3.3 Thực thi chương trình client – server trong Python

Trước khi tới phần thực thi chương trình client – server trong Python, bạn cần đảm bảo rằng bạn đã tạo và chèn đoạn code server vào file server.py và đã thực hiện chèn các đoạn code của client vào file client.py (Đã được đề cập ở phần 3.1 và phần 3.2)

Đầu tiên, bạn sẽ thực thi file server.py bằng câu lệnh như sau trong command line (CMD)

PS C:\Users\Administrator\Desktop> python server.py
_

Tiếp theo, sẽ thực thi file client.py bằng câu lệnh như sau trong command line (CMD) và nếu như nhận được bản tin được gửi từ server về client thì đồng nghĩa với việc kết nối client – server đã thành công!

PS C:\Users\Administrator\Desktop> python client.py
Ban tin nhan tu server:  Chao mung ban den voi server cua laptrinhtudau.com
Ban tin nhan tu server:  Hoc lap trinh tai laptrinhtudau.com

Lưu ý: File server.py phải được thực thi trước và thực thi trong nền (nghĩa là không được tắt file này) để khi file client.py thực thi mới có thể kết nối tới được server!