Python高阶技巧 网络编程

Socket

ocket (简称 套接字) 是进程之间通信一个工具,好比现实生活中的插座,所有的家用电器要想工作都是基于插座进行,进程之间想要进行网络通信需要socket。

Socket负责进程之间的网络数据传输,好比数据的搬运工。

 客户端和服务端

2个进程之间通过Socket进行相互通讯,就必须有服务端和客户端

Socket服务端:等待其它进程的连接、可接受发来的消息、可以回复消息

Socket客户端:主动连接服务端、可以发送消息、可以接收回复

Socket服务端编程

主要分为如下几个步骤:

1. 创建socket对象

import socket
# 创建Socket对象
socket_server = socket.socket()

2. 绑定socket_server到指定IP和地址

# 绑定socket_server到指定的ip和地址
socket_server.bind(host, port)

3.  服务端开始监听端口

# 服务端监听端口
socket_server.listen(backlog)
# listen方法内接受一个整数传参数,
# backlog为int整数,表示接受的链接数量,超出的会等待,可以不填,不填会自动设置一个合理值

4.  接收客户端连接,获得连接对象

# 接受客户端连接,获得连接对象
# result: tuple = socket_server.accept()
# conn = result[0]        # 客户端和服务端的链接对象
# address = result[1]     # 客户端的地址信息

conn, address = socket_server.accept()
print(f"接收到了客户端的链接,客户端的信息是:{address}")

# accept()方法,是阻塞的方法,等待客户端的链接,如果没有链接,就卡在这一行不向下执行了
# accept方法返回的是二元元组(链接对象, 客户端地址信息)
# 可以通过 变量1, 变量2 = socket_server.accept()的形式,直接接受二元元组内的两个元素

5. 客户端连接后,通过recv方法,接收客户端发送的消息

while True:
    # 接受客户端信息,要使用客户端和服务端的本次链接对象,而非socket_server对象
    data: str = conn.recv(1024).decode("UTF-8")
    # recv接受的参数是缓冲区大小,一般给1024即可
    # recv方法的返回值是一个字节数组也就是bytes对象,不是字符串,可以通过decode方法通过UTF-8编码,将字节数组转换为字符串对象
    print(f"客户端发来的消息是:{data}")

6. 通过conn(客户端当次连接对象),调用send方法可以回复消息

while True:
    # 接受客户端信息,要使用客户端和服务端的本次链接对象,而非socket_server对象
    data: str = conn.recv(1024).decode("UTF-8")
    # recv接受的参数是缓冲区大小,一般给1024即可
    # recv方法的返回值是一个字节数组也就是bytes对象,不是字符串,可以通过decode方法通过UTF-8编码,将字节数组转换为字符串对象
    print(f"客户端发来的消息是:{data}")
    # 发送回复消息
    msg = input("请输入你要和客户端回复的消息:")
    if msg == 'exit':
        break
    conn.send(msg.encode("UTF-8"))

7. conn(客户端当次连接对象)和socket_server对象调用close方法,关闭连接

# 关闭链接
conn.close()
socket_server.close()

实现服务端并结合客户端进行测试

下载网络调试助手作为客户端

https://github.com/nicedayzhu/netAssist/releases

Socket客户端编程

主要分为如下几个步骤:

1. 创建socket对象

2. 连接到服务端

3. 发送消息

4. 接收返回消息

5. 关闭链接

服务端客户端相互通讯

结合上一节学习的服务端代码,以及当前学习的客户端代码。

两者均运行起来,进行相互通讯。

 

"""
演示Socket服务端开发
"""
import socket
# 创建Socket对象
socket_server = socket.socket()
# 绑定ip地址和端口
socket_server.bind(("localhost", 8888))
# 监听端口
socket_server.listen(1)
# listen方法内接受一个整数传参数,表示接受的链接数量
# 等待客户端链接
# result: tuple = socket_server.accept()
# conn = result[0]        # 客户端和服务端的链接对象
# address = result[1]     # 客户端的地址信息
conn, address = socket_server.accept()
# accept方法返回的是二元元组(链接对象, 客户端地址信息)
# 可以通过 变量1, 变量2 = socket_server.accept()的形式,直接接受二元元组内的两个元素
# accept()方法,是阻塞的方法,等待客户端的链接,如果没有链接,就卡在这一行不向下执行了

print(f"接收到了客户端的链接,客户端的信息是:{address}")

while True:
    # 接受客户端信息,要使用客户端和服务端的本次链接对象,而非socket_server对象
    data: str = conn.recv(1024).decode("UTF-8")
    # recv接受的参数是缓冲区大小,一般给1024即可
    # recv方法的返回值是一个字节数组也就是bytes对象,不是字符串,可以通过decode方法通过UTF-8编码,将字节数组转换为字符串对象
    print(f"客户端发来的消息是:{data}")
    # 发送回复消息
    msg = input("请输入你要和客户端回复的消息:")
    if msg == 'exit':
        break
    conn.send(msg.encode("UTF-8"))
# 关闭链接
conn.close()
socket_server.close()
"""
演示Socket客户端开发
"""
import socket
# 创建socket对象
socket_client = socket.socket()
# 连接到服务端
socket_client.connect(("localhost", 8888))

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()

总结:

客户端和服务端的相同点:

import socket
# 创建socket对象
socket_client = socket.socket()

客户端和服务端的不同点:

  • 服务端:
# 绑定ip地址和端口
socket_server.bind(("localhost", 8888))
# 监听端口
socket_server.listen(1)
  • 服务端先接收消息再发送消息
  • 客服端:
# 连接到服务端
socket_client.connect(("localhost", 8888))
  • 客服端先发送消息再接收消息

猜你喜欢

转载自blog.csdn.net/qq1226546902/article/details/132058346