Saturday, November 23, 2024

[Python] Tập viết ứng dụng sử dụng socket

-

1. Ứng dụng phân giải tên miền.

Ứng dụng đầu tiên là một ứng dụng giải quyết tên miền sử dụng giao thức UDP. Giao thức UDP (User Datagram Protocol) là một giao thức truyền tải dữ liệu không tin cậy và không đảm bảo thứ tự của các gói tin. Trong ứng dụng này, chúng ta sử dụng UDP để gửi yêu cầu giải quyết tên miền và nhận phản hồi từ máy chủ DNS.

import socket

def domain_resolved_application()
    # Define the address and port to use
    UDP_IP = "8.8.8.8"  # Google's public DNS server
    UDP_PORT = 53  # DNS uses port 53

    # Create a UDP socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # Set a timeout in case the server does not respond
    sock.settimeout(5)

    # Define the domain to resolve
    domain = "wiki.hoanghd.com"

    # Construct the DNS query message
    query = bytearray()
    query += b"\x00\x00"  # 2-byte ID field
    query += b"\x01\x00"  # 2-byte flags field
    query += b"\x00\x01"  # 2-byte QDCOUNT field (1 question)
    query += b"\x00\x00"  # 2-byte ANCOUNT field (0 answers)
    query += b"\x00\x00"  # 2-byte NSCOUNT field (0 name server records)
    query += b"\x00\x00"  # 2-byte ARCOUNT field (0 additional records)
    for label in domain.split("."):
        query += bytes([len(label)])
        query += label.encode("ascii")
    query += b"\x00"  # Terminating null byte
    query += b"\x00\x01"  # 2-byte QTYPE field (A record)
    query += b"\x00\x01"  # 2-byte QCLASS field (IN class)

    # Send the DNS query to the server and receive the response
    sock.sendto(query, (UDP_IP, UDP_PORT))
    response, server_address = sock.recvfrom(1024)

    # Extract the IP address from the DNS response message
    ip_address = socket.inet_ntoa(response[-4:])

    print(f"The IP address of {domain} is {ip_address}")

Đầu tiên, chúng ta định nghĩa địa chỉ IP của máy chủ DNS mà chúng ta muốn sử dụng để giải quyết tên miền (trong ví dụ này, địa chỉ IP của máy chủ DNS của Google). Sau đó, chúng ta tạo một socket UDP bằng cách sử dụng socket.socket() và chuyền vào tham số socket.AF_INET để chỉ định rằng chúng ta sẽ sử dụng địa chỉ IPv4, và socket.SOCK_DGRAM để chỉ định rằng chúng ta sẽ sử dụng giao thức UDP.

Tiếp theo, chúng ta tạo một yêu cầu giải quyết tên miền bằng cách sử dụng định dạng được đặc tả trong RFC 1035. Thông điệp yêu cầu này bao gồm tên miền mà chúng ta muốn giải quyết, loại thông tin mà chúng ta muốn truy vấn (ví dụ: địa chỉ IPv4 hay địa chỉ IPv6), và mã truy vấn được tạo ngẫu nhiên.

Sau khi thông điệp yêu cầu đã được tạo, chúng ta gửi thông điệp này đến máy chủ DNS bằng cách sử dụng phương thức sendto() của socket. Chúng ta đợi phản hồi từ máy chủ DNS bằng cách sử dụng phương thức recvfrom() của socket, và nhận phản hồi vào một tuple chứa dữ liệu nhận được và địa chỉ nguồn.

Tiếp theo, chúng ta trích xuất địa chỉ IP từ phản hồi và hiển thị nó trên màn hình.

The IP address of wiki.hoanghd.com is 113.161.201.128

2. Tạo socket bằng Python.

Ứng dụng thứ hai là một ứng dụng sử dụng giao thức TCP để xử lý sâu các kết nối giữa server và client.

import socket

def socket_deep_application():
    # Define the address and port to use
    TCP_IP = "192.168.100.99"
    TCP_PORT = 9090

    # Create a TCP socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # Bind the socket to the address and port
    sock.bind((TCP_IP, TCP_PORT))

    # Listen for incoming connections
    sock.listen(1)

    print(f"Listening on {TCP_IP}:{TCP_PORT}")

    while True:
        # Accept an incoming connection
        conn, addr = sock.accept()

        print(f"Connection from {addr[0]}:{addr[1]}")

        # Receive data from the client
        data = conn.recv(1024)

        if not data:
            # No data received, close the connection
            conn.close()
            continue

        # Process the data
        processed_data = data.upper()

        # Send the processed data back to the client
        conn.send(processed_data)

        # Close the connection
        conn.close()

socket_deep_application()

Trong ứng dụng này, chúng ta sử dụng socket của Python để tạo một server và lắng nghe các kết nối từ client. Đầu tiên, chúng ta khởi tạo một socket TCP sử dụng phương thức socket() của Python, với các tham số AF_INETSOCK_STREAM để chỉ định giao thức TCP.

Sau đó, chúng ta gán một địa chỉ IP và một cổng cho server bằng cách sử dụng phương thức bind(). Địa chỉ IP này được chọn để lắng nghe các kết nối từ tất cả các địa chỉ IP trên máy chủ, và cổng được chọn để lắng nghe các kết nối tới cổng này.

Tiếp theo, chúng ta sử dụng phương thức listen() để đặt server vào trạng thái lắng nghe các kết nối tới. Server sẽ tiếp tục lắng nghe và chấp nhận các kết nối mới từ client bằng cách sử dụng phương thức accept(). Khi một kết nối mới được chấp nhận, chúng ta nhận được một đối tượng socket mới để truyền tải dữ liệu giữa server và client.

Sau khi chấp nhận kết nối, chúng ta sử dụng một vòng lặp vô hạn để nhận và xử lý dữ liệu từ client. Đầu tiên, chúng ta sử dụng phương thức recv() để nhận dữ liệu từ client. Chúng ta kiểm tra nếu dữ liệu là rỗng (nghĩa là client đã đóng kết nối), thì chúng ta thoát khỏi vòng lặp và đóng socket. Nếu dữ liệu không rỗng, chúng ta xử lý dữ liệu này và gửi phản hồi trở lại client bằng cách sử dụng phương thức send().

Trong ví dụ này, chúng ta đơn giản là xử lý dữ liệu đầu vào của client và đảo ngược nó trước khi gửi phản hồi trở lại client. Tuy nhiên, các ứng dụng sử dụng giao thức TCP có thể có nhiều mục đích khác nhau, bao gồm truyền tải và xử lý các file, chia sẻ dữ liệu giữa các client khác nhau, và nhiều hơn nữa.

Kết quả của chương trình.

Listening on 192.168.100.99:9090

Dùng một máy tính khác telnet tới, ta có kết quả.

shell> telnet 192.168.100.99 9090
Trying 192.168.100.99...
Connected to 192.168.100.99.
Escape character is '^]'.
^CConnection closed by foreign host.
Previous article
Next article

LEAVE A REPLY

Please enter your comment!
Please enter your name here

4,956FansLike
256FollowersFollow
223SubscribersSubscribe
spot_img

Related Stories