Python-05-网络编程

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粘包问题:每次都将结果接收干净

  1. 服务端:

    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()
    
  2. 客户端:

    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()
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容