简单设计并开发一个移动通信程序
来源:互联网 发布:火箭队球迷 知乎 编辑:程序博客网 时间:2024/06/06 19:06
网络越来越好,手机之间的互动已经是常态,王者荣耀、微信实时视频等,已经将多屏互动推到各到各种应用场景。
为了让大家能清楚地了解多屏互动,我将结合实例对移动设备实时通信进行研究,并系统性地呈现一些解决方案。
最开始,我尝试给大家展示如何建立一个最简单的点对点通信。
万事开头难,先假定一下需求:
局域网内通信。
写一个你看我画的程序。
纯客户端(一开始,我不打算让服务器参与)。
下面对需求进行进一步的分析。
需求分析
我做了一个简单的原型设计,如下图,其实真正的状态比这个稍复杂,这里提供一下 原型链接
需求原型
从原型上看,我们的流程应该是下图的形式。
流程图
下面我们进行架构设计与开发选型了。
架构设计
基于前文的需求假定进行简单设计网络模型,我将目标的网络分拆成3层:
网络模型
对应的开发架构应该是这样的
开发架构
开发规则
基于实时通信的高效性,我将底层库的开发语言选择了C++,协议格式选择为二进制,网络层协议选择UDP(后面会有切换TCP的选择)。
通信协议端口我选择12000.
下面我将开始搭建底层库(写到这里还是一行代码都没写,不过现在是国庆节,既然有时间那就开始搞吧)。
底层库搭建
创建工程
工程目录如下
我设计的busi头文件,给上层调用的。(详细的见 github)
#ifndef hello_busi_hpp#define hello_busi_hpp#include <stdio.h>namespace hello{ class BusiInterface{ public: virtual int onInit(int myIp, int myPort); virtual int onLink(int srcIndex, int srcIp, int srcPort, const char* srcName, int nameSize); virtual int onConfirm(int srcIndex, const char* srcName, int nameSize); virtual int onCancel(int srcIndex); virtual int onMsg(int srcIndex, const char* msg, int size); }; class Busi{ public: Busi(); virtual ~Busi(); virtual int init(BusiInterface* itf); virtual int link(const char* myName, int nameSize, int dstIp, int dstPort); virtual int confirm(const char* myName, int nameSize, int index); virtual int cancel(int index); virtual int sendMsg(int index, const char* msg, int size); private: Busi* m_busi; };}#endif /* hello_busi_h */
花了半天的时间写完了底层库,先来测试一下底层库的连通性,我写了一个程试程序,只列下核心文件, 详细请看github上。
void Test::testBusi(){ m_busi = new Busi(); m_busi->init(this); char ip[128]; printf("pleast input your name\n"); fgets(m_name, 127, stdin); printf("please input your select\n"); printf("1 for link\n"); printf("2 for auto link\n"); int v; scanf("%d", &v); if(v == 1){ printf("please input the dst ip you want link\n"); scanf("%s", ip); int dstIp = inet_addr(ip); m_busi->link(m_name, strlen(m_name)+1, dstIp, HELLO_COMM_SERVER_LISTEN_PORT); } else{ printf("now you can want link from others\n"); }}void Test::sendMsg(const char *buffer, int size){ m_busi->sendMsg(m_dstIndex, buffer, size);}int Test::onInit(int myIp, int myPort){ struct in_addr addr; addr.s_addr = myIp; printf("on init, my ip:%s, my port:%d\n", inet_ntoa(addr), myPort); return HELLO_STATUS_OK;}int Test::onLink(int srcIndex, int srcIp, int srcPort, const char* srcName, int nameSize){ struct in_addr addr; addr.s_addr = srcIp; printf("on link from ip:%s, port:%d, name:%s\n", inet_ntoa(addr), srcPort, srcName); m_busi->confirm(m_name, strlen(m_name), srcIndex); printf("now you can send msg to destination\n"); g_linked = 1; m_dstIndex = srcIndex; return HELLO_STATUS_OK;}int Test::onConfirm(int srcIndex, const char* srcName, int nameSize){ printf("on confirm from index:%d, name:%s\n", srcIndex, srcName); m_dstIndex = srcIndex; printf("now you can send msg to destination\n"); g_linked = 1; return HELLO_STATUS_OK;}int Test::onCancel(int srcIndex){ printf("on cancel from index:%d\n", srcIndex); return HELLO_STATUS_OK;}int Test::onMsg(int srcIndex, const char* msg, int size){ printf("on msg from index:%d, msg: size:%d\n", srcIndex, size); printf("msg:%s", msg); return HELLO_STATUS_OK;}
因为我有一台mac, 一个ubuntu,所有测试时候,2边都要编译,mac是用xcode比较简单,ubuntu上编写makefile
framework:
BUSI_SRC=$(wildcard busi/*.cpp)NET_SRC=$(wildcard net/*.cpp)PACKAGE_SRC=$(wildcard package/*.cpp)UTIL_SRC=$(wildcard util/*.cpp)SRC=$(BUSI_SRC) $(NET_SRC) $(PACKAGE_SRC) $(UTIL_SRC)OBJS=$(patsubst %.cpp, %.o, $(SRC))CXXFLAGS += -D_WMD -pthread -std=c++11 -g -O0LDFLAGS += -L/lib64 -pthreadLIB=../lib/libwmd.a default: $(LIB)$(LIB): $(OBJS) rm -rf $@ ar -rs $@ $(OBJS)clean: -rm -rf $(OBJS).cpp: $(CXX) -o $@ $< $(CXXFLAGS) $(LDFLAGS) $(LIBRARY) $(LIBS)
test
SRC=$(wildcard *.cpp)OBJS=$(patsubst %.cpp, %.o, $(SRC))CXXFLAGS += -std=c++11 -g -O0LDFLAGS += ../lib/libwmd.a -L/lib64 -pthreadAPP=./hello.outdefault:$(APP)clean: -rm -rf $(OBJS) -rm -rf $(APP)$(APP): $(OBJS) $(CXX) -o $@ $^ $(CXXFLAGS) $(LDFLAGS).cpp: $(CXX) -g -o $@ $< $(CXXFLAGS) $(LDFLAGS) $(LIBRARY) $(LIBS)
生成的程序如下:
现在我们来实测一下连通性:
我让mac做主动连接的一方,让linux做被动连接。
然后试着各自问候一下吧
可以看到2者已经通了,咱们的底层库搭建OK!
感兴趣并助喜欢动手同学,可以 下载代码 实测一下。
写一个你看我画的程序吧
为了方便调试,我选择开发一个mac版的你看我画。
创建工程
在xcode上建立一个spritekit工程
在storyboard上加入按钮元素并绑定ViewController中的变量。
代码目录设计
framework为底层库,util为工具目录,adaptor为适配层。
实现绘图功能
创建一个自定义的view用来实现绘画。
在实现上我用最简单的绘图API, 不过为了区分对手与我画的,我用了2种颜色。
设置自定义鼠标响应事件
并在代码里创建1个scene用于加载自定义view.
上下层打通
object c 调用原生C++,我的做法是加一层代理。
我将代码结构设计如下
含义
适配架构
在开发的时候,我希望上层在发送消息时,不需要指定IP与端口,而只需要索引就行,因此在framework层
建立一个 地址与索引的对应关系。
所以适配层调用接口只需要指定index就行了
应用层通信实现
结合之前设计的流程图,这个游戏过程的生命周期用viewcontroller 中的代码表示如下:
所以最终连接建立要么在confirm后,要么在onConfirm后。
start函数其实只是负责切换到画图场景
OK,整体代码写完后,我们来演示一下效果。
程序演示
先看下截图
没发现markdown能支持视频,所以只能将视频链接发上来:
http://v.youku.com/v_show/id_XMzA4MTQ0NjkzNg==.html?spm=a2h3j.8428770.3416059.1
我画的有点丑,不过没关系,大家可以上github上拉下来自己画。
https://github.com/70207/draw.git
- 简单设计并开发一个移动通信程序
- 一个简单的socket通信聊天程序
- 一个简单的java socket通信程序
- 一个简单的NIO Socket通信程序
- 一个简单的网络通信程序
- 一个简单的,基本功能完善的移动通信架构
- Java编写一个简单的TCP通信程序。服务器发送一条字符串,客户端接收该信息并显示。
- 开发并部署一个简单的EJB
- 由一个简单的客户端间TCP/UDP通信程序引发的关于设计模式的思考
- 一个后台运行程序的简单设计
- 一个简单的DELPHI程序注册码设计
- 一个简单的DELPHI程序注册码设计 .
- Qt开发串口通信以及坐标显示程序并移植
- Qt开发串口通信以及坐标显示程序并移植
- Qt开发串口通信以及坐标显示程序并移植
- C#网络编程TCP通信实例程序简单设计
- C#网络编程TCP通信实例程序简单设计
- 简单一个opengl程序,2D图形移动
- 深入理解express框架
- python pandas 统计性质
- O
- Python,函数(1)
- Win10以管理员身份打开命令提示符CMD的3种方法
- 简单设计并开发一个移动通信程序
- SqlServer列传行+动态sql
- 超初级的用Python收集杂乱字符串中的特定字符,统计出每个特定字符的出现次数并取出最小值
- 171206-类与对象【连续第四十二天】
- opencv之画图(Drawing Functions in OpenCV )
- thinkphp3.2 中用S方法实现 用户定时操作
- 利用Swoole实现PHP+websocket 聊天室
- Qt 拖拽 动态 垃圾箱
- 查看APK的签名的方法