- 博客(112)
- 收藏
- 关注
原创 openframeworks出现问题--E: 无法定位软件包问题
E: Unable to locate package libgl1-mesa-dev-hwe-18.04E: Couldn’t find any package by glob ‘libgl1-mesa-dev-hwe-18.04’E: Couldn’t find any package by regex ‘libgl1-mesa-dev-hwe-18.04’这个问题就是install_dependencies.sh文件中**libgl1-mesa-devXTAG∗∗的形式不匹配,只要去除{XTA
2021-12-10 17:17:19 1955
原创 c++后端开发菜鸟实习记录
(时长三十分钟)1.手撕算法题(关于环),未做出来2.网络五层模型、OSI七层模型3.TCP\UDP在哪一层,http/https在哪一层,区别是什么?4.三次握手、四次挥手5.hash_map了解么?底层是什么?红黑树?6.愿意转java不?7.项目的粘包问题...
2021-07-09 10:01:03 612
原创 7.1---客户端与服务端的粘包现象演示(网络缓冲区)
客户端代码和服务端代码都使用前面文章所封装的class本文先对缓冲区做各种测试,文章最后会介绍粘包现象。接下来的几篇文章中会介绍客户端与服务端如何处理这种粘包现象一、测试1:循环发送与接收少量数据(8kb)测试1的过程为:服务端:服务端代码基本不变,其接收客户端发送过来的数据,在收到数据之后将相应数据回送给客户端客户端:客户端使用while()循环一直向服务端发送程序客户端与服务端的每次交互的单个数据包比较小,只有8字节//服务端代码如下#include "EasyTcpServer.hpp
2021-07-01 19:45:32 260
原创 6.1---将客户端封装为class
一、概述在前面的文章中,客户端的代码都是以面向过程的形式展现,本文将之前客户端的代码封装为一个class二、代码如下MessageHeader.hpp这个头文件包含所有的数据包的格式定义#ifndef _MessageHeader_hpp_#define _MessageHeader_hpp_ enum CMD{ CMD_LOGIN, CMD_LOGIN_RESULT, CMD_LOGOUT, CMD_LOGOUT_RESULT, CMD_NEW_USER_JOIN, CMD_
2021-07-01 19:40:09 113
原创 6.2---将服务端端封装为class
一、概述在前面的文章中,服务端的代码都是以面向过程的形式展现,本文将之前服务端的代码封装为一个class二、代码如下MessageHeader.hpp这个头文件包含所有的数据包的格式定义#ifndef _MessageHeader_hpp_#define _MessageHeader_hpp_ //消息的类型enum CMD{ CMD_LOGIN, //登录 CMD_LOGIN_RESULT, //登录结果 CMD_LOGOUT, //退出 CMD
2021-07-01 19:37:59 123
原创 5.2---将服务端代码进行跨平台移植(Windows、Unix)
一、跨平台移植概述前面的文章我们的代码都是在Windows下进行编译运行的,现在我们需要将代码移动到Linux和Mac OS操作系统上进行运行因为Linux和Mac OS底层都是使用Unix内核,因此将代码修改之后,在Linux和Mac OS上面都可以进行编译并运行,不需要单独设计两份二、代码修订代码修订1头文件修订:Windows与Unix下套接字使用的头文件不同,因此需要修订一些常量定义:Windows下有SOCKET、、INVALID_SOCKET、SOCKET_ERROR等宏的定义,但是
2021-07-01 19:35:49 439
原创 5.1---将客户端代码进行跨平台移植(Windows、Unix)
一、跨平台移植概述前面的文章我们的代码都是在Windows下进行编译运行的,现在我们修改代码,使其在Windows、Ubuntu、Mac OS系统上都可以运行因为Linux和Mac OS底层都是使用Unix内核,因此将代码修改之后,在Linux和Mac OS上面都可以进行编译并运行,不需要单独设计两份二、代码修订代码修订1头文件修订:Windows与Unix下套接字使用的头文件不同,因此需要修订一些常量定义:Windows下有SOCKET、、INVALID_SOCKET、SOCKET_ERROR
2021-07-01 19:29:17 546
原创 4---为客户端添加输入线程
一、为客户端添加输入线程在前一篇文章中我们的客户端不能手动的在命令行中输入命令发送给服务端,而是简单地书写了一小段代码,然后发送给服务端此处我们为客户端添加一个线程,此处采用的是C++11中的线程对象std::thread二、代码设计思路设计了一个全局变量g_bRun代表当前客户端正在运行,main函数主循环while中使用g_bRun在主循环while之前设计创建一个C++11线程对象,线程运行函数名为cmdThread(),函数参数为客户端的socket。并且该线程分离出了主线程(为什么要分离
2021-07-01 19:23:01 139
原创 3---将服务端、客户端升级为select模型
一、Windows下的selectWindows下的select函数与Unix下的select函数语法相同,但是有些语言稍有不同Unix下的select函数其参数1为操作的最大描述符的值加1。但是Windows下的select函数的第一个参数可以填最大的文件描述符加1,也可以默认填0(其参数1只是为了兼容而已)另外,Windows下的fd_set数据类型定义如下,其两个成员变量可以进行调用(但是Unix下的fd_set不提供),含义如下:fd_count:当前fd_set集合中存放的描述符的数量f
2021-07-01 19:18:55 157
原创 2---封装网络数据报
一、为什么设计网络数据报在消息交互时使用字符串不安全,且比较麻烦不好处理二、本文案例中用到的数据报格式本文的案例为:客户端可以输入login来登录服务端,或者输入logout来退出服务端服务端根据客户端传来的数据,做相应的回复消息类型枚举//消息的类型enum CMD{ CMD_LOGIN, //登录 CMD_LOGIN_RESULT, //登录结果 CMD_LOGOUT, //退出 CMD_LOGOUT_RESULT, //退出结果 CMD_E
2021-07-01 19:07:04 114
原创 1---Windows下Tcp Socket的基本结构(客户端、服务端)(转载)
1.服务端#define WIN32_LEAN_AND_MEAN#define _WINSOCK_DEPRECATED_NO_WARNINGS //for inet_pton() #include <windows.h>#include <WinSock2.h>#include <iostream> #pragma comment(lib, "ws2_32.lib") using namespace std; int main(){ WORD.
2021-07-01 17:25:55 202
原创 几种构造函数详解
有个老哥写的构造函数解析,觉得很不错,害怕以后csdn这sb又自动收费,转载过来保存下。转载地址class Complex { private : double m_real; double m_imag; public: // 无参构造函数 // 如果创建一个类你没有写任何构造函数,则系统会自动生成默认的无参构造函数,函数为空 // 只要你写了一个下面的某一种构造函数,系统就不会再自动生成这样一个 //默认构造函数,如果希望
2021-05-09 08:48:04 1398
原创 25 领域规则模式(Interpreter)
在特定领域中,某些变化虽然频繁,但可以抽象为某种规则。这时候,结合特定领域,将问题抽象为语法规则,从而给出在该领域下的一般性解决方案。①只有满足“业务规则频繁变化,且类似的结构不断重复出现,并且容易抽象为语法规则问题”才适合Interpreter模式。②Interpreter模式比较适合简单的文法表示,对于复杂的文法表示,Interpreter模式会产生比较大的类层次结构,需要求助于语法分析生成器这样的标准工具。...
2021-01-05 20:38:59 299
原创 23、24行为变化模式(Command、Visitor)
在组件的构建过程中,组件行为的变化经常导致组件本身剧烈的变化。“行为变化”模式将组件的行为和组件本身进行解耦,从而支持组件行为的变化,实现两者之间的松耦合。命令模式(Command)①Command模式的根本目的在于将“行为请求者”和“行为实现者”解耦。②Command模式与C++中的函数对象有些类似。但两者定义行为接口的规范有所区别:Command以面向对象中的“接口-实现”来定义行为接口规范,更严格,但有性能损失;C++函数对象以函数签名来定义行为接口规范,更灵活,性能更高。访问器(Visito
2021-01-05 20:21:07 153
原创 20、21、22数据结构模式(Composite、Iterator、Chain of Resposibility)
常常有一些组件在内部具有特定的数据结构,如果让客户程序依赖这些特定的数据结构,将极大地破坏组件的复用。这时候,将这些特定的数据结构封装在内部,在外部提供统一的接口,来实现与特定数据结构无关的访问,是一种行之有效的解决方案。组合模式(Composite)①Composite模式采用树形结构来实现普遍存在的对象容器,从而将“一对多”的关系转化为“一对一”的关系,使得客户代码可以一致地(复用)处理对象和对象容器,无需关心处理的是单个对象还是组合的对象容器。②将“客户代码与复杂对象容器结构”解耦是Compos
2020-12-29 21:00:25 120
原创 18、19状态变化模式(State、Memento)
在某些构建过程中,某些对象的状态经常面临变化,如何对这些变化进行有效的管理?同时又维持高层模块的稳定?状态变化模块为这一问题提供了一种解决方案。状态模式(State)①State模式将所有与一个特定状态相关的行为都放入一个State的子类对象中,在对象状态切换时,切换相应的对象;但同时维持State的接口,这样实现了具体操作与状态转换之间的解耦。②如果State对象没有实例变量,那么各个上下文可以共享同一个State对象,从而节省对象开销。备忘录(Memento)①Memento模式的核心是信息隐
2020-12-28 21:55:23 147
原创 14、15、16、17 接口隔离模式(Facade、Proxy、Adapter、Mediator)
在组建的构建过程中,某些接口之间直接的依赖常常带来许多问题、甚至根本无法实现。采用添加一层间接(稳定接口),来隔离本来互相紧密关联的接口是一种常见的解决方案。门面模式(Facade)①从客户的角度来看,Facade模式简化了整个组件系统的接口,对于组件内部与外部客户程序来说,达到了一种“解耦”的效果–内部子系统的任何变化不会影响到Facade接口的变化②Facade设计模式更注重从架构的层次去看整个系统,而不是单个类的层次。③Facade设计模式并非一个集装箱,可以任意地放进任何多个对象。Facad
2020-12-28 21:21:09 192
原创 12、13对象性能模式(Singleton、Flyweight)
面向对象很好的解决了“抽象”问题,但是不可避免地要付出一定的代价。对于通常情况来讲,面向对象的成本大多可以忽略不计。但在某些情况下,面向对象的成本必须谨慎处理。单例模式(Singleton)Singleton模式一般不要支持拷贝构造函数和Clone接口,因为这有可能导致多个对象实例,与Singleton模式初衷违背。享元模式(Flyweight)...
2020-12-28 19:39:09 99
原创 8、9、10、11对象创建模式(工厂方法、抽象工厂、原型模式、构建器)
通过“对象创建”模式绕开new,来避免对象创建(new)过程中所导致的紧耦合,从而支持对象创建的稳定。工厂方法(Factory Method)①Factory Method模式用于隔离类对象的使用者和具体类型之间的耦合关系。面对一个经常变化的具体类型,紧耦合关系会导致软件的软弱。②Factory Method模式通过面向对象的手法,将所要创建的具体对象工作延迟到子类,从而实现一种扩展(而非更改)的策略,较好地解决了这种紧耦合关系。③Factory Method模式解决单个对象的需求变化,缺点在于要求
2020-12-27 10:53:28 95
原创 6、7 单一职责模式(装饰模式、桥模式)
1.装饰模式(Decorator)①通过采用组合而非继承的方法,Decorator模式实现了在运行时动态扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了使用继承带来的灵活性差和多子类衍生问题②Decorator类在接口上表现为is-a Component的继承关系,即Decorator类继承了Component类所具有的接口。但在实现上又表示为has-a Component的组合关系,即Decorator类又使用另外一个Component类2.桥模式(Bridge)...
2020-12-25 09:46:11 143 1
原创 3、4、5 组件协作模式
1.模板方法(Template method)2.策略模式(Strategy)①Strategy及其子类为组件提供了一系列可重用的算法,从而可以使得类型在运行时方便地根据需要在各个算法之间切换②Strategy提供了用条件判断语句以外的另一种选择,消除条件判断语句,就是在解耦合。含有许多条件判断语句的代码通常都需要Strategy模式③如果Strategy对象没有实例变量,那么各个上下文可以共享同一个Strategy对象,从而节省对象开销...
2020-12-19 10:12:54 70
原创 155 线程的相关操作
1.线程的挂起与恢复SuspendThread、ResumeThread线程的挂起和恢复是有次数的,挂起和恢复的次数是一一对应的2.线程的优先级①AfxBeginThread创建线程的时候直接指定②CreateThread需要创建之后指定。获取:GetThreadPriority 设置:SetThreadPriorityUINT _cdecl ThreadProc1(LPVOID lpParameter){ CStdioFile mFile; mFile.Open(_T("F:\\456.
2020-12-17 21:51:59 124
原创 154 、MFC中用户界面线程
界面线程的创建①从CWinThread类派生自己的子类:CUIThread②重载InitInstance(必须重载)与ExitInstance(可选重载)函数③在InitInstance函数界面中进行界面的创建④调用AfxBeginThread函数开启界面线程
2020-12-17 20:42:55 177
原创 2.面向对象设计原则
1.依赖倒置原则(DIP)①高层模块(稳定)不应该依赖于低层模块(变化),二者都应该依赖于抽象(稳定)②抽象(稳定)不应该依赖于实现细节(变化),实现细节应该依赖于抽象(稳定)2.开放封闭原则(OCP)①对扩展开放,对更改封闭。②类模块应该是可扩展的,但是不可修改3.单一职责原则(SRP)①一个类应该仅有一个引起它变化的原因②变化的方向隐含着类的责任4.liskov替换原则(LSP)①子类必须能够替换它们的基类②继承表达类型抽象5.接口隔离原则(ISP)①不应该强迫客户程序依赖它们
2020-12-17 10:32:51 100
原创 152.创建线程的方式
1.CreateThread①需要释放线程资源 CloseHandle(要释放的线程句柄)②注意传递给线程过程的参数的类型2.AfxBeginThread①会创建工作线程和界面线程②工作线程建议不要去操作界面③注意传递给线程过程的参数的类型线程不需要自己释放3._beginthreadex注:①2,3是调用第1种方法...
2020-12-16 20:35:50 75
原创 27.实现一个简单的任务管理器
①、设计界面、以及列表控件变量的绑定;控件:List Controlsingleselection:Trueview:report绑定控件变量:m_TaskList②、列表控件样式的指定:m_TaskList.SetExtendedStyle(LVS_EX_GRIDLINES|LVS_EX_FULLROWSELECT);//设置列表视图控件的当前扩展样式 m_TaskList.InsertColumn(0, _T("进程名称"),2,100); m_TaskList.InsertColumn
2020-12-14 22:03:45 507
原创 26.进程的相关操作
打开某一进程1.ShellExecute方法可以直接使用路径打开//int IRet = (int)ShellExecute(m_hWnd, _T("open"), _T("C:\\WINDOWS\\NOTEPAD.EXE"), _T("F:\\123.txt"), NULL, SW_SHOW);//打开记事本 //int IRet = (int)ShellExecute(m_hWnd, _T("open"), _T("C:\\Program Files\\Internet Explorer\\ie
2020-12-12 20:45:44 81
原创 25.系统信息的获取
1.获取当前用户名称GetUserNameDWORD dwLen = UNLEN + 1; TCHAR szUserName[UNLEN + 1] = { 0 }; GetUserName(szUserName, &dwLen); MessageBox(szUserName);2.获取计算机的名称GetComputerNameDWORD dwLen = MAX_COMPUTERNAME_LENGTH + 1; TCHAR szComputerName[MAX_COMPUTERNA
2020-12-10 22:28:03 149
原创 24 系统各种路径信息的获取
1.Windows、System32、temp等目录的获取TCHAR szBuffer[MAX_PATH] = { 0 }; GetSystemWindowsDirectory(szBuffer, MAX_PATH); GetSystemDirectory(szBuffer, MAX_PATH); GetTempPath(MAX_PATH, szBuffer);2.桌面目录、我的文档等目录TCHAR szPath[MAX_PATH] = { 0 };SHGetSpecialFolderPat
2020-12-10 20:17:53 154
原创 23文件夹的基本操作
1.创建一个文件夹CreateDirectory(只能创建一层目录)2.文件夹的删除RemoveDirectory(此函数只能删除一个空的目录,如果目录中有子目录或子文件的话会删除失败的)3.文件夹属性的获取GetFileAttributes4.文件和文件夹的遍历操作CFileFind实现删除非空目录bool deleteTargetFolder(LPCTSTR lpstrPath){ CString strRootPath(lpstrPath); if (strRootPath[s
2020-12-09 21:36:16 259
原创 21、22)文件的基本操作
1.文件的创建、关闭创建:CFile::Open(一般用两个参数)关闭:CFile::Close2.文件的读写读:CFile::Read写:CFile::Write3.读取或写入一行数据读取一行:CStdioFile::ReadString;写入一行:CStdioFile::WriteString;4.文件指针将文件的指针移动到文件的任意位置:CFile::Seek//如果第二个参数指定为CFile::end的时候,偏移量为负数;将文件指针移动到文件的头部:CFile::SeekToB
2020-12-09 19:54:19 121
原创 20(补充).实现简单的计算器
1.将计算结果保存到剪切板在按钮函数里添加如下函数if (!OpenClipboard())//打开剪切板 { return; } if (!EmptyClipboard())//清空剪切板的数据 { CloseClipboard(); return; } CString str; GetDlgItemText(IDC_STATIC_RESULT, str); size_t cbStr = (str.GetLength() + 1) * sizeof(TCHAR);//申请的
2020-12-03 22:23:09 97
原创 20.实现简单的计算器
1.添加两个Edit Control、两个Static Text和一个ComBo Box;如下图所示:2.为ComBo Box添加变量,命名为mComBoCal;3.在对话框的源文件的初始化函数中添加如下代码,在ComBo Box中添加内容;mComBoCal.InsertString(0, _T("+"));//在ComBo中添加"+"运算 mComBoCal.InsertString(1, _T("-"));//在ComBo中添加"-"运算 mComBoCal.InsertString(2
2020-12-03 21:25:56 173
原创 19.对话框的状态栏操作
让对话框的状态栏显示时钟、鼠标位置、鼠标点的颜色信息1 添加字符串资源ID_INDICATION_POS = 鼠标所在位置ID_INDICATION_COLOR = 鼠标位置颜色ID_INDICATION_TIME = 当前系统事件2.在对话框类的头文件中进行状态栏对象的定义CStatusBar mWndStatusBar;3.定义窗格数组static UINT indicators[] ={ID_INDICATION_POS,//鼠标所在位置ID_INDICATION_COLOR,/
2020-12-02 21:59:21 306
原创 18.对话框的工具栏操作
1.工具栏在对话框中显示1.1主对话框的头文件中添加声明CToolBar mWndToolBar;主对话框的源文件中添加如下代码 if (!mWndToolBar.CreateEx(this, TBSTYLE_FLAT,WS_CHILD|WS_VISIBLE | CBRS_ALIGN_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS,CRect(4, 4, 0, 0)) || !mWndToolBar.LoadToolBar(IDR_TOOLBAR1)) { return
2020-12-01 22:08:03 200
原创 17.对话框的菜单操作
1.MFC中菜单的关联类CMenu2.下拉对话框在对应选项处右击添加事件处理程序,3.弹出对话框在主函数中响应WM_OnContextMenu消息,在其中添加如下代码CMenu mMenu, *pMenu=NULL; mMenu.LoadMenuW(IDR_MENU1); pMenu = mMenu.GetSubMenu(0); pMenu->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,point.x,point.y,this); ```
2020-12-01 20:24:00 217
原创 16.让对话框支持拖拽操作/目录框打开操作
1.打开目录对话框void CMFCApplication7Dlg::OnBnClickedButton1(){ TCHAR szPath[MAX_PATH] = { 0 }; BROWSEINFO mBroInfo = { 0 }; mBroInfo.hwndOwner = m_hWnd; ITEMIDLIST *pidl = SHBrowseForFolder(&mBroInfo);//打开文件目录对话框 if (SHGetPathFromIDList(pidl, szPath
2020-11-30 21:37:29 169
原创 内存分配方式
内存分配方式有三种:(1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。(2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。(3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或
2020-11-22 20:52:09 178
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人