3. TCP-Client例程讲解#
1. 环境准备#
为了顺利进行TCP通信的演示,我们需要确保以下环境已经配置妥当:
1.1 硬件连接#
确保你的CanMV开发板和电脑都已经通过网线连接到同一个路由器或交换机上,形成一个局域网。
路由器或交换机需要正常工作,以确保网络通畅。
1.2 关闭防火墙#
为了避免防火墙拦截TCP通信,建议暂时关闭电脑上的防火墙。
1.3 工具准备#
下载并安装NetAssist网络调试助手工具,这将帮助我们进行网络数据的收发测试。
1.4 记录IP地址#
打开CMD(命令提示符),输入
ipconfig
指令,查看并记录电脑网口所分配的IP地址。这将用于后续设置和测试。
2. 客户端例程解析#
2.1 导入库#
import network
import socket
import time
network:这个库用于操作网络接口,如配置IP地址、检查网络状态等。
socket:这个库提供了socket接口,用于网络通信。
time:这个库提供了与时间相关的函数,如延时(sleep)。
2.2 定义客户端函数#
def client():
# ...(后续代码)
定义了一个名为
client
的函数,这个函数包含了TCP客户端的所有逻辑。
2.3 配置网络接口#
def network_use_wlan(is_wlan=True):
if is_wlan:
sta=network.WLAN(0)
sta.connect("Canaan","Canaan314")
print(sta.status())
while sta.ifconfig()[0] == '0.0.0.0':
os.exitpoint()
print(sta.ifconfig())
ip = sta.ifconfig()[0]
return ip
else:
a=network.LAN()
if not a.active():
raise RuntimeError("LAN interface is not active.")
a.ifconfig("dhcp")
print(a.ifconfig())
ip = a.ifconfig()[0]
return ip
这段代码根据输入参数来配置网络接口。主要流程如下:
WLAN模式:
如果
is_wlan
参数为True
,则程序配置无线网络接口(WLAN)。创建 WLAN 接口实例并尝试连接到指定的 Wi-Fi 网络(SSID 为 “Canaan”,密码为 “Canaan314”)。
打印 WLAN 接口的连接状态,并在获得有效 IP 地址之前循环等待。
成功连接后,打印网络配置并返回获取的 IP 地址。
LAN模式:
如果
is_wlan
参数为False
,则程序配置有线网络接口(LAN)。获取 LAN 接口实例并检查其是否已激活。
如果接口未激活,抛出
RuntimeError
异常,提示接口未激活。将 LAN 接口配置为 DHCP 模式,自动从路由器获取 IP 地址。
打印网络配置并返回获取的 IP 地址。
2.4 创建Socket#
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
创建一个新的socket对象,使用IPv4(
AF_INET
)和TCP(SOCK_STREAM
)协议。第三个参数(通常为0)用于指定socket的类型或其他选项,但在大多数情况下可以保持为0。
2.5 获取服务器地址和端口#
ai = socket.getaddrinfo("172.16.1.174", 8080)
addr = ai[0][-1] # 提取地址和端口
地址解析:使用
getaddrinfo
函数根据提供的服务器地址("172.16.1.174"
)和端口号(8080
)获取地址信息。这个函数返回一个列表,其中每个元素都是一个包含多个元素的元组,第一个元素是地址族(如IPv4或IPv6),最后一个元素是一个包含地址和端口的元组。提取地址和端口:从
getaddrinfo
返回的结果中选择第一个元素(通常是首选的协议和地址),并提取出地址和端口。
2.6 连接到服务器#
try:
s.connect(addr)
print("Connected to server:", addr)
except Exception as e:
s.close()
print("Connection error:", e)
return
尝试使用
connect
方法连接到服务器。如果连接成功,则打印连接信息。如果在连接过程中发生异常(如网络不可达、服务器未运行等),则捕获异常并打印错误信息,然后关闭socket并退出函数。
2.7 发送数据#
for i in range(10):
message = "K230 tcp client send test {0} \r\n".format(i)
print("Sending:", message)
s.sendall(message.encode()) # 发送数据前需要编码为字节串
time.sleep(0.2) # 稍作延时
在一个循环中发送10条消息。
构造每条消息,并使用
format
方法将循环变量i
插入到消息中。在发送之前,使用
encode
方法将消息编码为字节串,因为sendall
方法需要字节串作为参数。使用
sendall
方法发送数据,这个方法会尝试发送所有数据,直到所有数据都被发送完毕或发生错误。在每次发送后使用
time.sleep
方法稍作延时,以模拟发送间隔。
2.8 关闭Socket#
s.close()
print("Client ends connection.")
在完成所有通信后,使用
close
方法关闭socket,以释放资源。打印一条消息表示客户端已结束连接。
2.9 完整例程#
#配置 tcp/udp socket调试工具
import network
import socket
import os,time
def network_use_wlan(is_wlan=True):
if is_wlan:
sta=network.WLAN(0)
sta.connect("Canaan","Canaan314")
print(sta.status())
while sta.ifconfig()[0] == '0.0.0.0':
os.exitpoint()
print(sta.ifconfig())
ip = sta.ifconfig()[0]
return ip
else:
a=network.LAN()
if not a.active():
raise RuntimeError("LAN interface is not active.")
a.ifconfig("dhcp")
print(a.ifconfig())
ip = a.ifconfig()[0]
return ip
def client():
#获取lan接口
network_use_wlan(True)
#建立socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
#获取地址及端口号 对应地址
ai = socket.getaddrinfo("192.168.1.110", 8080)
#ai = socket.getaddrinfo("10.10.1.94", PORT)
print("Address infos:", ai)
addr = ai[0][-1]
print("Connect address:", addr)
#连接地址
if(s.connect(addr) == False):
s.close()
print("conner err")
return
for i in range(10):
str="K230 tcp client send test {0} \r\n".format(i)
print(str)
#print(s.send(str))
#发送字符串
print(s.write(str))
time.sleep(0.2)
#time.sleep(1)
#print(s.recv(4096))
#print(s.read())
#延时1秒
time.sleep(1)
#关闭socket
s.close()
print("end")
#main()
client()
3. 例程现象与操作说明#
打开NetAssist网络调试助手,建立TCP server连接:
在例程源码中修改对应的IP,端口:
ai = socket.getaddrinfo("172.16.1.174", 8080)
运行例程代码,NetAssist网络调试助手输出信息: