Trang chủHướng dẫnLập trình Socket trong Python: Hướng dẫn và ví dụ Server và Client

Lập trình Socket trong Python: Hướng dẫn và ví dụ Server và Client

CyStack blog 10 phút để đọc
CyStack blog18/07/2025
Locker Avatar

Chris Pham

Technical Writer

Locker logo social
Reading Time: 10 minutes

Mô-đun socket của Python là một công cụ mạnh mẽ để xây dựng các ứng dụng mạng. Trong hướng dẫn này, bạn sẽ được làm quen với những kiến thức cơ bản về lập trình socket trong Python, bao gồm cách tạo kiến trúc client-server đơn giản, xử lý nhiều client cùng lúc bằng threading, và phân biệt giữa socket TCPUDP.

Lập trình Socket trong Python

Bạn cũng sẽ học cách thiết lập kết nối, gửi và nhận dữ liệu, từ đó xây dựng các ứng dụng mạng ổn định bằng Python.

Lập trình Socket trong Python là gì?

Để hiểu về lập trình socket trong Python, trước tiên chúng ta cần làm quen với ba khái niệm quan trọng: Socket Server, Socket Client, và Socket.

Vậy server là gì? Server là một chương trình phần mềm luôn “lắng nghe” các yêu cầu từ phía client và xử lý hoặc phản hồi các yêu cầu đó một cách phù hợp.

Ngược lại, client là bên gửi yêu cầu. Một chương trình client sẽ gửi yêu cầu truy cập tài nguyên nào đó đến server, và server sẽ phản hồi lại yêu cầu đó.

Socket là điểm cuối (endpoint) của một kênh giao tiếp hai chiều giữa server và client. Socket có thể dùng để giao tiếp giữa các tiến trình trong cùng một chương trình, giữa các tiến trình trên cùng một máy, hoặc giữa các tiến trình trên các máy khác nhau. Để giao tiếp với một chương trình từ xa, chúng ta cần kết nối thông qua cổng socket (socket port).

Mục tiêu chính của hướng dẫn này là giúp bạn hiểu cách socket server và client giao tiếp với nhau. Ngoài ra, bạn cũng sẽ học cách viết một chương trình socket server bằng Python.

Ví dụ về Socket trong Python

Như đã đề cập trước đó, một socket client sẽ gửi yêu cầu tài nguyên đến socket server, và server sẽ phản hồi lại yêu cầu đó. Vì vậy, chúng ta sẽ xây dựng mô hình cả phía server lẫn client để hai bên có thể giao tiếp với nhau. Các bước thực hiện như sau:

  1. Chương trình socket server của Python sẽ chạy trước và chờ các yêu cầu kết nối.
  2. Chương trình socket client sẽ chủ động khởi tạo phiên giao tiếp đầu tiên.
  3. Sau đó, server sẽ phản hồi lại các yêu cầu từ phía client.
  4. Chương trình client sẽ kết thúc nếu người dùng nhập vào thông điệp “bye”. Server cũng có thể kết thúc theo sau, hoặc tiếp tục chạy vô thời hạn tùy theo cách bạn thiết kế . Ví dụ, có thể cho server tự thoát nếu nhận được một lệnh cụ thể từ phía client.

Python Socket Server

Chúng ta sẽ lưu chương trình socket server bằng Python với tên file socket_server.py. Để sử dụng kết nối socket trong Python, bạn cần import mô-đun socket. Tiếp theo, chúng ta cần thực hiện tuần tự một số bước để thiết lập kết nối giữa server và client.

Địa chỉ host có thể lấy bằng cách sử dụng hàm socket.gethostname().

Lưu ý nên sử dụng cổng (port) lớn hơn 1024, vì các port nhỏ hơn thường được dành riêng cho các giao thức mạng tiêu chuẩn (như HTTP, FTP…).

Hãy xem đoạn code ví dụ bên dưới. Các chú thích trong code sẽ giúp bạn hiểu rõ cách hoạt động của server socket.

import socket

def server_program():
    # get the hostname
    host = socket.gethostname()
    port = 5000  # initiate port no above 1024

    server_socket = socket.socket()  # get instance
    # look closely. The bind() function takes tuple as argument
    server_socket.bind((host, port))  # bind host address and port together

    # configure how many client the server can listen simultaneously
    server_socket.listen(2)
    conn, address = server_socket.accept()  # accept new connection
    print("Connection from: " + str(address))
    while True:
        # receive data stream. it won't accept data packet greater than 1024 bytes
        data = conn.recv(1024).decode()
        if not data:
            # if data is not received break
            break
        print("from connected user: " + str(data))
        data = input(' -> ')
        conn.send(data.encode())  # send data to the client

    conn.close()  # close the connection

if __name__ == '__main__':
    server_program()

Vậy là socket server trong Python của chúng ta đang chạy trên port 5000 và sẽ chờ các yêu cầu kết nối từ phía client. Nếu bạn muốn server không tự thoát khi client ngắt kết nối, chỉ cần xóa điều kiện if và lệnh break trong đoạn code. Vòng lặp while trong Python được sử dụng để duy trì server hoạt động liên tục, luôn sẵn sàng chờ kết nối từ client.

Python Socket Client

Chúng ta sẽ lưu chương trình socket client bằng Python với tên file socket_client.py. Chương trình này có cấu trúc tương tự như server, ngoại trừ phần binding.

Điểm khác biệt chính giữa chương trình server và client là: ở phía server, chúng ta cần gắn kết (bind) địa chỉ host và port lại với nhau. Ở phía client thì không cần thực hiện bước này.

Hãy xem đoạn code ví dụ về socket client bằng Python bên dưới, phần chú thích trong code sẽ giúp bạn hiểu rõ cách hoạt động.

import socket

def client_program():
    host = socket.gethostname()  # as both code is running on same pc
    port = 5000  # socket server port number

    client_socket = socket.socket()  # instantiate
    client_socket.connect((host, port))  # connect to the server

    message = input(" -> ")  # take input

    while message.lower().strip() != 'bye':
        client_socket.send(message.encode())  # send message
        data = client_socket.recv(1024).decode()  # receive response

        print('Received from server: ' + data)  # show in terminal

        message = input(" -> ")  # again take input

    client_socket.close()  # close the connection

if __name__ == '__main__':
    client_program()

Kết quả khi chạy chương trình Socket trong Python

Để xem kết quả hoạt động, bạn hãy chạy chương trình socket server trước, sau đó mới chạy chương trình socket client.

Tiếp theo, hãy thử gửi một đoạn nội dung từ phía client, rồi phản hồi lại từ phía server.

Cuối cùng, gõ “bye” từ phía client để kết thúc cả hai chương trình.

Đoạn video ngắn dưới đây sẽ minh họa cách mà ví dụ socket server và client hoạt động trong lần chạy thử của tôi.

Lập trình Socket trong Python: Hướng dẫn và ví dụ Server và Client

python3.6 socket_server.py 
Connection from: ('127.0.0.1', 57822)
from connected user: Hi
 -> Hello
from connected user: How are you?
 -> Good
from connected user: Awesome!
 -> Ok then, bye!
python3.6 socket_client.py 
 -> Hi
Received from server: Hello
 -> How are you?
Received from server: Good
 -> Awesome!
Received from server: Ok then, bye!
 -> Bye

Lưu ý rằng socket server đang chạy trên port 5000, nhưng phía client cũng cần một socket port để kết nối với server. Port này sẽ được gán ngẫu nhiên khi client gọi hàm connect(). Trong ví dụ này, client được gán port 57822.

Xử lý nhiều Client bằng cách sử dụng Thread

Một server có thể sử dụng thread để xử lý nhiều client cùng lúc. Cách tiếp cận này cho phép server xử lý đồng thời nhiều kết nối từ client, từ đó cải thiện khả năng phản hồi và giúp server xử lý hiệu quả khi có số lượng lớn client kết nối cùng lúc.

Dưới đây là ví dụ minh họa cách thực hiện điều này trong Python bằng cách sử dụng mô-đun threading:

import threading

def handle_client(client_socket):
    # This function is responsible for handling each client connection.
    # It sends a greeting message to the client and then closes the connection.
    client_socket.send(b"Hello, Client!")
    client_socket.close()

while True:
    # The server continuously listens for incoming client connections.
    client_socket, addr = server_socket.accept()
    # When a new client connects, a new thread is created to handle the client.
    client_thread = threading.Thread(target=handle_client, args=(client_socket,))
    client_thread.start()

Socket Chặn (Blocking) và Không Chặn (Non-Blocking)

Trong lập trình socket, socket có thể hoạt động ở hai chế độ: blocking hoặc non-blocking . Chế độ này quyết định cách socket xử lý khi đang chờ nhận hoặc gửi dữ liệu.

Socket Blocking : Ở chế độ blocking, các thao tác như recv()accept() sẽ tạm dừng chương trình cho đến khi có dữ liệu hoặc kết nối được chấp nhận. Cách làm này tuy đơn giản để triển khai, nhưng lại có thể gây ra vấn đề hiệu năng và khiến ứng dụng kém phản hồi, nhất là khi phải xử lý nhiều tác vụ cùng lúc.

Socket Non-Blocking: Ngược lại, ở chế độ non-blocking, nếu chưa có dữ liệu thì các hàm như recv() sẽ trả về ngay lập tức, thay vì giữ chương trình lại. Cách tiếp cận này giúp tránh hiện tượng treo ứng dụng do các thao tác mạng bị chặn. Socket non-blocking đặc biệt hữu ích trong những ứng dụng cần xử lý nhiều kết nối đồng thời, chẳng hạn như web server hoặc chat server. Tuy nhiên, kiểu lập trình này phức tạp hơn, vì bạn cần quản lý luồng dữ liệu bất đồng bộ một cách rõ ràng và hiệu quả.

So sánh TCP và UDP Sockets

Tính năng TCP (Transmission Control Protocol) UDP (User Datagram Protocol)
Kết nối Có kết nối (Connection-oriented) Không kết nối (Connectionless)
Độ tin cậy Đáng tin cậy, đảm bảo toàn vẹn dữ liệu Không đáng tin cậy, không có đảm bảo
Trường hợp sử dụng Trình duyệt web, truyền tệp Phát video trực tuyến, trò chơi

TCP (Transmission Control Protocol)UDP (User Datagram Protocol) là hai giao thức cơ bản trong bộ giao thức Internet, cho phép truyền thông qua mạng Internet. Sự khác biệt chính giữa chúng nằm ở cách thiết lập kết nốimức độ đảm bảo tính toàn vẹn của dữ liệu.

TCP là một giao thức hướng kết nối (connection-oriented), một kết nối ổn định phải được thiết lập giữa bên gửi và bên nhận trước khi quá trình truyền dữ liệu có thể bắt đầu. Cơ chế này đảm bảo các gói tin (data packets) được chuyển đến đúng thứ tự và sẽ được truyền lại nếu bị mất hoặc lỗi, qua đó duy trì tính toàn vẹn của dữ liệu.

TCP phù hợp với các ứng dụng cần đảm bảo dữ liệu được truyền chính xác, chẳng hạn như trình duyệt web hoặc truyền file.

Ngược lại, UDP là một giao thức phi kết nối (connectionless), có nghĩa là không có một kết nối đầu-cuối chuyên biệt. Dữ liệu được gửi đi dưới dạng một chuỗi các gói tin (packets), và bên nhận không cần gửi lại tín hiệu xác nhận. Điều này giúp UDP nhanh hơn nhưng cũng kém tin cậy hơn so với TCP. Do đó, UDP thường được sử dụng cho các ứng dụng yêu cầu tốc độ truyền tải nhanh và có thể chấp nhận việc mất mát một phần dữ liệu, chẳng hạn như streaming video và game trực tuyến.

Các lỗi thường gặp và cách debug

  1. Lỗi Address Already in Use: Lỗi này xảy ra khi có một tiến trình khác đang sử dụng port mà ứng dụng của bạn cố gắng sử dụng. Để xử lý, bạn có thể chạy lệnh sau để xác định tiến trình nào đang chiếm dụng port:
netstat -an | grep <port_no>

Sau khi xác định được tiến trình, bạn có thể dừng tiến trình đó hoặc chọn một port khác cho ứng dụng của mình.

2. Lỗi Connection Refused: Lỗi này xảy ra khi client cố gắng kết nối đến một server không hoạt động, hoặc server không lắng nghe trên port đã chỉ định. Để khắc phục, hãy đảm bảo rằng server đang chạy và đang lắng nghe đúng port trước khi client khởi tạo kết nối. Dưới đây là một đoạn mã Python đơn giản để kiểm tra xem server có đang lắng nghe trên một port cụ thể hay không:

import socket

def check_port(host, port):
    try:
        with socket.create_connection((host, port), timeout=1):
            print(f"Port {port} is open on {host}")
    except socket.timeout:
        print(f"Port {port} is not open on {host}")

# Example usage
check_port('localhost', 5000)

3. Exception Handling: It's essential to handle exceptions properly to ensure your application can recover from errors gracefully. Here's an example of how to handle a connection error using a `try-except` block:

```python
try:
    client_socket.connect(('localhost', 12345))
except socket.error as e:
    print(f"Error connecting to the server: {e}")
    # Optionally, you can add additional error handling or logging here
except Exception as e:
    print(f"An unexpected error occurred: {e}")
    # Optionally, you can add additional error handling or logging here

Câu hỏi thường gặp (FAQs)

1. Làm thế nào để tạo một socket server trong Python?

Dưới đây là ví dụ cách tạo một socket server bằng Python:

import socket

def server_program():
    # get the hostname
    host = socket.gethostname()
    port = 5000  # initiate port no above 1024

    server_socket = socket.socket()  # get instance
    # look closely. The bind() function takes tuple as argument
    server_socket.bind((host, port))  # bind host address and port together

    # configure how many clients the server can listen to simultaneously
    server_socket.listen(2)
    conn, address = server_socket.accept()  # accept new connection
    print("Connection from: " + str(address))
    while True:
        # receive data stream. it won't accept data packets greater than 1024 bytes
        data = conn.recv(1024).decode()
        if not data:
            # if data is not received break
            break
        print("from connected user: " + str(data))
        data = input(' -> ')
        conn.send(data.encode())  # send data to the client

    conn.close()  # close the connection

if __name__ == '__main__':
    server_program()

2. Làm thế nào để tạo một socket client trong Python?

Tương tự, bạn có thể tạo một socket client như sau:

import socket

def client_program():
    host = socket.gethostname()  # as both code is running on same pc
    port = 5000  # socket server port number

    client_socket = socket.socket()  # instantiate
    try:
        client_socket.connect((host, port))  # connect to the server
    except ConnectionRefusedError:
        print("The connection to the server was refused")
        return

    message = input(" -> ")  # take in the user's message

    while message.lower().strip() != 'bye':
        client_socket.send(message.encode())  # send in the socket and in networking
        data = client_socket.recv(1024).decode()  # receive in the client
        print('Response from the server : ' + data)  # in the client console
        message = input(" -> ")

    client_socket.close()  # close the connection

if __name__ == '__main__':
    client_program()

3. Sự khác biệt giữa socket TCP và UDP là gì?

TCP cung cấp kết nối đáng tin cậy, trong khi UDP có tốc độ nhanh hơn nhưng không đảm bảo tính toàn vẹn của dữ liệu.

Tính năng TCP UDP
Kết nối Có hướng kết nối (Connection-oriented) Không kết nối (Connectionless)
Độ tin cậy Đảm bảo dữ liệu được gửi thành công Không đảm bảo dữ liệu được gửi
Thứ tự gói tin Đảm bảo đúng thứ tự Không đảm bảo thứ tự
Kiểm tra lỗi Kiểm tra và sửa lỗi Chỉ kiểm tra lỗi, không sửa
Tốc độ Chậm hơn do có kiểm tra lỗi Nhanh hơn vì không kiểm tra lỗi
Trường hợp sử dụng Truyền file, email, truy cập web Game online, truyền phát video, VoIP

4. Làm cách nào để xử lý nhiều client trong lập trình socket với Python?

Bạn có thể sử dụng mô-đun threading để xử lý nhiều client cùng lúc. Dưới đây là ví dụ minh họa cách bạn có thể chỉnh sửa mã phía server để quản lý nhiều kết nối đồng thời bằng cách sử dụng đa luồng:

import threading

def handle_client(conn, addr):
    print(f"New connection from {addr}")
    while True:
        try:
            message = conn.recv(1024).decode()
            if message:
                print(f"Message from {addr}: {message}")
                conn.send(message.encode())
        except Exception as e:
            print(f"Error with connection from {addr}: {e}")
            break
    conn.close()

def server_program():
    host = socket.gethostname()
    port = 5000

    server_socket = socket.socket()
    server_socket.bind((host, port))
    server_socket.listen()

    while True:
        conn, addr = server_socket.accept()
        thread = threading.Thread(target=handle_client, args=(conn, addr))
        thread.start()
        print(f"Active connections: {threading.activeCount() - 1}")

if __name__ == '__main__':
    server_program()

Kết luận

Trong hướng dẫn này, chúng ta đã tìm hiểu những kiến thức cơ bản về lập trình socket với Python, bao gồm:

  • Cách xây dựng kiến trúc client-server đơn giản
  • Cách xử lý nhiều client đồng thời bằng mô-đun threading
  • Sự khác biệt giữa socket TCP và UDP

Những tài liệu này sẽ giúp bạn nắm vững hơn về Python cũng như cách ứng dụng ngôn ngữ này trong lập trình mạng.

0 Bình luận

Đăng nhập để thảo luận

Chuyên mục Hướng dẫn

Tổng hợp các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.

Đăng ký nhận bản tin của chúng tôi

Hãy trở thành người nhận được các nội dung hữu ích của CyStack sớm nhất

Xem chính sách của chúng tôi Chính sách bảo mật.

Đăng ký nhận Newsletter

Nhận các nội dung hữu ích mới nhất