Python – Lập trình mạng với Socket

4.6/5 - (15 votes)

Python cung cấp module Socket hỗ trợ thực thi các giao thức mạng, dùng tạo các ứng dụng server hoặc client.

Chúng ta sẽ viết một ứng dụng Echo Server đơn giản.

Server

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print ("Starting server on port 10000")
server.bind((socket.gethostname(), 10000))
server.listen(1)

while True:
    conn, client = server.accept()
    try:
       print ("Connection from", client)
 
    while True:
        data = conn.recv(1024)
        print ("Receive from client:", data)
        if data:
            print ("Response to client")
            conn.sendall(data)
        else:
            print ("No data received")
            break
    finally:
        conn.close()

Server sẽ lắng nghe nghe các kết nối từ client, nhận tin nhắn từ client nếu có và gửi trả lời về lại client.

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

Đầu tiên chúng ta tạo một đối tượng socket, tham số AF_INET cho biết chúng ta sử dụng IP v4, SOCK_TREAM là dùng giao thức TCP. Ngoài ra còn một số giá trị khác như AF_INET6 là dùng IP v6, AF_UNIX là chỉ kết nối các ứng dụng trong một máy (không dùng mạng), SOCK_DGRAM là dùng giao thức UDP.

print("Starting server on port 10000")
server.bind((socket.gethostname(), 10000))

Phương thức bind() chỉ định socket sẽ lắng nghe với địa chỉ IP của máy lấy từ phương thức gethostname() trên cổng 10000.

server.listen(1)

while True:
    conn, client = server.accept()

Phương thức listen() cho python biết socket này là một server, tham số của phương thức này là số lượng các kết nối có thể có trong hàng đợi, ít nhất là 0 và cao nhất là do hệ điều hành chỉ định (thường là 5). Phương thức accept() sẽ đưa server vào trạng thái chờ đợi cho đến khi có kết nối thì sẽ trả về một tuple gồm có một socket khác dùng để truyền dữ liệu qua lại với client và một tuple nữa bao gồm địa chỉ ip và port của ứng dụng client.

while True:
    data = conn.recv(1024)
    print ("Receive from client:", data)
    if data:
        print ("Response to client")
        conn.sendall(data)
    else:
        print ("No data received")
        break

Phương thức recv() sẽ đọc các byte dữ liệu có trong socket conn, tham số 1024 tức là mỗi lần chỉ đọc tối ta 1024 byte dữ liệu, nên chúng ta đặt trong vòng lặp while để có thể đọc hết những gì client gửi sang, nếu có dữ liệu gửi sang thì chúng ta gửi trả lời về client thông qua phương thức sendall()ở đây chúng ta chỉ đơn giản là gửi lại những gì client đã gửi lên server thôi.

finally:
    conn.close()

Khi đã đọc hết dữ liệu từ client, chúng ta break vòng lặp và ngắt kết nối bằng phương thức close().

Client

import socket

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((socket.gethostname(), 10000))
try:
    message = "Hello from client"
    client.sendall(message.encode('ascii'))

    amount_received = 0
    amount_expected = len(message)

    while amount_received < amount_expected:
        data = client.recv(1024)
        amount_received += len(data)
        print ("Response from server:", data)
finally:
    print ("Closing socket")
    client.close()

Chúng ta cũng tạo một đối tượng socket kết nối và gửi tin nhắn lên server.

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('localhost', 10000))

Đối tượng socket ở client cũng sử dụng IP v4 và giao thức TCP. Phương thức connect() sẽ chỉ định cho python biết đây là một ứng dụng client và tạo kết nối đến server.

message = "Hello from client"
client.sendall(message.encode('ascii'))

Sau khi đã kết nối đến server, chúng ta gửi tin nhắn lên bằng phương thức sendall(), dữ liệu truyền đi chỉ là các bit mà trong Python 3 thì mặc định chuỗi luôn luôn là Unicode nên chúng ta phải mã hóa chuỗi này sang ASCII bằng phương thức encode() trước (để giải mã thì chúng ta dùng phương thức decode('ascii')).

finally:
    print ("Closing socket")
    client.close()

Cũng tương tự như server, khi đã kết thúc công việc chúng ta phải ngắt kết nối socket nếu không sẽ lãng phí tài nguyên. Mặc định thì khi kết thúc một chương trình python thì bộ thu gom rác của python đã tự động ngắt kết nối socket rồi nhưng chúng ta nên tự ngắt thì tốt hơn.

C:\User\Python>python server.py
Starting server on port 10000
Connecting from ('192.168.0.103', 56419)
Receive from client: b'Hello from client'
Response to client
Receive from client: b''
No data received
C:\User\Python\python client.py
Response from server: b'Hello from client'
Closing socket
3 2 votes
Article Rating
Subscribe
Thông báo cho tôi qua email khi
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Inline Feedbacks
View all comments
mkcuong
mkcuong
6 năm trước

Phần bạn viết ở server
“””
while True:
conn, client = server.accept()
try:
print (“Connection from”, client)

while True:
data = conn.recv(1024)
print (“Receive from client:”, data)
if data:
print (“Response to client”)
conn.sendall(data)
else:
print (“No data received”)
break
finally:
conn.close()
“””
ở phần while thứ 2 phải lùi đầu dòng chứ