网站菜单

C++开发——FTP传输模块(带断线重连)

index为FTP功能模块,controlthread控制连接状态,断线重连,使用的QThread。

index.cpp

#include "index.h"
#include "mainwindow.h"
#include "controlthread.h"
#include <QBuffer>
#include <string>
#include <sys/time.h>


//获取buffer
extern BYTE                    *g_readBuf;
extern unsigned char           * g_pRgbBuffer;
extern Width_Height            g_W_H_INFO;

extern struct timeval          t1, t2;             //计时器起点
extern QString                 value_freq;         //传输间隔
extern int                     failCount;

//构造函数
Index::Index()
{
    this->pCommon = new Common;

    if(!this->initSocketLib()){
        this->error(this->errorMsg);
        exit(-1);
    }
}
//析构函数
Index::~Index()
{
    closesocket(this->ctrlSock);
    closesocket(this->dataConnSock);
    closesocket(this->dataTransSock);
    WSACleanup();
}
//程序开始
void Index::appStart()
{
    cout << endl << "欢迎使用sindftp! (本软件出自www.sindsun.com)" <<endl << endl;

    if(!this->login()){
        this->error(this->errorMsg);
        cout << "error code is " << replyCode << endl;
        Sleep(3000);
        system("cls");
        this->appStart();
    }
    this->menuList();
}
//登录
bool Index::login()
{
    this->ctrlSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(this->ctrlSock == static_cast<unsigned>(SOCKET_ERROR)){
        this->error("创建socket失败");
        exit(-1);
    }

    sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(static_cast<unsigned short>(this->portNum));
    addr.sin_addr.s_addr = inet_addr(this->hostName.c_str());
    int connStatus = connect(this->ctrlSock, reinterpret_cast<sockaddr *>(&addr), sizeof (addr));
    if(connStatus == -1){
        this->errorMsg = "连接服务器失败";
        return false;
    }
    if(!this->recvFromRemote() || this->replyCode != 220){
        this->errorMsg = "连接服务器错误";
        return false;
    }

    //进入登录
    this->requestString = "USER " + this->userName;
    if(!sendToRemote(true) || this->replyCode != 331){
        this->errorMsg = "用户名错误";
        return false;
    }
    this->requestString = "PASS " + this->userPwd;
    if(!sendToRemote(true) || this->replyCode != 230){
        this->errorMsg = "用户名或密码错误";
        return false;
    }

    return true;
}
//菜单列表
void Index::menuList()
{
    cout << "----------- sindftp ------------" << endl << endl;
    cout << "--------------------------------" << endl << endl;
    cout << "显示菜单\t menu" << endl << endl;
    cout << "切换目录\t cwd dirname" << endl << endl;
    cout << "文件列表\t list dirname" << endl << endl;
    //cout << "文件重命名\t rename filename" << endl << endl;
    cout << "上传文件\t upload filename" << endl << endl;
    cout << "下载文件\t download filename" << endl << endl;
    cout << "删除文件\t del filename" << endl << endl;
    cout << "帮助信息\t help" << endl << endl;
    cout << "清除屏幕\t clear" << endl << endl;
    cout << "退出平台\t quit" << endl << endl;
    cout << "--------------------------------" << endl;
    cout << endl;

    localInput();
}
//本地命令输入处理
void Index::localInput()
{
    requestString = "";
    responseString = "";
    errorMsg = "";

    string userInputCmd = "";
    cout << endl;
    cout << "input cmd ### " ;
    cin.sync();
    getline(cin, userInputCmd);

    if(userInputCmd.length() < 1){
        errorMsg = "请输入正确的命令!";
        localInput();
        return;
    }
    //分割命令与参数
    string cmd = "";
    string param = "";
    bool cmdOver = false;
    for(char ch:userInputCmd){
        if(ch == ' '){
            cmdOver = true;
            continue;
        }

        if(cmdOver){
            param += ch;
        }else{
            cmd += ch;
        }
    }
    //处理命令
    if(cmd == "help"){  //帮助
        requestString = "HELP";
        sendToRemote(true);
    }else if(cmd == "menu"){  //菜单
        menuList();
    }else if(cmd == "cwd"){  //改变目录
        //改变数据目录
        requestString = "CWD "+param;
        sendToRemote(true);
    }else if(cmd == "list"){  //列表
        getList(param);
    }else if(cmd == "rename"){  // 重命名

    }else if(cmd == "upload"){  //上传
        uploadFile(param);
    }else if(cmd == "download"){  //下载
        downloadFile(param);
    }else if(cmd == "del"){  //删除
        deleteFile(param);
    }else if(cmd == "clear"){  //清除屏幕
        system("cls");
        menuList();
    }else if(cmd == "quit"){  //退出
        cout << "Bye bye!" <<endl;
        exit(-1);
    }else{
        //errorMsg = "请输入正确的命令!";
        //error(errorMsg);
        requestString = userInputCmd;
        sendToRemote(true);
    }

    localInput();
}
//远程命令发送
bool Index::sendToRemote(bool returnReplyCode)
{
    if(this->requestString.length() < 1){
        this->errorMsg = "ftp命令不能为空";
        return false;
    }
    cout << endl << setw(10) << "发送命令: " << setw(10) << requestString << endl;

    requestString += "\r\n";
    requestString = this->pCommon->gbkToUtf8(requestString.c_str());
    unsigned int cmdLength = requestString.length();
    char *tmpCmdStr = new char[cmdLength];
    memset(tmpCmdStr, 0, cmdLength);
    memcpy(tmpCmdStr, requestString.c_str(), cmdLength);

    int sendStatus = send(this->ctrlSock, tmpCmdStr, static_cast<int>(cmdLength), 0);
    delete [] tmpCmdStr;
    if(sendStatus == -1){
        this->errorMsg = "请求失败";
        return false;
    }
    if(returnReplyCode){
        return recvFromRemote();
    }
    return true;
}
//接收远程响应
bool Index::recvFromRemote()
{
    if(this->ctrlSock == INVALID_SOCKET){
        this->errorMsg = "服务已断开 ";
        return false;
    }
    char buf[MAX_MSG_SIZE];
    int recvStatus = -1;
    responseString = "";

    while(true){
        memset(buf, 0, MAX_MSG_SIZE);

        recvStatus = recv(this->ctrlSock, buf, MAX_MSG_SIZE, MSG_PARTIAL);
        //cout << "######### " << buf << endl;
        if(recvStatus > 0){
            responseString = buf;
//            ofstream myfile("recvFromRemote.txt", ios::app);
//            myfile << responseString << '=' << recvStatus<< '=' <<'\n';
//            myfile << buf<< '\n';
//            myfile.close();
            break;
        }
        Sleep(50);
    }
    if(responseString.length() == 0){
        this->errorMsg = "接收数据失败";
        return false;
    }
    this->success(responseString);

    return this->getReplyCode();
}
//处理远程响应,返回响应码
bool Index::getReplyCode()
{
    string tmpMsg = "";
    tmpMsg = responseString.substr(0, 3);
    char charCode[4] = {};

    memcpy(charCode, tmpMsg.c_str(), tmpMsg.length());
    charCode[3] = '\0';
    this->replyCode = static_cast<unsigned int>(atoi(charCode));
//    ofstream myfile("replyCode.txt", ios::app);
//    myfile << responseString<<'\n';
//    myfile << tmpMsg<< '\n';
//    myfile << charCode<< '\n';

//    myfile << replyCode << ' ' << tmpMsg.length() << '\n';

    if( !(this->replyCode >= 1 && this->replyCode <= 1000)){
        this->errorMsg = "getReplyCode"; //"无法获取到响应码";
//        myfile <<"getReplyCode ErrorCode " <<replyCode << '\n';
//        myfile.close();
        return false;
    }
//    myfile.close();
    return true;
}
//写日志文件
bool Index::writeLogs(string msg)
{
    if(msg.length() == 0){
        return false;
    }
    SYSTEMTIME sTime;
    GetLocalTime(&sTime);
    char fullTime[20];
    memset(fullTime, 0, 20);
    sprintf(fullTime, "%4d-%02d-%02d %02d:%02d:%02d", sTime.wYear, sTime.wMonth, sTime.wDay,
            sTime.wHour, sTime.wMinute, sTime.wSecond);
    msg = "\r\n" + msg;
    msg = fullTime + msg;

    fstream fs;
    fs.open("c:/tools/datasock_recv_logs.log", ios::app);

    fs << msg << endl;

    fs.close();

    return true;
}
//显示错误
void Index::error(string errorStr)
{
    if(errorStr.length() > 0){
        cout << endl;
        cout << "Error: " << errorStr;
        cout << endl;
    }
}
//显示成功
void Index::success(string sucStr)
{
    if(sucStr.length() > 0){
        cout << endl;
        cout << "服务响应:" << endl;
        cout << sucStr;
        cout << endl;
    }
}
//按值选择数据传输模式
bool Index::transModelSelect()
{
    if(transModeVal == TransMode::PORT){
        return portMode();
    }else if(transModeVal == TransMode::PASV){
        return pasvMode();
    }else{
        return (pasvMode() || portMode());
    }
}
//PORT主动传输模式
bool Index::portMode()
{
    dataConnSock = socket(AF_INET, SOCK_STREAM, 0);
    if(dataConnSock == static_cast<unsigned>(SOCKET_ERROR)){
        errorMsg = "初始化数据socket失败";
        return false;
    }

    portDataConnCount += 1;

    sockaddr_in addr;
    int addrLength = sizeof (addr);
    int getsocknameStatus = getsockname(ctrlSock, reinterpret_cast<sockaddr *>(&addr), &addrLength);
    if(getsocknameStatus == -1){
        errorMsg = "获取socket信息失败";
        return false;
    }
    int localPort = ntohs(addr.sin_port) + portDataConnCount;   //获取机地随机端口+1

    addr.sin_family = AF_INET;
    addr.sin_port = htons(static_cast<u_short>(localPort));
    //addr.sin_addr.s_addr = htonl(INADDR_ANY);

    int countBind = 0;
    int bindStatus = -1;
    while(bindStatus != 0){
        bindStatus = bind(dataConnSock, reinterpret_cast<sockaddr *>(&addr), sizeof (addr));
        countBind ++;
        if(countBind >= 10){
            break;
        }
    }
    if(bindStatus == -1){
        errorMsg = "绑定失败";
        return false;
    }

    //主动模式下的监听一下要放到发送了请求数据命令之后
    int listenStatus = listen(dataConnSock, 64);
    if(listenStatus == -1){
        errorMsg = "监听失败";
        return false;
    }

    char *ipAddr = new char[32];
    memset(ipAddr, 0, 32);
    ipAddr = inet_ntoa(addr.sin_addr);

    //计算端口号
    int port1 = localPort/256;
    int port2 = localPort%256;

    if(portDataConnCount == 5000)
    {
        portDataConnCount = 0;
    }

    char charPortNum1[5];
    char *portNum1 = itoa(port1, charPortNum1, 10);
    char charPortNum2[5];
    char *portNum2 = itoa(port2, charPortNum2, 10);

    string portModelStr = ipAddr;
    portModelStr += ",";
    portModelStr += portNum1;
    portModelStr += ",";
    portModelStr += portNum2;
    //替换里面的特殊字符
    for(char &c:portModelStr){
        if(c == '.'){
            c = ',';
        }
    }
    requestString = "PORT " + portModelStr;
    if(!sendToRemote(true)){
        errorMsg = "发送port命令失败";
        ofstream myfile("portError.txt", ios::app);
        myfile << errorMsg << endl;
        myfile.close();
        return false;
    }

    transModeVal = TransMode::PORT;

    success("PORT模式开启成功");

    return true;
}
//允许远程连接本机
bool Index::allowAccept()
{
    if(transModeVal != TransMode::PORT){
        return true;
    }
    sockaddr_in acceptAddr;
    int acceptAddrLength = sizeof (acceptAddr);
    dataTransSock = accept(dataConnSock, reinterpret_cast<sockaddr *>(&acceptAddr), &acceptAddrLength);
    if(dataTransSock == static_cast<u_short>(INVALID_SOCKET)){
        errorMsg = "接受请求失败";
        return false;
    }
    return true;
}
//PASV连接模式
bool Index::pasvMode()
{
    dataTransSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(dataTransSock == static_cast<u_short>(SOCKET_ERROR)){
        errorMsg = "PASV socket初始化失败";
        return false;
    }
    requestString = "PASV";
    if(!sendToRemote(true) || replyCode != 227){
        errorMsg = "PASV设置失败";
        return false;
    }
    //处理字符串
    char *newChar = strrchr(responseString.c_str(), '(') + 1;
    string tmpStr = newChar + 1;
    int spCount = 0;
    string p1 = "";
    string p2 = "";
    for(char ch:tmpStr){
        if(ch == ')'){
            break;
        }
        if(ch == ','){
            spCount ++;
            continue;
        }
        if(spCount > 3){
            if(spCount == 4){
                p1 += ch;
            }else{
                p2 += ch;
            }
        }
    }
    int dataPort = atoi(p1.c_str()) * 256 + atoi(p2.c_str());
    cout << "p1 " << p1 << endl;
    cout << "p2 " << p2 << endl;
    cout << "port " << dataPort << endl;
    sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(static_cast<u_short>(dataPort));
    addr.sin_addr.s_addr = inet_addr(hostName.c_str());
    int ret = connect(dataTransSock, reinterpret_cast<sockaddr *>(&addr), sizeof (addr));
    if(ret == -1){
        errorMsg = "PASV连接服务器失败";
        error(errorMsg);
        closesocket(dataTransSock);
        return false;
    }

    transModeVal = TransMode::PASV;

    success("PASV模式开启成功");

    return true;
}
//获取文件列表
bool Index::getList(string dirPath)
{
    if(!transModelSelect()){
        error(errorMsg);
        return false;
    }
    requestString = "LIST "+dirPath;
    if(!sendToRemote(true) || replyCode != 150 ){
        error(errorMsg);
        return false;
    }

//    if(!allowAccept()){
//        error(errorMsg);
//        return false;
//    }

    char *recvData = new char[MAX_MSG_SIZE];
    memset(recvData, 0 , MAX_MSG_SIZE);
    //如果是150,需要再接收一次数据发送结束的通知
    int recvStatus = recv(dataTransSock, recvData, MAX_MSG_SIZE, 0);
    if(recvStatus == -1){
        error("接收数据失败");
        return false;
    }

    success(pCommon->utf8ToGbk(recvData));
    writeLogs(recvData);
    success("写入日志文件成功");
    delete [] recvData;


    return true;
}
//上传文件
bool Index::uploadFile(string filePath)
{
    if(!transModelSelect()){
        return false;
    }
    char *fileName = strrchr(filePath.c_str(), '/');
    requestString = "STOR ";
    requestString += fileName +1;
    if(!sendToRemote(true)){
        errorMsg = "命令发送失败";
        return false;
    }
    if(!allowAccept()){
        return false;
    }

    fstream fs;
    fs.open(filePath, ios::in);
    if(!fs.is_open())
    {
        return false;
    }
    char buf[MAX_MSG_SIZE];
    memset(buf, 0, sizeof(MAX_MSG_SIZE));
    bool status = true;
    while(!fs.eof()){
        fs.read(buf, MAX_MSG_SIZE);
        int storStatus = send(dataTransSock, buf, sizeof (buf), 0);
        if(storStatus == -1){
            errorMsg = "上传文件异常";
            status = false;
            break;
        }
    }
    //closesocket(dataTransSock);
    if(!status){
        return false;
    }

    return true;
}

//上传Buffer
bool Index::uploadBuffer(QImage image)
{
    //设置传输buffer
    QByteArray data;
    QBuffer buffer(&data);
    buffer.open(QIODevice::WriteOnly);
    image.save(&buffer, "BMP");

    if(!transModelSelect()){
        errorMsg = "transModelSelect";
        return false;
    }

    //设置写入命令
    string filePath = "./result.BMP";
    char *fileName = strrchr(filePath.c_str(), '/');
    requestString = "STOR ";
    requestString += fileName +1;
    if(!sendToRemote(true)){
        errorMsg = "命令发送失败";
        ofstream myfile("sendToRemote.txt", ios::app);
        myfile << errorMsg <<  endl;
        myfile.close();
        return false;
    }

    if(!allowAccept()){
        errorMsg = "allowAccept";
        ofstream myfile("allowAccept.txt", ios::app);
        myfile << errorMsg <<  endl;
        myfile.close();
        return false;
    }

    if(transModeVal == TransMode::PORT)
    {
        //开启等待回复
        int on = 0;
        setsockopt(dataTransSock, IPPROTO_TCP, TCP_NODELAY, (char *)&on, sizeof(int));
//        //关闭缓冲区
//        int nZero=1;
//        setsockopt(dataTransSock, SOL_SOCKET, SO_SNDBUF, (char *)&nZero,sizeof(nZero));
//        //设置超时时间
//        int timeout = 2 * 1000;
//        setsockopt(dataTransSock, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(int));
//        setsockopt(dataTransSock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(int));
    }

    //看看哪里出了问题
    int err;
    int len = sizeof(int);
    int nOpt = getsockopt(dataTransSock, SOL_SOCKET, SOCKET_ERROR, (char*)err, &len);
    if(0 && nOpt == SOCKET_ERROR)
    {
        int nErrorCode = WSAGetLastError();

        ofstream myfile("socketError.txt", ios::app);
        myfile << nErrorCode <<  ' ' << dataTransSock << ' ' << ctrlSock;
        myfile << " \n";
        myfile.close();

        switch(nErrorCode)
        {
            case WSAEINTR:
            case WSAEINPROGRESS:
            case WSAEWOULDBLOCK:
            //一般错误,不处理
            break;

            default:
            //接收错误,关闭Socket

            break;
        }
        errorMsg = "getsockopt";
        return false;
    }

    //传输数据
    int uploadStatus = send(dataTransSock, data.data(), data.size(), 0);

    //重置计时器起点
    gettimeofday(&t1, NULL);
    failCount = 0;

    //设置间隔,默认16帧
    if(value_freq.isEmpty() || value_freq.isNull() || value_freq == 0)
    {
        Sleep(65);
    }
    else
    {
        Sleep(int(1000 / value_freq.toInt()));
    }



    if(uploadStatus == -1)
    {
        int nErrorCode = WSAGetLastError();
        ofstream myfile("transmitionError.txt", ios::app);
        myfile << uploadStatus << ' ' << nErrorCode << '\n';
        myfile.close();

        myfile << "11111";
        myfile.close();
        return false;
    }

//    //测速
//    gettimeofday(&t2, NULL);
//    timeuse = (t2.tv_sec - t1.tv_sec) + (double)(t2.tv_usec - t1.tv_usec)/1000000.0;

//    ofstream myfile("delay.txt", ios::app);
//    myfile << timeuse;
//    myfile << "   ";
//    myfile.close();

    closesocket(dataTransSock);
    closesocket(dataConnSock);
    return true;
}

//下载文件
bool Index::downloadFile(string fileName)
{
    //先获取文件大小
    requestString = "SIZE ";
    requestString += fileName;
    if(!sendToRemote(true)){
        errorMsg = "命令发送失败";
        return false;
    }
    int fileSize = atoi(responseString.substr(4).c_str());

    if(!transModelSelect()){
        return false;
    }
    requestString = "RETR " + fileName;
    if(!sendToRemote(true)){
        errorMsg = "命令发送失败";
        return false;
    }
    if(!allowAccept()){
        errorMsg = "连接失败";
        return false;
    }
    //开始进行下载动作
    string localPath = "d:/test/d_" + fileName;
    fstream fs;
    fs.open(localPath, ios::app);
    int countFileSize = 0;
    char *buf = new char[MAX_MSG_SIZE];
    while (countFileSize < fileSize) {
        memset(buf, 0, MAX_MSG_SIZE);
        recv(dataTransSock, buf, MAX_MSG_SIZE, 0);
        if(strlen(buf) < 1){
            break;
        }
        fs << buf ;
        countFileSize += strlen(buf);
    }
    fs.close();

    return true;
}
//删除文件
bool Index::deleteFile(string fileName)
{
    if(!transModelSelect()){
        return false;
    }
    requestString = "DELE " + fileName;
    if(!sendToRemote(true)){
        errorMsg = "命令发送失败";
        return false;
    }


    return true;
}
//网络组件初始化
bool Index::initSocketLib()
{
    WSADATA wsa;
    WORD vCode = MAKEWORD(2, 2);
    int wsaStartupStatus = WSAStartup(vCode, &wsa);

    if(wsaStartupStatus == -1){
        this->errorMsg = "初始化套接字库失败,请重试";
        return false;
    }
   //检查套接字版本号
   if(LOBYTE(wsa.wVersion) != 2 || HIBYTE(wsa.wHighVersion) != 2){
       WSACleanup();
       this->errorMsg = "套接字版本号不符合,请重新配置";
       return false;
   }
   return true;
}

index.h

#ifndef INDEX_H
#define INDEX_H

#include <iostream>
#include <string>
#include <winsock2.h>
#include <fstream>
#include <windows.h>
#include <iomanip>
#include <locale>
#include <QBuffer>
#include <QRgb>

#include "common.h"

using namespace std;

#define MAX_MSG_SIZE 1024


class Index{
public:
    Index();
    ~Index();
    //程序开始
    void appStart();
public:
    Common *pCommon;

    enum TransMode{
        AUTO, PORT, PASV
    };

    //主机名
    string hostName = "";
    //端口号
    int portNum = 0;
    //用户名
    string userName = "";
    //密码
    string userPwd = "";


    //操作命令socket
    SOCKET ctrlSock;
    //数据连接socket
    SOCKET dataConnSock;
    //数据传输socket
    SOCKET dataTransSock;


    //命令字符串
    string requestString = "";
    //接收的响应字符串
    string responseString = "";
    //响应码
    unsigned int replyCode = 0;
    //主动模式端口号计数
    int portDataConnCount = 0;
    //错误消息
    string errorMsg = "";
    //选择的连接模式
    TransMode transModeVal = TransMode::PORT;

    //网络组件初始化
    bool initSocketLib();
    //登录
    bool login();
    //退出登录
    bool logout();
    //菜单列表
    void menuList();
    //本地命令输入处理
    void localInput();
    //远程命令发送
    bool sendToRemote(bool returnReplyCode=false);
    //接收远程响应
    bool recvFromRemote();
    //处理远程响应,返回响应码
    bool getReplyCode();
    //写日志文件
    bool writeLogs(string msg);
    //显示错误
    void error(string errorStr);
    //显示成功
    void success(string sucStr);
    //按值选择数据传输模式
    bool transModelSelect();
    //PORT主动传输模式
    bool portMode();
    //允许远程连接本机
    bool allowAccept();
    //PASV连接模式
    bool pasvMode();
    //ftp参数初始化设置
    bool initFtpParam();

    //获取文件列表
    bool getList(string dirPath);
    //编辑名称
    bool setRename(string fileName);
    //上传文件
    bool uploadFile(string filePath);
    //上传QImage
    bool uploadBuffer(QImage image);
    //下载文件
    bool downloadFile(string fileName);
    //删除文件
    bool deleteFile(string fileName);

};

#endif // INDEX_H

controlthread.cpp

#include "controlthread.h"
#include "mainwindow.h"
#include "index.h"
#include <QDebug>
#include <sys/time.h>
#include <stdio.h>
#include <iostream>
#include <fstream>

extern bool             startCounting;
extern UploadThread     *m_thread2;
struct timeval          t1, t2;                 //global
extern bool             counterThreadSwitch;
double                  timeuse;
int                     failCount;

using namespace std;

ControlThread::ControlThread(QObject *parent) : QThread(parent)
{

}

void ControlThread::run()
{
    //测速起点
    gettimeofday(&t1, NULL);

    forever
    {
        if(startCounting && counterThreadSwitch)
        {
            countDown();
        }
        else if(!startCounting && counterThreadSwitch)
        {
            startCounting = true;
            failCount = 0;
            gettimeofday(&t1, NULL);
            m_thread2->start();
        }
        else if(!counterThreadSwitch)
        {
            break;
        }
    }
}

void ControlThread::countDown()
{
    //测速终点
    gettimeofday(&t2, NULL);
    timeuse = (t2.tv_sec - t1.tv_sec) + (double)(t2.tv_usec - t1.tv_usec)/1000000.0;

//    ofstream myfile("countDown.txt", ios::app);
//    myfile << "good"  << " " << timeuse<< '\n';
//    myfile.close();

    if(timeuse > 5)
    {

        //连续超时2次以后判定为失败
        failCount += 1;
        gettimeofday(&t1, NULL);

        if(failCount == 2)
        {
            m_thread2->terminate();

            while(m_thread2->isRunning())
            {
                Sleep(50);
            }

            startCounting = false;

            ofstream myfile("countDownTimeout.txt", ios::app);
            myfile << "bad" << " "<< timeuse << '\n';
            myfile.close();
        }

    }
}

controlthread.h

#ifndef CONTROLTHREAD_H
#define CONTROLTHREAD_H

#include <QObject>
#include <QDebug>
#include <QThread>

class ControlThread : public QThread
{
    Q_OBJECT
public:
    explicit ControlThread(QObject *parent = 0);

public:
    void run();
    void countDown();

signals:

private:


public slots:

};

#endif // CONTROLTHREAD_H

参考:

Sindsun

http://www.sindsun.com
显示评论 (0)

文章评论

相关推荐

Yolov5_Seg输出解析

通过矩阵乘法(在代码中称为“matmul”)来计算分割掩码的原因,主要与实例分割网络(例如 YOLOv5 Segmentation)的实现方式有关。这种方法实际上是一种高效的特征图与目标分割系数组合的…

Ubuntu交叉编译Python

在 Ubuntu 上交叉编译 Python 的流程通常用于为不同平台生成可执行文件(如 ARM、MIPS 等)。以下是一般的操作步骤: 1. 安装必要的依赖工具 首先,确保已经安装了编译所需的工具和依…