这半个月主要精力放在了开发一个网络数据服务器。该服务器的架构是基于IOCP模型,该程序的主要功能如下:
- 服务器解析硬件传入的数据帧并打印;
- 服务器解析客户端传入的JSON类型数据命令,根据相应的命令传入不同的硬件信息,把硬件数据转化成JSON类型数据传给客户端。
目前只实现了这两个功能哈哈哈哈。解析JSON用的是jsoncpp库,之前的博客我有写到jsoncpp库是怎么用的。下面我就详细讲一下开发这个程序遇到的困难以及相应的解决方法。
- 1.socket网络通讯如何发送unsigned const char* 类型数据?
因为之前写TCP程序时发送的都是const char* 类型数据,然后突然发送的是unsigned const
char*类型数据,有点蒙。之前以为如果使用强制类型转换会对数据造成破坏,后来上网搜索了相关问题之后迷糊灌顶,把网上回答如下:
什么叫"强制转化会损失数据"???在计算机内部,没有类型这个概念,也就不存在是否损失数据这个问题. 所谓的强制转换,其实就是告诉编译器,将这个值按照什么方式进行解释.而这个过程是并不会修改数据的. 对于c/c++来说, char 和
unsigned char 其实就是一样的(都是8bit,1个字节),所以两者在任何地方都可以说是完全等效的. 至于BYTE,其实也就是
unsigned char 而已. 知道了这些,还需要考虑么? 假设你发送的数据是 BYTE b; 那么发送的时候,
send(SOCKET , (const char )b , int,int);就行了,传输的数据是不会出错的. 至于接收,同样定义一个
BYTE b ,不过要预先分配好空间, 比如 BYTEb=new BYTE[100]; 然后, recv(SOCKET ,
(char)b , int , int ) 就是了.得到的 b 的数据,就是你发送过来的数据了.*经过实践确实如他所说。
BYTE* buf = new BYTE[40];
int HID = 40;
int seq = 1;
SetLocal(buf, HID, seq);
for (int i = 0; i < 40; i++)
{
printf("%.2x ", buf[i]);
}
send(sockClient, (const char*)buf, 40, 0); // 发送信息
- 2.报错C1189 #error: “No Target Architecture”
这是在代码移植时出现的问题,在网上搜了问题原因是:
因为单独包含了一些windows.h已经包含了的头文件如"fileapi.h",“WinUser.h”,但是却没有包含windows.h或者先包含了如"fileapi.h",“WinUser.h”,后包含windows.h,顺序不对。
最后的解决方法是: 在项目中添加_AMD64_宏可以解决该问题。具体方法:项目名称右键–>属性–>C/C+±->预处理器–>添加宏
问题解决!
- 3.运行出现错误:#error: Building MFC application with /MD[d] (CRT dll version) requires MFC shared dll version. Please #define _AFXDLL or
do not use /MD[d]
程序运行出现问题,在网上搜索到解决方案:
先选择“解决方案管理器”,然后按如下路径:项目-》属性-》C/C+±》代码生成-》运行库,将“多线程调试DLL(/MDd)”改成“多线程(/MT)”或“多线程调试(/MTd)。
问题解决!
- 4.运行时出现错误:#error WINDOWS.H already included. MFC apps must not #include <windows.h>
错误原因:多次包含window.h文件
之前我做程序引用头文件的一般顺序是先引用库文件,然后再引用当前文件目录下的文件。结果在这个程序的编写中遇到了问题。出现错误程序的头文件引用如下:#include <process.h> #include <string> #include <cstring> #include <json.h> #include <iostream> #include <stdio.h> #include <tchar.h> #include <vector> #include "Threadsafe_queue.h" #include <WinSock2.h> #include "LogFile.h" #include "LogTool.h" #include <MSWSock.h> #include "StructDefine.h" ``` 我把同文件目录下的头文件StructDefine.h放在了最后进行引用,这就造成了编译错误。之前我以为是#include<WinSock2.h>这个地方重复引用了 window.h文件,改了好多位置都不对,后来把#include "StructDefine.h"引> 用放在最前面编译通过。 心得:编写程序时头文件先引用同目录下的文件,最后引用库文件。 问题解决!
- 5.如何传送一个心跳帧
之前对实际应用中的数据报文不太了解,对心跳帧的具体内部构成不太理解,不了解心跳帧也就传输不了心跳帧。后来看了心跳帧的简要文档后,还是有点迷迷蒙蒙。在看了相关代码后才对心跳帧有了一个清晰的认识。
然后就是如何传送心跳帧,解决方法是定义一个 unsigned
char类型数组,把数据按照字节以十六进制方式存到数组中,最后在send中通过强转把unsigned char类型转化为const char
类型,即:send(sockClient, (const char)buf, 40, 0);这就实现了传输一个心跳帧。
- 6.如何区分硬件设备传入数据还是客户端传入的指令?
在这里我设置客户端传入的指令为{“cmd”:xxx,”hid”:xxx},硬件传入数据是心跳帧或定位帧。在服务端我设置了字符串匹配来判断服务器收到的信息。如果数据和“cmd”匹配,传入的就是客户端数据,对客户端的数据进行处理。
如果不和”cmd”匹配,那么就默认是硬件数据,会有相应操作对硬件数据进行解析。 问题解决!
- 7.服务端解析客户端传入的JSON形式的指令,根据指令向客户端返回相应数据?
解析JSON形式的指令我使用的是jsoncpp库来解析json数据,根据指令向客户端返回数据本来我是想返回一个char型数组,结果我师父说如果返回char型数组,别人是不会知道传入的是什么数据的,还不如传入json数据,于是我就把解析的数据又封装成json格式传给客户端。
问题解决!