在现代计算机网络中,Socket(套接字)是实现进程之间通信的重要工具。在网络应用中,Socket 充当了进程间数据传输的搬运工,负责进程之间的网络数据传输。无论是服务器还是客户端,二者通过 Socket 进行通信,形成了网络应用的基础。本章详细讲解了Socket服务端开发以及Socket客户端开发。
Socket 是网络编程中用于建立和管理网络连接的一种抽象,主要用于服务端和客户端之间的通信。
①Socket服务端
②Socket客户端
①导包并创建socket对象
import socket
socket_server=socket.socket()
②绑定socket_server到指定IP和地址
socket_server.bind((host, port))
bind()
方法:是 socket 对象的方法,用于将一个地址(主机名和端口号)绑定到一个 Socket 上,通常用于服务器端。(host, port)
: 一个元组,其中 host 通常是 IP 地址,port 是整数形式的端口号。【示例】
# 绑定socket_server到指定IP和地址
socket_server.bind(("localhost",8888))
localhost
:一个特殊的主机名,表示本地计算机。它允许服务端在本机上进行测试而不需要连接外部网络。8888
:要绑定的端口号。端口号用于标识特定的服务或进程。在这个例子中,服务端将在本地的 8888 端口上监听来自客户端的连接请求。③服务端开始监听端口
socket_server.listen(backlog)
listen
方法:用于将 Socket 设置为被动模式,以便接收来自客户端的连接请求。# 服务端开始监听端口
socket_server.listen(1) # listen()方法内接收一个整数传参数,表示接受的链接数量backlog
:为 int 整数,表示允许的连接请求数量。如果同时有多个客户端请求连接,超出该数量的请求将被拒绝。该参数是可选的,如果不指定,系统会自动设置一个合理的默认值。
【示例】④接收客户端连接,获得连接对象
socket_server.accept()
accept
方法:一个阻塞方法,用于在服务器端接受客户端的连接请求。调用该方法后,如果没有客户端尝试连接,accept() 方法会阻塞并等待直到有一个客户端尝试连接。
该方法返回一个二元元组(conn, address)
,其中:
conn
:一个新的 Socket 对象,用于与连接的客户端进行通信。address
:客户端的地址(IP 地址和端口),提供了连接的客户端的信息。【示例】
# 等待客户端链接
conn,address=socket_server.accept()
"""
上面这行代码等价于
result:tuple=socket_server.accept()
conn=result[0]
address=result[1]
"""
【分析】
accept
方法返回的是二元元组(conn, address)
,可以通过变量1,变量2=socket_server.accept()
的形式直接接收二元元组内的两个元素。
⑤接收客户端发送的消息
conn.recv(bytes)
recv
方法:一个阻塞方法,用于接收连接中发来的数据。如果接收到的数据小于指定的字节数,方法将返回已接收的数据;如果没有数据可接收,程序会等待,直到有数据到达为止。bytes
: 一个 int 整数,指定要接收的最大字节数。【注意】
recv
方法通过conn
调用而不是socket_server
调用。因为conn
是专用于与特定客户端进行通信的 Socket 对象,而conn
是用于监听和接受连接的服务器 Socket。
【示例】
data=conn.recv(1024).decode("UTF-8")
⑥回复客户端信息
conn.send(data)
send
方法:用于将数据发送给连接的客户端# 通过conn(客户端当次连接对象),调用send方法可以回复消息
conn.send(msg.encode("UTF-8"))在这个示例中,conn.send() 方法接收的参数是通过 encode("UTF-8") 将字符串转换为字节后的结果。这样,客户端才能正确接收和处理该信息。data
: 一个字节序列(bytes 对象),表示要发送的数据。
【示例】⑦关闭连接
conn(客户端当次连接对象)和socket_server对象调用close方法,关闭连接。
conn.close()
socket_server.close()
⑧测试
下载网络调试助手作为客户端进行测试。
下载地址:https://github.com/nicedayzhu/netAssist/releases
服务端代码示例:
# 导包
import socket
# 创建socket对象
socket_server=socket.socket()
# 绑定socket_server到指定IP和地址
socket_server.bind(("localhost",8888))
# 服务端开始监听端口
socket_server.listen(1) # listen()方法内接收一个整数传参数,表示接受的链接数量
# 等待客户端链接
conn,address=socket_server.accept()
print(f"接收到了客户端的链接,客户端信息为{address}")
while True:
# 接收客户端连接,获得连接对象
data=conn.recv(1024).decode("UTF-8")
print(f"客户端发来的消息:{data}")
# 通过conn(客户端当次连接对象),调用send方法可以回复消息
msg=input("请输入回复客户端的信息:")
if msg=='exit':
break
conn.send()
# 关闭连接
conn.close()
socket_server.close()
运行服务端代码
双击打开安装好的网络调试助手netAssist
配置netAssist相关环境,点击“开始连接”
连接成功
客户端发送消息
服务端成功接收消息
输入 "exit",代码中的 break 语句会被执行,从而终止当前的循环,服务端会停止向客户端发送消息,并最终结束程序。
主要分为如下几个步骤:
①导包并创建socket对象
import socket
socket_client=socket.socket()
②连接到服务端
socket_client.connect((host, port))
connect()
方法:一个阻塞方法,用于客户端连接到服务器。如果服务器没有响应,connect() 会阻塞,直到连接成功或发生超时。
【示例】
# 绑定socket_server到指定IP和地址
socket_client.connect(("localhost",8888))
③发送消息
socket_client.send(data)
# 发送消息
socket_client.send("你好呀".encode("UTF-8"))
④接收服务端消息
socket_client.recv(bytes)
# 接收返回信息
recv_data=socket_client.recv(1024) # 1024为缓冲区大小,一般给1024即可
⑤关闭链接
socket_client.close()
服务端示例代码:
# 导包
import socket
# 创建socket对象
socket_server=socket.socket()
# 绑定socket_server到指定IP和地址
socket_server.bind(("localhost",8888))
# 服务端开始监听端口
socket_server.listen(1) # listen()方法内接收一个整数传参数,表示接受的链接数量
# 等待客户端链接
conn,address=socket_server.accept()
print(f"接收到了客户端的链接,客户端信息为{address}")
while True:
# 接收客户端连接,获得连接对象
data=conn.recv(1024).decode("UTF-8")
print(f"客户端发来的消息:{data}")
# 通过conn(客户端当次连接对象),调用send方法可以回复消息
msg=input("请输入回复客户端的信息:")
if msg=='exit':
break
conn.send()
# 关闭连接
conn.close()
socket_server.close()
客户端示例代码:
# 导包
import socket
# 创建socket对象
socket_client=socket.socket()
# 绑定socket_server到指定IP和地址
socket_client.connect(("localhost",8888))
# 发送消息
socket_client.send("你好呀".encode("UTF-8"))
while True:
# 发送消息
msg = input("请输入要给服务端发送的消息:")
if msg == 'exit':
break
socket_client.send(msg.encode("UTF-8"))
# 接收返回消息
recv_data = socket_client.recv(1024) # 1024是缓冲区的大小,一般1024即可。 同样recv方法是阻塞的
print(f"服务端回复的消息是:{recv_data.decode('UTF-8')}")
# 关闭链接
socket_client.close()
先启动服务端再启动客户端。
服务端接收到客户端发来的信息并回复客户端。
客户端接收到服务端发来的信息并回复服务端。
输入 "exit",代码中的 break 语句会被执行,从而终止当前的循环,服务端会停止向客户端发送消息,并最终结束程序。
思考:为什么服务端会比客户端多一个conn对象?
回答:服务端与客户端在通信中扮演着不同的角色。服务端需要接收来自多个客户端的连接,每当一个客户端连入时,服务端通过accept()方法创建一个新的连接对象conn,用于与该特定客户端进行数据交换。这样,服务端可以同时处理多个客户端的请求,而客户端每次只与一个服务端连接。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。