核心 Bug:客户端与服务器端口不匹配(导致请求无法送达)

Bug 分析报告

1. 核心 Bug:客户端与服务器端口不匹配(导致请求无法送达)
  • 问题描述 :客户端代码中定义的服务器端口为 69(static const int PORT = 69),而服务器代码中绑定的端口为 6969(static const int PORT=6969)。由于 UDP 通信中客户端必须发送数据到服务器实际监听的端口,端口不匹配会导致服务器无法接收客户端的下载 / 上传请求,最终表现为功能失败。
  • 定位代码
    • 客户端端口定义(TFTPClient类私有成员):

      cpp

      运行

      复制代码
      static const int PORT = 69;  // 客户端使用的服务器端口
    • 服务器端口定义(TFTPServer类私有成员):

      cpp

      运行

      复制代码
      static const int PORT=6969;  // 服务器实际监听的端口
2. 次要 Bug:客户端输入缓冲区处理不当(可能导致文件名读取失败)
  • 问题描述 :客户端run()函数中,用户输入选择(1/2/3)后调用waitForInput()清空缓冲区,但在doDownload()doUpload()中使用getline(cin, filename)读取文件名时,可能因缓冲区残留数据导致读取空字符串或错误内容。
  • 定位代码
    • run()中输入选择后调用waitForInput()

      cpp

      运行

      复制代码
      cin >> choice;   // 输入选项
      waitForInput(); // 吸收垃圾字符
    • waitForInput()实现(仅清空到换行符,但未考虑cin的状态):

      cpp

      运行

      复制代码
      void TFTPClient::waitForInput() {
          while (getchar() != '\n'); // 纯清空输入缓冲区直到换行符
      }
    • 若用户输入选择后有多余字符(如1 abc\n),waitForInput()会将abc也清空,导致后续getline需要重新输入,但更严重的是,若cin状态异常(如输入非字符),可能导致getline直接失败。

Bug 解决方案

1. 修复端口不匹配问题
  • 修改客户端端口 :将客户端TFTPClient类中的PORT修改为与服务器一致的 6969,确保客户端请求能发送到服务器监听的端口。

    cpp

    运行

    复制代码
    // 客户端TFTPClient类私有成员修改
    static const int PORT = 6969;  // 与服务器端口保持一致
2. 优化输入缓冲区处理(避免文件名读取失败)
  • 改进waitForInput()函数 :在清空缓冲区前先检查cin的状态,确保输入流正常,避免因输入异常导致后续getline失效。

    cpp

    运行

    复制代码
    void TFTPClient::waitForInput() {
        // 若cin处于错误状态,先清空错误标志
        if (cin.fail()) {
            cin.clear();
        }
        // 清空缓冲区直到换行符
        while (getchar() != '\n');
    }
  • getline前手动清空缓冲区 :尽管waitForInput()已处理,但为确保getline能正确读取文件名,可在doDownload()doUpload()getline前再做一次缓冲区检查(可选增强):

    cpp

    运行

    复制代码
    // doDownload()中读取文件名前添加
    cout << "请输入要下载的文件的文件名称:";
    cin.ignore(numeric_limits<streamsize>::max(), '\n'); // 强制清空残留缓冲区
    getline(cin, filename);
    
    // doUpload()中同理
    cout << "请输入要上传的文件名:";
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    getline(cin, filename);
3. 补充错误处理(增强鲁棒性)
  • 服务器路径拼接容错 :服务器handleReadRequesthandleWriteRequest中拼接文件路径时,处理root_dir/结尾的情况(避免出现//):

    cpp

    运行

    复制代码
    // 服务器拼接路径时修改
    string full_path;
    if (!root_dir.empty() && root_dir.back() == '/') {
        full_path = root_dir + filename;
    } else {
        full_path = root_dir + "/" + filename;
    }
  • 客户端超时处理 :客户端recvfrom时添加超时机制,避免因服务器无响应导致程序卡死(使用setsockopt设置SO_RCVTIMEO):

    cpp

    运行

    复制代码
    // 客户端构造函数中添加超时设置(如5秒超时)
    struct timeval timeout = {5, 0}; // 5秒
    setsockopt(sfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));

总结

主要问题是客户端与服务器端口不匹配,导致请求无法送达,修复端口一致即可解决核心功能失败问题。输入缓冲区处理和错误处理的优化可进一步提升程序稳定性。

相关推荐
是垚不是土6 小时前
基于Blackbox Exporter的网络服务黑盒监控体系实践
网络·数据库·安全·http·微服务·prometheus
福尔摩斯张6 小时前
TCP协议深度解析:从报文格式到连接管理(超详细)
linux·c语言·网络·c++·笔记·网络协议·tcp/ip
刀刀是个萌妹子6 小时前
使用CloneZilla还原操作系统
linux·运维·服务器
那我掉的头发算什么6 小时前
【javaEE】保姆级 HTTP 全解析:请求响应 + 状态码 + Fiddler 实操
网络·http·java-ee·fiddler
列逍6 小时前
Linux文件(二)
linux·磁盘·文件系统·挂载·软硬链接·缓冲区
一个平凡而乐于分享的小比特6 小时前
U-Boot 和 Linux 内核的关系及设备树详解
linux·设备树·uboot
代码不行的搬运工6 小时前
交换机和网卡的 PFC 机制工作原理与实例解析
运维·服务器·网络·算力网络
Sleepy MargulisItG7 小时前
【Linux网络编程】UDP Socket
linux·网络·udp
一条懒鱼6667 小时前
k8s-网络
网络·容器·kubernetes