【NVIDIA JETSON AGX XAVIER】与个人笔记本(win11)建立TCP-IP连接相互传输数据(含源码)


前言

我的上一篇博客:【NVIDIA JETSON AGX XAVIER】与个人笔记本(win11)建立TCP-IP连接传输数据(含源码)
博客中的代码只能实现从服务器端(个人笔记本(win11))传输数据到客户端(NVIDIA JETSON AGX XAVIER),且只能传输一次文件
本博客将进行优化,并实现双向传输数据。

一、个人笔记本(win11)传输数据到XAVIER(多次传输)

在前面代码的基础上添加循环机制,假如现在服务器ip地址是192.168.0.1

1.服务器端代码(个人笔记本win11)

代码如下(示例):

import socket
import os

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:
                    bytes_to_send = f.read(1024)
                    conn.send(bytes_to_send)
    else:
        conn.send(b'ERR ')

def server_program():
    host = socket.gethostname()
    port = 5005
    server_socket = socket.socket()
    server_socket.bind((host, port))
    server_socket.listen(5)
    print("服务器启动,等待连接...")
    conn, address = server_socket.accept()
    print("连接来自: " + str(address))
    while True:
        data = conn.recv(1024).decode()
        if not data:
            # 如果没有接收到数据,继续等待新的文件请求
            continue
        send_file(data, conn)
    conn.close()

if __name__ == '__main__':
    server_program()

2.客户端代码(NVIDIA JETSON AGX XAVIER)

代码如下(示例):

import socket

def client_program():
    host = socket.gethostname()
    port = 5001

    client_socket = socket.socket()
    client_socket.connect(("192.168.0.1", port))
    print("连接成功")

    while True:  # 添加外部循环以持续请求文件
        file_name = input("输入要传输的文件名或输入'exit'退出: ")
        if file_name.lower() == 'exit':
            break
        client_socket.send(file_name.encode())

        data = client_socket.recv(1024).decode()
        if data[:6] == 'EXISTS':
            file_size = int(data[6:])
            client_socket.send(b'OK')
            f = open('new_' + file_name, 'wb')
            data = client_socket.recv(1024)
            total_recv = len(data)
            f.write(data)
            while total_recv < file_size:
                data = client_socket.recv(1024)
                total_recv += len(data)
                f.write(data)
                print("{0:.2f}".format((total_recv/float(file_size))*100)+ "% Done")
            print("下载完成!")
            f.close()
        else:
            print("文件不存在!")

    client_socket.close()

if __name__ == '__main__':
    client_program()

二、两端相互传输(以另一种形式解决上一篇博客的问题)

假如现在服务器ip地址是192.168.0.1

1.服务器端代码(个人笔记本win11)

在前面代码的基础上添加receive_file函数,处理接收的客户端的数据。
代码如下(示例):

import socket
import os

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:
        data = conn.recv(1024).decode()
        if data.startswith('send'):
            filename = data[5:]
            receive_file(filename, conn)
        else:
            send_file(data, conn)
        if not data:
            # break
            continue

    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)


if __name__ == '__main__':
    server_program()

2.客户端代码(NVIDIA JETSON AGX XAVIER)

在前面代码的基础上添加send_file_to_server函数,判断发送给服务器的文件是否存在,修改主函数(client_program),添加"输入 ‘get’ 请求文件,或者 ‘send’ 发送文件,或输入’exit’退出三种模式选择,客户端(Xavier)可以选择收或发文件。
代码如下(示例):

import socket
import os
def client_program():
    host = socket.gethostname()
    port = 5011

    client_socket = socket.socket()
    client_socket.connect(("192.168.0.1", port))
    print("连接成功")

    while True:  # 添加外部循环以持续请求文件
        action = input("输入 'get' 请求文件,或者 'send' 发送文件,或输入'exit'退出:")
        if action.lower() == 'exit':
            break
        elif action.lower() == 'get':
            file_name = input("输入要传输的文件名: ")
            client_socket.send(file_name.encode())
            data = client_socket.recv(1024).decode()
            if data[:6] == 'EXISTS':
                file_size = int(data[6:])
                client_socket.send(b'OK')
                # f = open(r'' + file_name, 'wb')
                f = open(r'new_' + file_name, 'wb')
                data = client_socket.recv(1024)
                total_recv = len(data)
                f.write(data)
                while total_recv < file_size:
                    data = client_socket.recv(1024)
                    total_recv += len(data)
                    f.write(data)
                    print("{0:.2f}".format((total_recv/float(file_size))*100)+ "% Done")
                print("下载完成!")
                f.close()
            else:
                print("文件不存在!")
                client_socket.send(file_name.encode())
        elif action.lower() == 'send':
            file_name = input("输入要发送的文件名: ")
            if os.path.isfile(file_name):  # 在这里添加检查
                send_file_to_server(file_name, client_socket)
                print("成功发送:" + file_name)
            else:
                print("文件不存在,请检查文件名是否正确。")
    client_socket.close()
def send_file_to_server(filename, client_socket):
    if os.path.isfile(filename):  # 检查文件是否存在
        client_socket.send(('send ' + filename).encode())
        response = client_socket.recv(1024).decode()
        if response == 'READY':
            with open(filename, 'rb') as f:
                bytes_to_send = f.read(1024)
                while bytes_to_send:
                    client_socket.send(bytes_to_send)
                    bytes_to_send = f.read(1024)
    else:
        print("文件不存在,请检查文件名是否正确。")
if __name__ == '__main__':
    client_program()

三、传输数据中的缓存问题

运行上述程序出现的问题:客户端在选择进行两次send发送文件时,前一次send发送成功,且能够在服务器上看到传输的文件,但是文件大小为0,过一段时间后,文件才会恢复原本的大小

且再一次的send,输入文件名回车后,程序将没有反应。

在这里插入图片描述

在这里插入图片描述
程序将没有反应。只能直接结束程序,报错如下:
在这里插入图片描述

1.查找资料,发现问题

问题可能与文件传输的同步性有关。当文件内容在传输后为空,但过一段时间后恢复,这可能意味着文件数据在传输过程中被缓存或延迟了。这种情况可能是由于网络延迟或者客户端和服务器之间的同步问题。

对于客户端在第一次发送文件后无法再次发送文件的问题,这可能是因为客户端或服务器的socket没有正确地处理连续的send操作。在某些情况下,如果发送缓冲区没有被及时清空,或者前一次的数据还没有完全发送完毕,再次尝试send可能会失败。

2.尝试解决

以下是一些可能的解决方法:

  1. 确认发送和接收程序的同步:确保发送方在发送完一个文件后,接收方已经完全接收并处理了该文件。可以通过在发送方和接收方之间实现一个简单的确认机制,例如发送方在发送完一个文件后等待接收方的确认消息,然后再进行下一个文件的发送。

  2. 检查网络状况:网络延迟或不稳定可能会导致文件传输中断或延迟。确保网络连接稳定,并考虑使用更可靠的网络连接。

  3. 使用流控制协议:如果您正在使用自定义的文件传输协议,考虑实现TCP-like的流控制机制,如滑动窗口协议,以确保数据的可靠传输。

  4. 调整socket选项:在某些情况下,调整socket的行为可以帮助解决问题。例如,设置socket为非阻塞模式,并使用select或epoll来监控socket的状态,这样可以更有效地管理发送缓冲区和避免发送阻塞。

  5. 使用现有的文件传输协议:如果可能,考虑使用现有的文件传输协议,如FTP或SFTP,这些协议提供了更完善的错误检查和恢复机制,适合传输大文件。

  6. 检查程序逻辑:仔细检查客户端和服务器程序的逻辑,确保在发送和接收文件时,程序能够正确处理连续的send操作。

尝试上述方法并未解决!判断可能是网络延迟问题


总结

本博客建立了 XAVIER与个人笔记本(win11)的TCP-IP连接并实现了相互传输数据,但传输过程中存在缓存问题,不能保证每次传输都能够成功,还需要优化程序!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值