zoukankan      html  css  js  c++  java
  • 串口.Qt532测试(同步)

    环境:Win7x64、Qt5.3.2 MSVC OpenGL(x86)、vs2010(x86)

    ZC:这里的例子是 同步的函数操作,貌似 如果子线程在等待 WaitCommEvent(...)或ReadFile(...) 返回的话(即 串口句柄正在被使用中),界面主线程执行 CloseHandle(...) 或 SetCommMask(...) 的话,就会卡在那里...    于是 考虑改用 异步方式

      ZC:想到 一个方式,使用同步方式的时候 可以使用 强制关闭线程的方式“TerminateThread(线程句柄, ExitCode);” 来关闭子线程,这样就不会再占用 串口句柄了,CloseHandle(..)也可以顺利执行。问题:TerminateThread(...) 会有一些 动态申请的资源释放,获取的锁释放 等的问题(具体看MSDN的说明,里面还提到了"heap lock",于是在 申请内存的过程中 如果强制结束线程的话 堆锁未释放 别的线程再申请内存的时候就卡在那里了...),还有 在 XP以及之前的Windws版本OS中 强制结束线程 OS不会释放 它的初始栈,造成内存泄漏(我看了一下 XP的资源管理器,确实是这样的现象)。

    1、ZC:

     1.1、开始时,遇到的问题:在接收信息的线程中,ReadFile(...) 每次都是 立即返回的  但是获取的数据都是0字节的长度,现象就好像是 用了 异步的方式 没等到事件 就立即返回了...

      找到问题:(1)、查看了 CreateFile(...)的参数,发现使用的就是 同步的方式(没有指定 参数 FILE_FLAG_OVERLAPPED)

           (2)、后来 发现是 COMMTIMEOUTS 设置的不正确的缘故

      测试下来,有2种方式 设置COMMTIMEOUTS,来 解决上面的问题:

        ①、类似如下的参数设置:

             COMMTIMEOUTS TimeOuts;
             //设定读超时
             TimeOuts.ReadIntervalTimeout = 100;
             TimeOuts.ReadTotalTimeoutMultiplier = 5000;
             TimeOuts.ReadTotalTimeoutConstant = 5000;
             //设定写超时
             TimeOuts.WriteTotalTimeoutMultiplier = 500;
             TimeOuts.WriteTotalTimeoutConstant = 2000;

        ②、这样设置:

             COMMTIMEOUTS CommTimeOuts;
             GetCommTimeouts(hCom1, &CommTimeOuts);
             CommTimeOuts.ReadIntervalTimeout  = MAXDWORD;
             CommTimeOuts.ReadTotalTimeoutMultiplier  = 0;
             CommTimeOuts.ReadTotalTimeoutConstant  = 0;
             CommTimeOuts.WriteTotalTimeoutMultiplier  = 10;
             CommTimeOuts.WriteTotalTimeoutConstant  = 1000;

          ZC:光是这样设置的话,就会出现上面的问题,ReadFile(...) 立即返回 0字节数据。接收线程 就会 连续不断的去ReadFile(...) ...

          ZC:这样设置的话,需要 使用 “SetCommMask(hCom1, EV_RXCHAR);” 和 “DWORD dwMask = EV_RXFLAG; WaitCommEvent(g_hCom, &dwMask, NULL);”,使用 它们 就是 声明和等待EV_RXCHAR事件(该事件 意思是 只要输入缓冲区接收到数据就会触发)

          

    2、测试代码:

      2,1、main.cpp

    #include "MainWindow.h"
    #include <QApplication>
    
    extern MainWindow* g_pMainWindow;
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
    
        g_pMainWindow = &w;
        a.installNativeEventFilter(&w);// 注意,不是“a.installEventFilter(w);”,少了 "Native"
    
        return a.exec();
    }

      2.2、MainWindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QAbstractNativeEventFilter>
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow, public QAbstractNativeEventFilter
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
    public:
        virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *);
    
    private slots:
        void on_pbtnConn_clicked();
        void on_pbtnRecvMsgClear_clicked();
        void on_pbtnSendMsgClear_clicked();
        void on_pbrnSend_clicked();
    
    public:
        Ui::MainWindow *ui;
    };
    
    #endif // MAINWINDOW_H

      2.3、MainWindow.cpp

    #include "MainWindow.h"
    #include "ui_MainWindow.h"
    
    
    
    MainWindow* g_pMainWindow = NULL;
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        // https://blog.csdn.net/horizons_kong/article/details/54412339
        // https://blog.csdn.net/zmdsjtu/article/details/78539681
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    #include <QDebug>
    #include <windows.h>
    #include <stdio.h>
    #include <process.h>
    
    #include "thread_z.h"
    #include "PassInfo_z.h"
    #include "SeriesPort_z.h"
    
    QString TimeNowZ()
    {
        SYSTEMTIME sys;
        GetLocalTime( &sys );
    
        char buf[128] = {0};
        sprintf_s( buf, sizeof(buf), "%02d:%02d:%02d.%03d ", sys.wHour, sys.wMinute, sys.wSecond, sys.wMilliseconds );
    
        return QString::fromLocal8Bit(buf);
    }
    
    void ShowMsgZ(const QString& _str)
    {
        if (g_pMainWindow != NULL)
            g_pMainWindow->ui->teRecv->append(_str);
    }
    
    bool MainWindow::nativeEventFilter(const QByteArray &eventType, void *message, long *)
    {
        MSG* pMsg = reinterpret_cast<MSG*>(message);
        if(pMsg->message == WM_PASSINFO)
        {
            int iLen = pMsg->wParam;
            QString strInfo = Info_Recv(ShowMsgZ, iLen, (char*)pMsg->lParam);
            if (! strInfo.isNull())
                //ui->teRecv->append(TimeNowZ() + strInfo);
                ui->teRecv->append(strInfo);
            else
                ui->teRecv->append("
    ");
    
            return true;
        }
    
        return false;
    }
    
    void MainWindow::on_pbtnConn_clicked()
    {
        QString strChuanKouHao = ui->cbChuanKouHao->currentText();
        QString strBoTeLv = ui->cbBoTeLv->currentText();
        BYTE Parity = (BYTE)ui->cbJiaoYanWei->currentIndex();
        BYTE ShuJuWei = (BYTE)(ui->cbShuJuWei->currentIndex() + 4);
        BYTE TingZhiWei = ((BYTE)ui->cbTingZhiWei->currentIndex() + 2) * 0.5;
        bool bRtn = SPort_Init(ShowMsgZ, strChuanKouHao.toLocal8Bit().data(),
                               strBoTeLv.toULong(), Parity, ShuJuWei, TingZhiWei);
        if (! bRtn)
        {
            ui->pbtnConn->setChecked(false);
            return;
        }
    
        ShowMsgZ("After SPort_Init(...)");
        _beginthread(Thread_RECV, 0, (void*)this->winId());
        ShowMsgZ("After _beginthread(...)");
    }
    
    
    void MainWindow::on_pbtnRecvMsgClear_clicked()
    {
        ui->teRecv->clear();
        //_beginthread(Thread_RECV, 0, (void*)this->winId());
    }
    
    
    void MainWindow::on_pbtnSendMsgClear_clicked()
    {
        ui->teSend->clear();
    }
    
    void MainWindow::on_pbrnSend_clicked()
    {
    //    char pc[] = {128,129};
    //    if (IsDBCSLeadByte(pc[0]))
    //        qDebug() << "T";
    //    else
    //        qDebug() << "F";
    
        ui->teRecv->append("
    ");
    }

      2.4、PassInfo_z.h

    #ifndef PASSINFO_Z_H
    #define PASSINFO_Z_H
    
    #include <QString>
    
    #include <Windows.h>
    #define WM_PASSINFO     WM_USER+0x1000
    
    typedef void (__cdecl *TshowMsg)(const QString& _str);
    
    void Info_Send(HWND _hWnd, int _iLen, char* _pc);
    void Info_Send_pc(HWND _hWnd, char* _pc);
    QString Info_Recv(TshowMsg _funcShowMsg, int _iLen, char* _pc);
    
    #endif // PASSINFO_Z_H

      2.5、PassInfo_z.cpp

    #include "PassInfo_z.h"
    
    
    void Info_Send(HWND _hWnd, int _iLen, char* _pc)
    {
        if (_hWnd == 0)
            return;
    
        if (_iLen > 0)
        {
            char* pc = new char[_iLen];
            memcpy(&pc[0], _pc, _iLen);
    
            PostMessage( _hWnd, WM_PASSINFO, WPARAM(_iLen), LPARAM(pc) );
        }
        else
            PostMessage( _hWnd, WM_PASSINFO, WPARAM(_iLen), 0 );
    }
    
    void Info_Send_pc(HWND _hWnd, char* _pc)
    {
        Info_Send(_hWnd, strlen(_pc), _pc);
    }
    
    QString Info_Recv(TshowMsg _funcShowMsg, int _iLen, char* _pc)
    {
        // ZC: 进入到这个函数,前提是 "_iLen > 0"
        if (_iLen <= 0)
            return QString::null;
        return QString::fromLocal8Bit(_pc, _iLen);
    }
    
    
    // ZC: IsDBCSLeadByte( char ):BOOL; // ZC: 判断是否是 中文/韩文等字符的第1个字节
    //char g_infoRecv[1024 * 4] = {0};
    //int g_iInfoRecvCnt = 0;
    
    //QString Info_Recv(TshowMsg _funcShowMsg, int _iLen, char* _pc)
    //{
    //    // ZC: 进入到这个函数,前提是 "_iLen > 0"
    
    //    _funcShowMsg(QString::number(g_iInfoRecvCnt));
    
    //    if (g_iInfoRecvCnt > 0)
    //    {
    //        memcpy(&g_infoRecv[g_iInfoRecvCnt], _pc, _iLen);
    //        g_iInfoRecvCnt += _iLen;
    
    //        if (! IsDBCSLeadByte(_pc[_iLen - 1]) )// ZC: 判断是否是 中文/韩文等字符的第1个字节
    //        {
    //            QString str = QString::fromLocal8Bit(g_infoRecv, g_iInfoRecvCnt);
    //            g_iInfoRecvCnt = 0;
    //            return str;
    //        }
    //    }
    //    else
    //    {
    //        if ( IsDBCSLeadByte(_pc[_iLen - 1]) )
    //        {
    //            memcpy(&g_infoRecv[g_iInfoRecvCnt], _pc, _iLen);
    //            g_iInfoRecvCnt += _iLen;
    //        }
    //        else
    //            return QString::fromLocal8Bit(_pc, _iLen);
    //    }
    //    return QString::null;
    //}

      2.6、SeriesPort_z.h

    #ifndef SERIESPORT_Z_H
    #define SERIESPORT_Z_H
    
    #include <Windows.h>
    #include <QString>
    
    extern HANDLE g_hCom;
    
    #define SERIES_PORT__IN_QUEUE_SIZE  1024 * 16
    #define SERIES_PORT__OUT_QUEUE_SIZE 1024 * 16
    
    typedef void (__cdecl *TshowMsg)(const QString& _str);
    
    bool SPort_Init(TshowMsg _funcShowMsg,
                    char* _pcSeriesPortName, DWORD _BaudRate, BYTE _Parity, BYTE _ByteSize, BYTE _StopBits);
    
    #endif // SERIESPORT_Z_H

      2.7、SeriesPort_z.cpp

    #include "SeriesPort_z.h"
    
    #include <QDebug>
    #include <QTextCodec>
    
    #include "PassInfo_z.h"
    
    //HWND g_hWnd = 0;
    HANDLE g_hCom = 0;
    
    bool SPort_Init(TshowMsg _funcShowMsg,
                    char* _pcSeriesPortName,
                    DWORD _BaudRate, BYTE _Parity, BYTE _ByteSize, BYTE _StopBits)
    {
        g_hCom = 0;
    
        WCHAR wszSeriesPortName[8] = {0};
        MultiByteToWideChar(CP_ACP, 0, _pcSeriesPortName, strlen(_pcSeriesPortName) + 1,
                            wszSeriesPortName, sizeof(wszSeriesPortName) / sizeof(wszSeriesPortName[0]));
        HANDLE hCom1 = CreateFile(wszSeriesPortName,//COM1口
                                  GENERIC_READ | GENERIC_WRITE, //允许读和写
                                  0, //独占方式
                                  NULL,
                                  OPEN_EXISTING, //打开而不是创建
                                  0, //同步方式
                                  NULL);
        if (hCom1 == INVALID_HANDLE_VALUE)
        {
            QTextCodec *pCodec = QTextCodec::codecForName("GBK");
            QString strPrint = pCodec->toUnicode("打开COM失败 !");
            _funcShowMsg(strPrint);
            return false;
        }
        else
        {
            QTextCodec *pCodec = QTextCodec::codecForName("GBK");
            QString strPrint = pCodec->toUnicode("COM打开成功 !");
            _funcShowMsg(strPrint);
        }
    
                            //    SetupComm(hCom1, SERIES_PORT__IN_QUEUE_SIZE, SERIES_PORT__OUT_QUEUE_SIZE); //输入缓冲区和输出缓冲区的大小都是1024
    
                            //    COMMTIMEOUTS TimeOuts;
                            //    //设定读超时
                            //    TimeOuts.ReadIntervalTimeout = 100;
                            //    TimeOuts.ReadTotalTimeoutMultiplier = 5000;
                            //    TimeOuts.ReadTotalTimeoutConstant = 5000;
                            //    //设定写超时
                            //    TimeOuts.WriteTotalTimeoutMultiplier = 500;
                            //    TimeOuts.WriteTotalTimeoutConstant = 2000;
                            //    if (! SetCommTimeouts(hCom1, &TimeOuts)) //设置超时
                            //    {
                            //        int iErr = ::GetLastError();
                            //        QTextCodec *pCodec = QTextCodec::codecForName("GBK");
                            //        QString strPrint = pCodec->toUnicode("设置串口读写超时时间失败");
                            //        strPrint += ", last error code is "+QString::number(iErr);
                            //        _funcShowMsg(strPrint);
                            //        return false;
                            //    }
    
                            //    DCB dcb;
                            //    GetCommState(hCom1, &dcb);
                            //    dcb.BaudRate = _BaudRate;//9600; //波特率为9600
                            //    dcb.ByteSize = _ByteSize;//8; //每个字节有8位
                            //    dcb.Parity = _Parity;//NOPARITY; //无奇偶校验位
                            //    dcb.StopBits = _StopBits;//ONESTOPBIT; //1个停止位
                            //    if (! SetCommState(hCom1, &dcb))
                            //    {
                            //        int iErr = ::GetLastError();
                            //        QTextCodec *pCodec = QTextCodec::codecForName("GBK");
                            //        QString strPrint = pCodec->toUnicode("设置串口参数失败");
                            //        strPrint += ", last error code is "+QString::number(iErr);
                            //        _funcShowMsg(strPrint);
                            //        return false;
                            //    }
    
        _funcShowMsg( QString::number(_BaudRate)+","+QString::number(_ByteSize)
                      +","+QString::number(_Parity)+","+QString::number(_StopBits) );
    
        DCB dcb;
        if (! GetCommState(hCom1, &dcb))
        {
            int iErr = ::GetLastError();
            QTextCodec *pCodec = QTextCodec::codecForName("GBK");
            QString strPrint = pCodec->toUnicode("获取串口当前属性参数失败");
            strPrint += ", last error code is "+QString::number(iErr);
            _funcShowMsg(strPrint);
            return false;
        }
        //配置串口参数
        dcb.BaudRate  = _BaudRate;    //波特率
        dcb.fBinary  = TRUE;    //二进制模式。必须为TRUE
        dcb.ByteSize  = _ByteSize;    //数据位。范围4-8
        dcb.StopBits  = _StopBits;    //停止位
        if (_Parity  == NOPARITY)
        {
            dcb.fParity  = FALSE;    //奇偶校验。无奇偶校验
            dcb.Parity  = _Parity;    //校验模式。无奇偶校验
        }
        else
        {
            dcb.fParity  = TRUE;        //奇偶校验。
            dcb.Parity  = _Parity;    //校验模式。无奇偶校验
        }
        dcb.fOutxCtsFlow  = FALSE;    //CTS线上的硬件握手
        dcb.fOutxDsrFlow  = FALSE;    //DST线上的硬件握手
        dcb.fDtrControl  = DTR_CONTROL_ENABLE;//DTR控制
        dcb.fDsrSensitivity  = FALSE;
        dcb.fTXContinueOnXoff  = FALSE;//
        dcb.fOutX  = FALSE;            //是否使用XON/XOFF协议
        dcb.fInX  = FALSE;            //是否使用XON/XOFF协议
        dcb.fErrorChar  = FALSE;        //是否使用发送错误协议
        dcb.fNull  = FALSE;            //停用null stripping
        dcb.fRtsControl  = RTS_CONTROL_ENABLE;//
        dcb.fAbortOnError  = FALSE;    //串口发送错误,并不终止串口读写
        //设置串口参数
        if (! SetCommState(hCom1, &dcb))
        {
            int iErr = ::GetLastError();
            QTextCodec *pCodec = QTextCodec::codecForName("GBK");
            QString strPrint = pCodec->toUnicode("设置串口参数失败");
            strPrint += ", last error code is "+QString::number(iErr);
            _funcShowMsg(strPrint);
            return false;
        }
    
        //设置串口事件
        SetCommMask(hCom1, EV_RXCHAR);//在缓存中有字符时产生事件
    
        SetupComm(hCom1, SERIES_PORT__IN_QUEUE_SIZE, SERIES_PORT__OUT_QUEUE_SIZE);
    
        //设置串口读写时间
        COMMTIMEOUTS CommTimeOuts;
        GetCommTimeouts(hCom1, &CommTimeOuts);
        CommTimeOuts.ReadIntervalTimeout  = MAXDWORD;
        CommTimeOuts.ReadTotalTimeoutMultiplier  = 0;
        CommTimeOuts.ReadTotalTimeoutConstant  = 0;
        CommTimeOuts.WriteTotalTimeoutMultiplier  = 10;
        CommTimeOuts.WriteTotalTimeoutConstant  = 1000;
        if (!SetCommTimeouts(hCom1, &CommTimeOuts))
        {
            int iErr = ::GetLastError();
            QTextCodec *pCodec = QTextCodec::codecForName("GBK");
            QString strPrint = pCodec->toUnicode("设置串口读写超时时间失败");
            strPrint += ", last error code is "+QString::number(iErr);
            _funcShowMsg(strPrint);
            return false;
        }
    
        g_hCom = hCom1;
        return true;
    }
    
    bool SendData(TshowMsg _funcShowMsg, HANDLE _hComm, char* data, int len)
    {
        if (_hComm == INVALID_HANDLE_VALUE)
        {
            QTextCodec *pCodec = QTextCodec::codecForName("GBK");
            QString strPrint = pCodec->toUnicode("串口未打开");
            _funcShowMsg(strPrint);
            return false;
        }
        //清空串口
        PurgeComm(_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR);
        //写串口
        DWORD dwWrite  = 0;
        DWORD dwRet  = WriteFile(_hComm, data, len, &dwWrite, NULL);
        int iErr = 0;
        if (! dwRet) { iErr = ::GetLastError(); }
        //清空串口
        PurgeComm(_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR);
        if (! dwRet)
        {
            QTextCodec *pCodec = QTextCodec::codecForName("GBK");
            QString strPrint = pCodec->toUnicode("发送数据失败");
            strPrint += ", last error code is "+QString::number(iErr);
            _funcShowMsg(strPrint);
            return false;
        }
        return true;
    }

      2.8、thread_z.h

    #ifndef THREAD_Z_H
    #define THREAD_Z_H
    
    void Thread_RECV(void *_ArgList);
    
    #endif // THREAD_Z_H

      2.9、thread_z.cpp

    #include "thread_z.h"
    
    #include <QDebug>
    
    #include <Windows.h>
    #include <process.h>
    
    #include "PassInfo_z.h"
    #include "SeriesPort_z.h"
    
    int g_iIdx = 0;
    bool MsgHandler01(HWND _hWnd, DWORD _dwRecv, char* _pc);
    
    void Thread_RECV(void *_ArgList)
    {
    //    ::MessageBoxA(0, "Thread_RECV(...) in ", "", 0);
    
        HWND hWnd = (HWND)_ArgList;
        if (hWnd == 0)
        {
            qDebug() << "Thread_RECV(...) - hWnd is NULL .";
            _endthread();
            return;
        }
        if (g_hCom == 0)
        {
            Info_Send_pc(hWnd, "Thread_RECV(...) - g_hCom is 0 .");
            _endthread();
            return;
        }
    
        Info_Send_pc(hWnd, "Thread_RECV(...) in");
        qDebug() << "Thread_RECV(...) in";
    
        //清空串口
        PurgeComm(g_hCom, PURGE_RXCLEAR | PURGE_TXCLEAR);
    
        char buf[SERIES_PORT__OUT_QUEUE_SIZE] = {0};
        char bufErr[256] = {0};
        while (true)
        {
    //        g_iIdx ++;
    //        if (g_iIdx > 10)
    //            break;
    
            BOOL bRtn = false;
    
            DWORD dwMask = EV_RXFLAG;//EV_RXCHAR;
            bRtn = WaitCommEvent(g_hCom, &dwMask, NULL);
            if (! bRtn)
            {
                int iErr = ::GetLastError();
                sprintf_s(bufErr, sizeof(bufErr), "WaitCommEvent(...) return false, last error code is %d .", iErr);
                Info_Send_pc(hWnd, bufErr);
                break;
            }
    
            DWORD dwRead;
            bRtn = ReadFile(g_hCom, &buf[0], SERIES_PORT__OUT_QUEUE_SIZE, &dwRead, NULL);
    //                {
    //                    char msg[128] = {0};
    //                    sprintf_s(msg, sizeof(msg), "%d - %d", g_iIdx, dwRead);
    //                    Info_Send_pc(hWnd, msg);
    //                }
            if (! bRtn)
            {
                int iErr = ::GetLastError();
                sprintf_s(bufErr, sizeof(bufErr), "ReadFile(...) return false, last error code is %d .", iErr);
                Info_Send_pc(hWnd, bufErr);
                break;
            }
    
            if (dwRead > 0)
                if (! MsgHandler01(hWnd, dwRead, buf))
                    break;
        }
    
        Info_Send_pc(hWnd, "Thread_RECV(...) out");
        qDebug() << "Thread_RECV(...) out";
    
        /* _endthread given to terminate */
        _endthread();
    }
    
    // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
    
    char g_infoRecv[1024 * 4] = {0};
    DWORD g_dwInfoRecvCnt = 0;
    
    bool MsgHandler01(HWND _hWnd, DWORD _dwRecv, char* _pc)
    {
        //char buf1[64] = {0};
    
    
        memcpy(&g_infoRecv[g_dwInfoRecvCnt], _pc, _dwRecv);
        g_dwInfoRecvCnt += _dwRecv;
    
        //Info_Send_pc(_hWnd, "11");
        void* p = memchr(&g_infoRecv[0], '
    ', g_dwInfoRecvCnt);
        if (p != NULL)
        {
            //Info_Send_pc(_hWnd, "12");
            DWORD dwBegin = (DWORD)( &g_infoRecv[0] );
            DWORD dwPos = (DWORD)p;
            int iLen = dwPos - dwBegin - 1;// 
     为占2个字节位置,需要将它们占的位置去掉
            //Info_Send_pc(_hWnd, "13");
            if (iLen < 0)
            {
                char bufErr[64] = {0};
                sprintf_s(bufErr, sizeof(bufErr), "MsgHandler01(...) - (dwLen < 0) : %d", iLen);
                Info_Send_pc(_hWnd, bufErr);
                return false;
            }
    
            //sprintf_s(buf1, sizeof(buf1), "14 : %d, %d, %d, %d", iLen, g_dwInfoRecvCnt, dwBegin, dwPos);
            //Info_Send_pc(_hWnd, buf1);
            Info_Send(_hWnd, iLen, &g_infoRecv[0]);
            //Info_Send_pc(_hWnd, "15");
            memcpy( &g_infoRecv[0], &g_infoRecv[iLen + 2], g_dwInfoRecvCnt - (iLen+2) );
            //Info_Send_pc(_hWnd, "16");
            g_dwInfoRecvCnt -= (iLen+2);
            //Info_Send_pc(_hWnd, "17");
        }
        return true;
    }

    3、

    4、

    5、

  • 相关阅读:
    git添加文件的原理流程
    maven复制包error
    一行代码-Js简单消息弹框
    WEB-给自己所有的域名加上HTTPS
    记录-配置文件-将网站协议从 HTTP 升级为 HTTPS (基于 Nginx 配置)
    记录-Mac终端自动补全的配置(解决不能输入大写T的问题)
    记录-Navicat连接MySQL8.0出现2059错误
    记录-MySQL 修改ROOT密码
    记录-Maven的安装与配置
    简单使用TensorFlow.js在浏览器进行视频实时目标识别(基于YOLO V3)
  • 原文地址:https://www.cnblogs.com/cppskill/p/9723688.html
Copyright © 2011-2022 走看看