1.网络的概念
网络是指将多个具有独立功能的计算机系统、设备或节点,通过通信线路和通信设备相互连接起来,以实现信息传输、资源共享和协同工作等功能的系统
2.ip地址的介绍
3.端口和端口号
3.socket介绍
4. TCP介绍,encode,decode
Tcp特点:
![]()
他们之间的关系可以类比为:网络就是社会关系,大家都可以在网络中进行数据传输,但比如说你要和一个人联系,首先你要找到他住的小区,这个小区就是ip地址,光有ip地址还不行,你要找到这个人住的家并且打开门进去说话,这个门就是端口这个门牌号就是端口号,但这就行了吗?你得有路呀,这个路就是scoket,有路就行了吗,你要有交通工具,这个交通工具的一种就是TCP。这样你就可以去联系一个人了哈哈哈。
4.TCP客户端程序开发流程
import socket
# 创建 TCP 套接字
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 服务器的 IP 地址和端口号
server_address = ('127.0.0.1', 8888)
# 连接服务器
client_socket.connect(server_address)
# 要发送的数据
message = "Hello, Server!"
# 编码并发送数据
client_socket.sendall(message.encode('utf-8'))
# 接收服务器返回的数据
data = client_socket.recv(1024)
# 解码数据
received_message = data.decode('utf-8')
print(f"Received from server: {received_message}")
# 关闭套接字
client_socket.close()
总而言之:
5.TCP服务端程序开发流程
import socket
# 创建 TCP 套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 服务器的 IP 地址和端口号
server_address = ('127.0.0.1', 8888)
# 绑定地址和端口
server_socket.bind(server_address)
# 开始监听,允许的最大连接队列长度为 5
server_socket.listen(5)
print("Server is listening on port 8888...")
try:
# 接受客户端连接
client_socket, client_address = server_socket.accept()
print(f"Accepted connection from {client_address}")
try:
# 接收客户端发送的数据
data = client_socket.recv(1024)
# 解码数据
received_message = data.decode('utf-8')
print(f"Received from client: {received_message}")
# 要发送的响应数据
response = "Hello, Client! Your message has been received."
# 编码并发送数据
client_socket.sendall(response.encode('utf-8'))
finally:
# 关闭客户端套接字
client_socket.close()
except KeyboardInterrupt:
print("Server is shutting down...")
finally:
# 关闭监听套接字
server_socket.close()
原理:
6.完整的服务端开发:很明显以上服务器只能一次服务于一个客户端,并且服务端会关闭,接下来是改进方法,首先先让它一直启动着循坏接受请求。 使用While True即可
import socket
if __name__ == '__main__':
# 1.创建服务端套接字对象
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置端口复用
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 2. 绑定IP地址和端口号
tcp_server_socket.bind(("", 8888))
# 3.设置监听 128:代表服务端等待排队连接的最大数量
tcp_server_socket.listen(128)
while True:
# 4. 等待接受客户端的连接请求 accept阻塞等待 返回一个用以和客户端通socket,客户端的地址
conn_socket, ip_port = tcp_server_socket.accept()
print("客户端地址:", ip_port)
try:
# 5. 接收数据
recv_data = conn_socket.recv(1024)
if recv_data:
print("接收到的数据:", recv_data.decode())
# 6.发送数据
conn_socket.send("客户端你的数据我收到了".encode())
else:
print(f"客户端 {ip_port} 断开连接")
except Exception as e:
print(f"与 {ip_port} 通信出错: {e}")
finally:
# 关闭与当前客户端的连接套接字
conn_socket.close()
# 关闭监听套接字(正常情况下程序不会执行到这一步,因为在while True循环中)
tcp_server_socket.close()
这样的话就可以循环接受客户端的连接,但是很明显它们得排队,我们要达到同时的效果,可以采用线程这个方法:
import socket
import threading
# 处理客户端请求的函数
def handle_client(conn_socket, client_address):
try:
# 接收客户端发送的数据
recv_data = conn_socket.recv(1024)
if recv_data:
try:
# 尝试将接收到的字节数据解码为字符串
message = recv_data.decode()
print(f"接收到来自 {client_address} 的数据:{message}")
# 向客户端发送响应消息
conn_socket.send("客户端你的数据我收到了".encode())
except UnicodeDecodeError:
print(f"来自 {client_address} 的数据解码失败,可能不是有效的文本数据。")
else:
print(f"客户端 {client_address} 主动关闭了连接。")
except ConnectionResetError:
print(f"客户端 {client_address} 重置了连接。")
except OSError as os_err:
print(f"与客户端 {client_address} 通信时发生 OS 错误: {os_err}")
except Exception as e:
print(f"处理客户端 {client_address} 请求时发生未知错误: {e}")
finally:
# 无论是否发生异常,最后都关闭与客户端的连接
conn_socket.close()
if __name__ == "__main__":
# 创建 TCP 套接字对象,使用 IPv4 地址族和 TCP 协议
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置套接字选项,允许地址重用,便于程序快速重启
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定服务器要监听的 IP 地址和端口号,这里使用空字符串表示监听所有可用的网络接口
server_address = ('', 8888)
tcp_server_socket.bind(server_address)
# 开始监听客户端连接请求,允许的最大连接队列长度为 128
tcp_server_socket.listen(128)
print(f"服务器正在监听 {server_address[0]}:{server_address[1]}...")
try:
while True:
# 接受客户端的连接请求,返回用于与客户端通信的新套接字和客户端地址
conn_socket, client_address = tcp_server_socket.accept()
print(f"客户端 {client_address} 已连接。")
# 创建一个新的线程来处理该客户端的请求
client_thread = threading.Thread(target=handle_client, args=(conn_socket, client_address))
# 设置线程为守护线程,当主线程退出时,守护线程会自动退出
client_thread.daemon = True
# 启动线程
client_thread.start()
except KeyboardInterrupt:
print("服务器接收到手动中断信号,正在关闭...")
finally:
# 关闭服务器套接字
tcp_server_socket.close()