00:00:00
Socket编程
1 python实现
1.1 TCP协议
1、服务器代码
python
# === TCP 服务端程序 ===
# 导入socket 库
from socket import *
import threading
# 主机地址为0.0.0.0, 表示绑定本机所有网络接口ip地址
# 主机地址127.0.0.1表示主机环回地址
# 等待客户端来连接
IP = '127.0.0.1'
# IP = '10.26.2.3'
# 端口号
PORT = 50000
# 定义一次从socket缓冲区最多读入512个字节数据
BUFFER = 512
# 实例化一个socket对象
# 参数 AF_INET表示该socket网络层使用IP协议
# 参数SOCK_STREAM 表示socket传输层使用tcp协议
server_socket = socket(AF_INET, SOCK_STREAM)
# socket绑定地址和端口
server_socket.bind((IP, PORT))
# 使用socket处于监听状态, 等待客户端的连接请求
# 参数5表示,最多接收多少个等待连接的客户端
server_socket.listen(5)
print(f"{IP}服务端启动成功, 在{PORT}端口等待客户端连接...")
# 定义处理客户端连接的函数
def handle_client(client_socket, addr):
print(f'接收一个客户端连接: {addr}')
try:
while True:
# 尝试读取对方发送的消息
data = client_socket.recv(BUFFER)
if not data:
# 如果返回空bytes,表示对方关闭了连接
break
# 读取的字节数据解码为字符串
info = data.decode()
print(f'收到客户端{addr}发来的信息: {info}')
# 发送响应,编码为bytes
client_socket.send(f'服务端接收到了信息 {info}'.encode())
finally:
# 关闭客户端连接
client_socket.close()
print(f'断开客户端连接: {addr}')
try:
# 主循环,接受客户端连接
while True:
client_socket, addr = server_socket.accept()
# 为每个客户端连接创建一个新线程
client_thread = threading.Thread(target=handle_client, args=(client_socket, addr))
client_thread.start()
except KeyboardInterrupt:
# 当用户按下Ctrl+C时,退出程序
print("服务器正在关闭...")
finally:
server_socket.close()
print("套接字已关闭。")
# listenSocket.close()2、客户机代码
python
# === TCP客户端程序 ===
from socket import *
# IP = '127.0.0.1'
IP = '10.26.2.3'
SERVER_PORT = 50000
BUFFER = 512
# 实例化一个socket对象,指明协议
dataSocket = socket(AF_INET, SOCK_STREAM)
# 连接服务端socket
dataSocket.connect((IP, SERVER_PORT))
print(f"已经和服务器{IP}:{SERVER_PORT}建立TCP连接")
while True:
# 从终端读入用户输入的字符串
toSend = input('>>')
if toSend == 'exit':
print(f"和服务器{IP}:{SERVER_PORT}断开TCP连接")
break
# 发送消息,也要编码为bytes
dataSocket.send(toSend.encode())
# 等待接收服务端的消息
recved = dataSocket.recv(BUFFER)
# 如果返回空bytes, 表示对方关闭了连接
if not recved:
break
# 打印读取的信息
print(recved.decode())
dataSocket.close()1.2 UDP协议
1、服务器代码
python
# === UDP 服务端程序 ===
# 导入socket 库
from socket import *
# 主机地址为0.0.0.0, 表示绑定本机所有网络接口ip地址
# 主机地址127.0.0.1表示主机环回地址
# IP = '127.0.0.1'
IP = '10.26.2.3'
# 端口号
PORT = 50000
# 定义一次从socket缓冲区最多读入512个字节数据
BUFFER = 512
# 实例化一个socket对象
# 参数 AF_INET表示该socket网络层使用IP协议
# 参数SOCK_DGRAM 表示socket传输层使用udp协议
udpSocket = socket(AF_INET, SOCK_DGRAM)
# socket绑定地址和端口
udpSocket.bind((IP, PORT))
print(f"{IP}服务端启动成功, 在{PORT}端口等待客户端连接...")
try:
while True:
# UDP不需要accept连接,直接从缓冲区读取数据报
data, addr = udpSocket.recvfrom(BUFFER)
# 读取的字节数据是bytes类型, 需要解码为字符串
info = data.decode()
print(f'收到来自 {addr} 的信息: {info}')
# 发送的数据类型必须是bytes, 所以要编码
response = f'服务端接收到了信息 {info}'.encode()
udpSocket.sendto(response, addr) # 使用sendto方法发送数据报,需要指定目标地址
except KeyboardInterrupt:
# 当用户按下Ctrl+C时,退出程序
print("服务器正在关闭...")
finally:
udpSocket.close()
print("套接字已关闭。")
# UDP服务器通常不需要显式关闭socket,除非要立即停止服务
# 但为了代码整洁,可以在必要时关闭socket
# udpSocket.close()2、客户机代码
python
# === UDP客户端程序 ===
from socket import *
# IP = '127.0.0.1'
IP = '10.26.2.3'
SERVER_PORT = 50000
BUFFER = 512
# 实例化一个socket对象,指明协议为UDP
udpSocket = socket(AF_INET, SOCK_DGRAM)
# UDP客户端不需要显式连接服务端,因为它发送的是数据报
# 数据报自带目标地址和端口信息
while True:
# 从终端读入用户输入的字符串
toSend = input('>> ')
if toSend.lower() == 'exit': # 允许用户输入'exit'或'EXIT'等不区分大小写的退出指令
print(f"和服务器{IP}:{SERVER_PORT}断开连接")
break
# 发送消息,也要编码为bytes
udpSocket.sendto(toSend.encode(), (IP, SERVER_PORT))
# 等待接收服务端的消息
# UDP是无连接的,recvfrom会阻塞直到接收到数据报
data, server = udpSocket.recvfrom(BUFFER)
# 打印读取的信息
print(data.decode())
# UDP客户端通常不需要显式关闭socket,但为了代码整洁,可以在退出前关闭它
udpSocket.close()WARNING
1、服务器和客户机的IP地址和端口需要对应
2、运行的时候需要先运行服务器socket代码,再运行客户机socket代码
