Lập trình mạng Python: giao thức TCP (phần 5)

Một client và server TCP đơn giản

Hãy nhìn vào code bên dưới. Như tôi đã làm trong học phần trước, tôi đã kết hợp hai chương trình riêng rẽ vào một phần
code đơn – vì chúng chia sẻ một đoạn code chung và để rằng code máy khách và máy chủ có thể được đọc cùng với nhau dễ dàng hơn.

#!/usr/bin/env python3
# Foundations of Python Network Programming, Third Edition
# https://github.com/brandon-rhodes/fopnp/blob/m/py3/chapter03/tcp_sixteen.py
# Simple TCP client and server that send and receive 16 octets
import argparse, socket
def recvall(sock, length):
data = b”
while len(data) < length:
more = sock.recv(length – len(data))
if not more:
raise EOFError(‘was expecting %d bytes but only received’
‘ %d bytes before the socket closed’
% (length, len(data)))
data += more
return data
def server(interface, port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((interface, port))
sock.listen(1)
print(‘Listening at’, sock.getsockname())
while True:
sc, sockname = sock.accept()
print(‘We have accepted a connection from’, sockname)
print(‘ Socket name:’, sc.getsockname())
print(‘ Socket peer:’, sc.getpeername())
message = recvall(sc, 16)
print(‘ Incoming sixteen-octet message:’, repr(message))
sc.sendall(b’Farewell, client’)
sc.close()
print(‘ Reply sent, socket closed’)
def client(host, port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, port))
print(‘Client has been assigned socket name’, sock.getsockname())
sock.sendall(b’Hi there, server’)
reply = recvall(sock, 16)
print(‘The server said’, repr(reply))
sock.close()
if __name__ == ‘__main__’:
choices = {‘client’: client, ‘server’: server}
parser = argparse.ArgumentParser(description=’Send and receive over TCP’)
parser.add_argument(‘role’, choices=choices, help=’which role to play’)
parser.add_argument(‘host’, help=’interface the server listens at;’
‘ host the client sends to’)
parser.add_argument(‘-p’, metavar=’PORT’, type=int, default=1060,
help=’TCP port (default 1060)’)
args = parser.parse_args()
function = choices[args.role]
function(args.host, args.p)

Trong học phần trước, tôi đã tiếp cận chủ đề bind() hoàn toàn cẩn thận, vì địa chỉ bạn cung cấp như đối số của nó thực
hiện một lựa chọn quan trọng: nó quyết định liệu các hosts ở xa có có thể cố gắng kết nối với máy chủ của chúng ta hay
liệu máy chủ của bạn có được bảo vệ lại các kết nối bên ngoài và có thể được liên hệ chỉ bởi các chương trình khác chạy
trên cùng máy. Tùy theo, học phần trước bắt đầu với phần code chương trình an toàn cái gắn bản thân chúng chỉ với giao
diện loopback và sau đó tiến tới phần code chương trình nguy hiểm hơn cái chấp nhận các kết nối từ các hosts khác trên
mạng.
Nhưng ở đây tôi đã kết hợp cả hai khả năng vào một phần code đơn. Với đối số host cái bạn cung cấp từ command line,
hoặc là bạn có thể thực hiện lựa chọn an toàn hơn gắn với 127.0.0.1 hoặc bạn có thể chọn gắn với một trong những địa chỉ
IP bên ngoài của máy của bạn thay vào – hoặc bạn có thể cung cấp một chuỗi kí tự trắng để chỉ ra rằng bạn sẽ chấp nhận
các kết nối tại bất cứ các địa chỉ IP của máy của bạn nào. Lại một lần nữa, xem lại học phần trước nếu bạn muốn nhớ lại
tất cả các quy tắc, cái áp dụng như nhau cho các kết nối và sockets TCP và UDP.

Chia sẻ