TCP通信
TCPClient:
import socket
# 1. 创建套接字
# AF_INET:底层网络使用IPv4
# SOCK_STREAM:表明是一个TCP套接字
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 创建TCP连接
serverIP = "localhost"
serverPort = 12000
clientSocket.connect((serverIP, serverPort))
# 3. 发送请求报文
requestMessage = str(input("Input lowercase sentence:"))
clientSocket.send(requestMessage.encode())
# 4. 接收响应报文
responseMessage = clientSocket.recv(1024)
# 5. 处理响应报文
print(responseMessage.decode())
# 6. 关闭套接字
clientSocket.close()
TCPServer:
import socket
# 1. 创建套接字
# AF_INET:底层网络使用IPv4
# SOCK_STREAM:表明是一个TCP套接字
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 将服务端地址和套接字绑定
serverIP = "localhost"
serverPort = 12000
serverSocket.bind((serverIP, serverPort))
# 3. 启动服务端以接受客户端连接,参数为请求连接的最大数量
serverSocket.listen(1)
print("The server is ready to receive")
while True:
    # 4. 监听客户端连接
    connectionSocket, addr = serverSocket.accept()
    # 5. 接收请求报文
    requestMessage = connectionSocket.recv(1024)
    # 6. 发送响应报文
    responseMessage = requestMessage.decode().upper()
    connectionSocket.send(responseMessage.encode())
    # 7. 关闭客户端套接字
    connectionSocket.close()
模拟B/S服务器:
import os
import socket
BASE_DIR = os.path.dirname(__file__)  # 当前文件所在的目录
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serverSocket.bind(('127.0.0.1', 8080))
serverSocket.listen(5)
while True:
    connectionSocket, addr = serverSocket.accept()
    requestMessage = connectionSocket.recv(1024).decode('utf-8')
    # 请求的资源url
    url = BASE_DIR + requestMessage.split(" ")[1]
    if os.path.isfile(url):  # 如果文件存在
        # 发送状态行
        connectionSocket.send(b"HTTP/1.1 200 OK\r\n")
        # 发送响应头
        connectionSocket.send(b"Content-Type:text/html\r\n")
        # 发送空行
        connectionSocket.send(b"\r\n")
        # 发送响应体
        with open(url, 'rb') as file:
            connectionSocket.send(file.read())
    else:  # 如果文件不存在
        connectionSocket.send(b"HTTP/1.1 404 Not Found\r\n")
    connectionSocket.close()
Python常用Web框架:Django、Flask、Tornado
UDP通信
UDPClient:
import socket
# 1. 创建套接字
# AF_INET:底层网络使用IPv4
# SOCK_DGRAM:表明是一个UDP套接字
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 2. 发送请求报文
requestMessage = str(input("Input lowercase sentence:"))
serverIP = "localhost"
serverPort = 12000
clientSocket.sendto(requestMessage.encode(), (serverIP, serverPort))
# 3. 接收响应报文
responseMessage, serverAddress = clientSocket.recvfrom(2048)
# 4. 处理响应报文
print(responseMessage.decode())
# 5. 关闭套接字
clientSocket.close()
UDPServer:
import socket
# 1. 创建套接字
# AF_INET:底层网络使用IPv4
# SOCK_DGRAM:表明是一个UDP套接字
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 2. 将服务端地址和套接字绑定
serverIP = "localhost"
serverPort = 12000
serverSocket.bind((serverIP, serverPort))
print("The server is ready to receive")
while True:
    # 3. 接收请求报文
    requestMessage, clientAddress = serverSocket.recvfrom(2048)
    # 4. 发送响应报文
    responseMessage = requestMessage.decode().upper()
    serverSocket.sendto(responseMessage.encode(), clientAddress)
TCP粘包问题
TCP粘包问题:请求结果没有接收完,在下次请求结果中会携带上次没收完的结果。
解决TCP粘包问题:每次都将结果接收干净
- 
服务端: import hashlib import json import socket import struct serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serverSocket.bind(("localhost", 12000)) serverSocket.listen(1) print("The server is ready to receive") while True: connectionSocket, addr = serverSocket.accept() while True: try: requestMessage = connectionSocket.recv(2048) print(requestMessage.decode("utf-8")) responseMessage = (requestMessage.decode().upper() * 3072).encode("utf-8") # 1. 自定义响应头 header = { "content-length": len(responseMessage), "md5": hashlib.md5(responseMessage).hexdigest() } header_json_bytes = json.dumps(header).encode("utf-8") # 2. 发送响应头长度 len_header_json_bytes = struct.pack('i', len(header_json_bytes)) connectionSocket.send(len_header_json_bytes) # 3. 发送响应头 connectionSocket.send(header_json_bytes) # 4. 发送响应内容 connectionSocket.send(responseMessage) except Exception: break connectionSocket.close()
- 
客户端: import hashlib import json import socket import struct clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) clientSocket.connect(("localhost", 12000)) while True: requestMessage = str(input("Input lowercase sentence:")) if requestMessage == "exit": clientSocket.close() break clientSocket.send(requestMessage.encode()) # 1. 接收响应头长度,i格式固定为4个字节 len_header_json_bytes = clientSocket.recv(4) len_header = struct.unpack('i', len_header_json_bytes)[0] # 2. 接收响应头,并解析出响应头 header_json_bytes = clientSocket.recv(len_header) header = json.loads(header_json_bytes.decode("utf-8")) content_length = header["content-length"] # 3. 接收响应内容 responseMessage = "".encode("utf-8") recv_length = 0 while recv_length < content_length: recv_content = clientSocket.recv(1024) print(recv_content.decode("utf-8"), end="") responseMessage += recv_content recv_length += len(recv_content) else: print(header["md5"] == hashlib.md5(responseMessage).hexdigest(), len(responseMessage.decode("utf-8")))
socketserver模块
TCP服务端:
import socketserver
# 自定义请求处理类:继承socketserver.BaseRequestHandler
class TCPRequestHandler(socketserver.BaseRequestHandler):
    # 处理请求的方法
    def handle(self):
        # 客户端地址
        print(self.client_address)
        # 接收请求报文
        requestMessage = self.request.recv(1024)
        # 发送响应报文
        self.request.send(requestMessage.upper())
        # 关闭连接
        self.request.close()
server_address = ("localhost", 12000)
requestHandlerClass = TCPRequestHandler
threadingTCPServer = socketserver.ThreadingTCPServer(server_address, requestHandlerClass)
# 一次处理一个请求,直到关闭为止
threadingTCPServer.serve_forever()
UDP服务端:
import socketserver
# 自定义请求处理类:继承socketserver.BaseRequestHandler
class UDPRequestHandler(socketserver.BaseRequestHandler):
    # 处理请求的方法
    def handle(self):
        # 客户端地址
        client_address = self.client_address
        # 请求报文
        requestMessage = self.request[0]
        serverSocket = self.request[1]
        # 发送响应报文
        serverSocket.sendto(requestMessage.upper(), client_address)
server_address = ("localhost", 12000)
requestHandlerClass = UDPRequestHandler
threadingUDPServer = socketserver.ThreadingUDPServer(server_address, requestHandlerClass)
# 一次处理一个请求,直到关闭为止
threadingUDPServer.serve_forever()