简单实现服务程序的一些问题
2015-11-14 16:44
295 查看
上个月按项目业务功能的新需求,需要实现一个简单的服务程序,对接前台客户端和后台的业务处理端。
之前存在一个windows平台对接端,使用IOCP通信模型来实现。而现在的需求是要在Linux服务器上进行实现,所以采用的是epoll模型。
这次的的实现周期大概是一个月的时间,主要是采用模仿的方式来做,因为在此之前对于网络编程这块不是太擅长,重新设计的风险太高,而且不能保证能够按时的完成项目计划。所以,花了半个月的时间阅读windows下的对接端源码,简单分析了一下大概的通信处理方式,这些工作做完之后,概要设计就算是基本做完了。
之后,花了一周左右的时间完成通信框架的编码,最后一周左右的时间主要用来实现命令的对接。
这次算的上是网络编程的一个小的尝试,结局还算圆满,希望能够还能有更多的尝试机会。
开发过程中遇到的一些问题:
1. 结构体对齐
前端传入的数据形式是多种多样的,有可能是xml文件,有可能是结构体。当传入的数据是结构体的时候,需要保证结构体对齐方式一致,不然可能会出现数据长度不一致的情况,造成数据的解析失败。
可以采用的方式是设置结构体的对齐方式:
因为每次前台发送的命令长度不一致,而对接端的接受缓存长度是一样的。这样的话,可能会出现一下几种情况:
1) 因为前台传入的命令比较短,并且一次发送了多个命令,对接端缓存一次接收到了多个命令;
2) 因为前台传入的命令太长,造成对接端缓存不能一次性接收到完整的命令;
如果每次收到数据,仅仅针对接收缓存的数据处理一次,就有可能造成一些命令丢失【可能是因为命令隐藏在前一个命令的后面,即情况1);可能因为命令格式错误,即情况(2】
可以采用的方式是,维护一个数据结构,将每次接收到的数据依次放入连续的地址空间里面,然后依次解析命令。
采用这种方式,需要注意一些问题:
1) 必须清除每条命令的长度,可以在定义报文格式的时候用一个字段进行记录;
2) 维护的这个数据结构对于每个连接是唯一的,保证接收到的数据能正常拼接;
3) 每次处理完一个命令之后,需要检查该结构体,保证接收到的完整命令都已经处理完成;
3. 重复包含头文件
因为在定义头文件的时候使用了预编译指令#ifndef,所以在包含头文件的时候有些肆无忌惮,然后就产生了.h和.cpp文件里面包含了同一个头文件的情况,有时候这种情况可能不太明显,因为那个相同的头文件不是直接包含的,而是隐藏在别的头文件里。
开始的时候好像没什么问题,当我在那个共同包含的头文件里,定义新的结构体或者宏的时候,再次进行编译的时候,编译器会报出找不到新结构体或宏的定义(经过很多次的确认和排查,结构体名字没有输错,makefile没有写错)。
当将可能的重复头文件去除之后,整个编译就很顺利了。
在检查重复包含这种情况的时候,觉得有个方式可以尝试一下:
不过,当检查完成之后,一定要将这三行从makefile去掉,不然编译起来慢的实在是太吓人了。
之前存在一个windows平台对接端,使用IOCP通信模型来实现。而现在的需求是要在Linux服务器上进行实现,所以采用的是epoll模型。
这次的的实现周期大概是一个月的时间,主要是采用模仿的方式来做,因为在此之前对于网络编程这块不是太擅长,重新设计的风险太高,而且不能保证能够按时的完成项目计划。所以,花了半个月的时间阅读windows下的对接端源码,简单分析了一下大概的通信处理方式,这些工作做完之后,概要设计就算是基本做完了。
之后,花了一周左右的时间完成通信框架的编码,最后一周左右的时间主要用来实现命令的对接。
这次算的上是网络编程的一个小的尝试,结局还算圆满,希望能够还能有更多的尝试机会。
开发过程中遇到的一些问题:
1. 结构体对齐
前端传入的数据形式是多种多样的,有可能是xml文件,有可能是结构体。当传入的数据是结构体的时候,需要保证结构体对齐方式一致,不然可能会出现数据长度不一致的情况,造成数据的解析失败。
可以采用的方式是设置结构体的对齐方式:
#pragma pack( push, n ) /* ** define the struct ** … */ #pragma pack( pop )2. 数据丢失
因为每次前台发送的命令长度不一致,而对接端的接受缓存长度是一样的。这样的话,可能会出现一下几种情况:
1) 因为前台传入的命令比较短,并且一次发送了多个命令,对接端缓存一次接收到了多个命令;
2) 因为前台传入的命令太长,造成对接端缓存不能一次性接收到完整的命令;
如果每次收到数据,仅仅针对接收缓存的数据处理一次,就有可能造成一些命令丢失【可能是因为命令隐藏在前一个命令的后面,即情况1);可能因为命令格式错误,即情况(2】
可以采用的方式是,维护一个数据结构,将每次接收到的数据依次放入连续的地址空间里面,然后依次解析命令。
采用这种方式,需要注意一些问题:
1) 必须清除每条命令的长度,可以在定义报文格式的时候用一个字段进行记录;
2) 维护的这个数据结构对于每个连接是唯一的,保证接收到的数据能正常拼接;
3) 每次处理完一个命令之后,需要检查该结构体,保证接收到的完整命令都已经处理完成;
3. 重复包含头文件
因为在定义头文件的时候使用了预编译指令#ifndef,所以在包含头文件的时候有些肆无忌惮,然后就产生了.h和.cpp文件里面包含了同一个头文件的情况,有时候这种情况可能不太明显,因为那个相同的头文件不是直接包含的,而是隐藏在别的头文件里。
开始的时候好像没什么问题,当我在那个共同包含的头文件里,定义新的结构体或者宏的时候,再次进行编译的时候,编译器会报出找不到新结构体或宏的定义(经过很多次的确认和排查,结构体名字没有输错,makefile没有写错)。
当将可能的重复头文件去除之后,整个编译就很顺利了。
在检查重复包含这种情况的时候,觉得有个方式可以尝试一下:
(makefile) …… .depend: *.cpp rm–f .depend g++-std=c++11 –MM $^ >.depend ……编译器会生成源文件的依赖文件列表,并输出到.depend里面,通过查看.depend文件可以很明显的看到重复包含的头文件。
不过,当检查完成之后,一定要将这三行从makefile去掉,不然编译起来慢的实在是太吓人了。
相关文章推荐
- wpf prism IRegionManager 和IRegionViewRegistry
- 求a,b两个数中较大的数
- SimpliciTI 地址分配
- iOS开发学习资源
- Java三大框架
- IIS6.0建立多个网站
- RecyclerView使用介绍
- Educational Codeforces Round 1 (A)模拟
- iOS9中的WebKit 与 Safari带来的惊喜
- c语言:常用各种头文件的作用,如:#include <stdlib.h>
- 聊天室项目分析
- 单例模式
- Linux中fork()函数详解
- jquery validate如果验证的元素是数组怎么办?
- 求给定两个数之间的所有质数
- Spark修炼之道(进阶篇)——Spark入门到精通:第六节 Spark编程模型(三)
- 设计的基础之一——色彩的搭配
- 淘宝分布式文件系统TFS设计
- 软件测试相关术语定义《全程软件测试》
- CC2541 AirSync(4)——封包、解包