引入
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
所以,我们无需深入理解tcp/udp协议,socket已经为我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵循tcp/udp标准的。
AF_UNIX
基于文件类型的套接字家族
在unix中,一切皆文件,基于文件的套接字调用的就是底层的文件系统来获取数据
两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信
AF_INET
基于网络类型的套接字家族
AF_INET是使用最广泛的一个,python支持很多种地址家族,但是由于我们只关心网络编程,故大多只使用AF_INET。
socket模块
基于网络类型的套接字,应用程序交流按照链接的有无,又分为基于tcp的套接字和基于udp的套接字
python中的socket模块帮我们封装了socket抽象层,并提供我们一些简单接口使用。
建立TCP连接
注意事项1:发送请求应该是由客户端向服务端主动发送,服务端不会主动向客户端发送
注意事项2:关闭连接服务器以及客户端都是可以主动关闭的,但是通常情况下应该由客户端去关闭,而不是服务端,除非客户端疯狂请求之类。
# 服务端
import socket
# 创建一个TCP socket # AF_INET代表ipv4家族 SOCK_STREAM代表TCP协议
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# IP地址和端口号, 端口号别给0-1024之间 IP地址如果是0.0.0.0 表主机的任意网卡都可以使用socket通信
server_address = ("127.0.0.1", 8080)
# 绑定地址和端口
server_socket.bind(server_address)
# 将socket设置为监听状态,并等待客户端链接,默认值为 socket.SOMAXCONN。
# socket.SOMAXCONN 是一个系统定义的常量,表示操作系统允许的最大连接数。
server_socket.listen()
print("链接已创建 等待客户端链接...")
try:
# 使用 accept() 方法接受客户端的连接,返回一个新的 Socket 对象和客户端地址。
client_socket, client_address = server_socket.accept()
print(f"客户端 [{client_address}] 已成功连接! ")
# 和客户端通信 这里要用客户端去回信 不然会报错 记得消息是二进制的
data = client_socket.recv(1024).decode()
print(f"来自客户端的消息:{data}")
client_socket.send("客户端 你好 ^_^".encode())
finally:
# 依次关闭客户端和服务端
client_socket.close()
server_socket.close()
# 客户端
import socket
# 创建socket # AF_INET代表ipv4家族 SOCK_STREAM代表TCP协议
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 服务器的地址和端口
server_address = ("127.0.0.1", 8080)
try:
# 链接服务器
client_socket.connect(server_address)
# 给服务器发送数据 注意要编码
message = "服务器 你好!"
client_socket.send(message.encode()) # 这里如果不指定编码格式 默认就是utf-8
# 接收服务器响应
response = client_socket.recv(1024) # 单位是字节
print(f"来自服务器的消息:{response.decode()}")
except socket.error as e:
print(f"发生了错误: {e}")
finally:
client_socket.close()
优化纯享版
因为使用了上下文管理器所以不需要手动关闭服务了
# 服务端
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(("127.0.0.1", 8080))
s.listen()
print("链接已创建 等待客户端链接...")
c, addr = s.accept()
with c:
data = c.recv(1024).decode()
print(f"来自客户端的消息:{data}")
c.send("客户端 你好 ^_^".encode())
# 客户端
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as c:
c.connect(("127.0.0.1", 8080))
message = "服务器 你好!"
c.send(message.encode())
response = c.recv(1024).decode()
print(f"来自服务器的消息:{response}")
如何循环发送消息
加一个循环不就好了...
# 服务端
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(("127.0.0.1", 8080))
s.listen()
print("链接已创建 等待客户端链接...")
c, addr = s.accept()
with c:
while (data := c.recv(1024)):
print(f"来自客户端的消息:{data.decode()}")
message = input("输入需要发送给客户端的消息:")
c.send(message.encode())
else:
print("系统提示:客户端已下线,链接已关闭...")
# 客户端
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as c:
c.connect(("127.0.0.1", 8080))
while True:
message = input("输入需要发送给服务器的消息:")
if len(message) < 1:
print("您已主动已关闭连接")
break
c.send(message.encode())
response = c.recv(1024).decode()
print(f"来自服务器的消息:{response}")
问题
没有捕获异常 很容易让程序卡死,建议捕获异常。
# 服务端
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(("127.0.0.1", 8080))
s.listen()
print("链接已创建 等待客户端链接...")
while 1:
try:
c, addr = s.accept()
while (data := c.recv(1024)):
print(f"来自客户端{addr}的消息:{data.decode()}")
message = input("输入需要发送给客户端的消息:")
c.send(message.encode())
else:
print("系统提示:客户端已下线,链接已关闭...")
break
c.close()
except socket.error as e:
print(e)
break
# 客户端
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as c:
c.connect(("127.0.0.1", 8080))
while True:
try:
message = input("输入需要发送给服务器的消息:")
if len(message) < 1:
print("您已主动已关闭连接")
break
c.send(message.encode())
response = c.recv(1024).decode()
print(f"来自服务器的消息:{response}")
except ConnectionResetError:
print("服务端主动下线,连接已关闭.")
break
UDP方式发送
# server.py
import socket
# 创建UDP socket
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
# 绑定IP地址和端口号
s.bind(("127.0.0.1", 8080))
# 接收数据和客户端地址
data, addr = s.recvfrom(1024)
# 打印客户端地址和接收到的数据(解码)
print("Client Address:", addr)
print("Received Data:", data.decode())
# client.py
import socket
# 创建UDP socket
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as c:
# 服务器地址
server_address = ("127.0.0.1", 8080)
# 发送数据到服务器
c.sendto("你好,我是UDP".encode(), server_address)
标签:socket,AF,print,message,INET,客户端
From: https://www.cnblogs.com/ccsvip/p/17964167