提示:本博客是在前面几篇博客上进行的最终优化,后续将不再更新这类问题。
文章目录
前言
提示:本博客解决了我的前几篇博客中提出的所有问题,针对代码程序进行了优化,下面链接是我的前几篇博客:
【NVIDIA JETSON AGX XAVIER】与个人笔记本(win11)建立TCP-IP连接传输数据(含源码)
【NVIDIA JETSON AGX XAVIER】与个人笔记本(win11)建立TCP-IP连接相互传输数据(含源码)
上面这几篇博客中出现的问题:
1.无法实现连续传输数据
2.无法实现从客户端(Xavier)传输数据到服务器端(个人笔记本电脑)
3.Xavier板子无法作为服务器进行TCP-IP连接
本博客将一一进行解决,并记录解决过程中出现的问题。
不想看改进过程的可以直接点击目录跳转到“五、2.3”程序看最终的代码
一、实现持续传输数据
1.服务器代码改进
在连接客户端程序中的def server_program()函数中,使用while循环实时接收到数据,并继续等待客户端新的文件请求。
while True:
2.服务器代码改进
在连接服务器程序中的client_program()函数中添加外部循环以持续请求文件
while True:
并增加代码,输入文件名可以一直传输数据,直到输入“exit”结束程序
file_name = input("输入要传输的文件名或输入'exit'退出: ")
具体实现循环的代码见以下链接中【一、个人笔记本(win11)传输数据到XAVIER(多次传输)】
【NVIDIA JETSON AGX XAVIER】与个人笔记本(win11)建立TCP-IP连接相互传输数据(含源码)
二、实现相互传输数据,但存在问题
具体实现相互传输的代码见以下链接中【二、两端相互传输(以另一种形式解决上一篇博客的问题)】
【NVIDIA JETSON AGX XAVIER】与个人笔记本(win11)建立TCP-IP连接相互传输数据(含源码)
3.程序出现问题
以上代码实现了相互传输数据,但是出现问题如下:
添加好程序后能够传输文件,传输后文件内容为空,且客户端send发送一次文件后,再次send无法发送文件,但是再强制结束进程后,第一次传输的文件大小从空恢复正常。
强制结束进程客户端(Xavier)报错如下:
查找资料寻找解决方法:客户端在传输一次数据后需要断开(执行close)
客户端第一次 send 后,如果没有执行 shutdown 或 close,可能会发生阻塞或无法发送。
需要确保服务器端已经准备好接收新的数据。如果服务器端处理第一次接收的文件内容后没有正确地再次准备接收新数据,客户端可能会无法进行二次发送。
解决:
在数据发送和接收的代码周围添加适当的错误判断和处理机制,比如尝试捕获和处理可能发生的异常。
具体代码:
服务器代码:
在receive_file(filename, conn)函数中
增加
conn.send(b'READY')
和
conn.send(b'DONE') # 发送文件接收完成的确认消息
发送给客户端“服务器以准备好接收数据”
对应客户端代码会有如下代码
if response == 'READY':
……
……
if response == 'DONE':
print("文件成功发送并由服务器接收。")
else:
print("服务器未确认文件接收完成。")
else:
print("服务器未准备好接收文件。")
同样在服务器的send_file()函数中有
if user_response[:2] == 'OK':
对应客户端中的
client_socket.send(b'OK')
修改后代码如下
三、解决传输中的缓存问题
1.服务器
代码如下(示例):
import socket
import os
import chardet
def send_file(filename, conn):
if os.path.isfile(filename):
# 发送文件存在确认消息
conn.send(b'EXISTS ' + str(os.path.getsize(filename)).encode())
user_response = conn.recv(1024).decode()
if user_response[:2] == 'OK':
with open(filename, 'rb') as f:
bytes_to_send = f.read(1024)
conn.send(bytes_to_send)
# while bytes_to_send != "":
while bytes_to_send:
bytes_to_send = f.read(1024)
conn.send(bytes_to_send)
else:
conn.send(b'ERR ')
def server_program():
# 获取主机名
host = socket.gethostname()
port = 5011 # 初始化端口号
server_socket = socket.socket() # 获取socket对象
server_socket.bind((host, port)) # 绑定地址到socket
server_socket.listen(5) # 监听连接,最多可接受5个连接
print("服务器启动,等待连接...")
conn, address = server_socket.accept() # 接受新连接
print("连接来自: " + str(address))
while True:
# raw_data = conn.recv(1024)
# if not raw_data:
# break
# encoding = chardet.detect(raw_data)['encoding']
# data = raw_data.decode(encoding)
data = conn.recv(1024).decode()
if data.startswith('send'):
filename = data[5:]
receive_file(filename, conn)
elif data.startswith('get'):
send_file(data[4:], conn)
if not data:
break
conn.close()
def receive_file(filename, conn):
conn.send(b'READY')
with open(filename, 'wb') as f:
while True:
bytes_read = conn.recv(1024)
if not bytes_read:
break
f.write(bytes_read)
break
# conn.send(b'DONE') # 发送文件接收完成的确认消息
conn.send(b'DONE') # 发送文件接收完成的确认消息
if __name__ == '__main__':
server_program()
2.客户端
代码如下(示例):
import socket
import os
def client_program():
host = socket.gethostname()
port = 5011
client_socket = socket.socket()
# 172.17.0.1
client_socket.connect(("192.168.137.1", port))
print("连接成功")
while True: # 添加外部循环以持续请求文件
action = input("输入 'get' 请求文件,或者 'send' 发送文件,或输入'exit'退出:")