C++

Vscode mingw下opencv及多线程C++socket

2019-05-12  本文已影响2人  applecai
目的:由于vslam都是用c++开发的,所以要多练习c++11,所以就自己设计项目来练手
立项:(适用于0.1版本)
名称:Display
功能:一个client将数据集中的png图片读取,通过tcp socket协议传输给server端显示。
其中特殊控制功能包括如下:
        Server端的按键s是控制socket传输数据的开关,
        按键j是控制是否将当前传输的图片数据实时显示的开关。
工具链:coding用Vscode,编译用CMake+MinGw8.1(环境搭建可以参考我之前的文章)
数据集:在client端是读取png的数据集

工程共享路径: https://github.com/AppleCai/Display

一,0.1版基本设计说明:

1.1 Server端:

1.1 Server端:
    1.1.1主进程下有2个线程—一个是key按键扫描
         另一个是server的socket通信传输数据及imshow显示图片。
    1.1.2添加了锁,用于按钮s键暂停socket传输的功能,此时会挂起server线程。
         当再次按s键后,在key线程中可以触发server线程唤醒。
    1.1.3由于有特殊控制功能,所以添加了策略模式的设计。
         可以选择不同的控制显示的方式。
1.2 client端:
    用作配合server的测试code,忽略设计。

二,后续更新版本说明:

2.1优化client和server间的通信协议。添加crc校验及各类出错处理。
2.2 Socket添加心跳包监控及重连接尝试。
2.3 HMI显示和socket传输分离为2个线程。
2.4 HMI图片显示添加ROI区域显示张数及叠加特质logo。
2.5 添加对图片的监视作用,添加弹窗报警及logDTC记录。(目的是使用进程间通信D-bus和共享内存)
2.6 Server端切换到linux上。
2.7 添加守护进程。
2.8 进行性能测试,进行优化。

三,0.1版设计图(详见Design文件夹中的word说明文档)

3.1 server端的3个对象关于按键的控制说明

按键时序说明.png

3.2 socket通信数据的应用协议说明

socket数据协议.png

3.3 server端的类图

类图.png

四,运行效果图

运行效果.png

五,代码片段

server.hpp文件

    #ifndef SERVER_HPP
    #define SERVER_HPP
    #include "key.hpp"
    #include "head.hpp"
    
    #define BUFFER_SIZE 1024
    
    /* socket通信基类 */
    class baseServer
    {
    public:
      enum status
      {
        E_OK = 0,
        E_NOK = -1
      };
      baseServer();
      ~baseServer(){};
      int socketCreate(int type, int way, int ip, int port);
      int socketBind(void);
      int socketListen(int num);
      int socketAccept(void);
      //virtua void socketDataHandler(void);
      virtual void socketDataHandler() = 0;
      int socketDisconnect(void);
      int socketCloseServer(void);
      int getConnectfd(void);
    
    private:
      int serverfd, connectfd;
      struct sockaddr_in serveraddr;
    };
    
    /* socket通信继承类 */
    class ServerEx : public baseServer
    {
    public:
      ServerEx();
      ~ServerEx(){};
      void socketDataHandler();
      void ReceiveFrame();
      void DisplayFrame();
      void HMIControlStrategy(char cmd);
      cv::Mat &GetImg();
      void server();
    
    private:
      struct _Msg
      {
        int length = 0;
        unsigned char cokstart[1] = {0};
        unsigned char buffer[BUFFER_SIZE];
      } Msg;
      std::vector<uchar> vec;
      cv::Mat img_decode;
    };
    
    /* 策略模式:用于按键对HMI显示的控制策略 */
    class myLock;
    class HMICtrl
    {
    public:
      HMICtrl() : _en(TRUE){};
      ~HMICtrl(){};
      void transmitCtrl();
      void transmitCtrlCfg(bool en);
      bool getTransmitCtrlCfg();
      void FrameTerminal();
      virtual void ActionInterface() = 0;
      ServerEx *myServerEx;
    protected:
      myLock *keylock;
    private:
      bool _en;
    };
    class keysearch;
    class HMICtrlEnable : public HMICtrl
    {
    public:
      HMICtrlEnable(keysearch *keysearch) : _cmd('j'), _keysearch(keysearch){};
      ~HMICtrlEnable(){};
      virtual void ActionInterface();
    
    private:
      char _cmd;
      keysearch *_keysearch;
    };
    
    class HMICtrlDisable : public HMICtrl
    {
    public:
      HMICtrlDisable(){};
      ~HMICtrlDisable(){};
      virtual void ActionInterface();
    };
    
    class Context
    {
    public:
      Context(HMICtrl *hmiCtrl);
      ~Context();
      void HMIcontrol();
    
    private:
      HMICtrl *_HMICtrl;
    };
    
    #endif

key.hpp文件

    #ifndef KEY_HPP
    #define KEY_HPP
    
    #include "head.hpp"
    #include "server.hpp"
    extern std::mutex mtx;
    extern std::condition_variable event;
    
    class myLock
    {
    public:
      myLock(){};
      ~myLock(){};
      void startLock();
      void stopLock();
      void waitEvent();
      void eventTrigger();
    
    private:
    };
    
    class keysearch
    {
    public:
      keysearch();
      ~keysearch(){};
      bool getJumpInfo();
      int KeyDetect();
      bool getTransCmd();
    
    private:
      bool jump;
      bool status;
      myLock *keylock;
    };
    extern keysearch k;
    
    #endif

main.c

    #include "head.hpp"
    #include "key.hpp"
    #include "server.hpp"
    
    /* key=j means stop HMI, but the transmit is keep */
    /* key=s means stop transmit, so the HMI also stop */
    
    int main(void)
    {
      ServerEx ser;
      using namespace std;
      thread t1(&ServerEx::server, ser);
      cout << "start" << endl;
      thread t2(&keysearch::KeyDetect, ref(k));
      t1.join();
      t2.join();
      getchar();
      return 0;
    }

六,历史记录

历史记录.png
上一篇下一篇

猜你喜欢

热点阅读