简单设计并开发一个移动通信程序

简介: 网络越来越好,手机之间的互动已经是常态,王者荣耀、微信实时视频等,已经将多屏互动推到各到各种应用场景。 为了让大家能清楚地了解多屏互动,我将结合实例对移动设备实时通信进行研究,并系统性地呈现一些解决方案。 最开始,我尝试给大家展示如何建立一个最简单的点对点通信。 万事开头难,先假定一下需求: 局域网内通信。 写一个你看我画的程序。 纯客户端(一开始,我不打算让服务器参与)。 下面

网络越来越好,手机之间的互动已经是常态,王者荣耀、微信实时视频等,已经将多屏互动推到各到各种应用场景。
为了让大家能清楚地了解多屏互动,我将结合实例对移动设备实时通信进行研究,并系统性地呈现一些解决方案。
最开始,我尝试给大家展示如何建立一个最简单的点对点通信。
万事开头难,先假定一下需求:
局域网内通信。
写一个你看我画的程序。
纯客户端(一开始,我不打算让服务器参与)。

下面对需求进行进一步的分析。

需求分析

我做了一个简单的原型设计,如下图,其实真正的状态比这个稍复杂,这里提供一下 原型链接

需求原型

image.png

从原型上看,我们的流程应该是下图的形式。

流程图

image.png

下面我们进行架构设计与开发选型了。

架构设计

基于前文的需求假定进行简单设计网络模型,我将目标的网络分拆成3层:

网络模型

image.png

对应的开发架构应该是这样的

开发架构

image.png

开发规则

基于实时通信的高效性,我将底层库的开发语言选择了C++,协议格式选择为二进制,网络层协议选择UDP(后面会有切换TCP的选择)。
通信协议端口我选择12000.

字段 注解
底层库开发语言 C++
协议格式 二进制
网络层协议 UDP
通信端口 12000

下面我将开始搭建底层库(写到这里还是一行代码都没写,不过现在是国庆节,既然有时间那就开始搞吧)。

底层库搭建

创建工程

工程目录如下
image.png

我设计的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 -O0
LDFLAGS += -L/lib64 -pthread
LIB=../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 -O0
LDFLAGS += ../lib/libwmd.a -L/lib64 -pthread
APP=./hello.out
default:$(APP)
clean:
        -rm -rf $(OBJS)
        -rm -rf $(APP)
$(APP): $(OBJS)
        $(CXX) -o $@ $^ $(CXXFLAGS) $(LDFLAGS)
.cpp:
        $(CXX) -g -o $@ $< $(CXXFLAGS) $(LDFLAGS) $(LIBRARY) $(LIBS)

生成的程序如下:
image.png

现在我们来实测一下连通性:
我让mac做主动连接的一方,让linux做被动连接。
image.png
image.png

然后试着各自问候一下吧
image.png
image.png

可以看到2者已经通了,咱们的底层库搭建OK!
感兴趣并助喜欢动手同学,可以 下载代码 实测一下。

写一个你看我画的程序吧

为了方便调试,我选择开发一个mac版的你看我画。

创建工程

在xcode上建立一个spritekit工程
image.png
image.png

在storyboard上加入按钮元素并绑定ViewController中的变量。
image.png

代码目录设计

image.png

framework为底层库,util为工具目录,adaptor为适配层。

实现绘图功能

创建一个自定义的view用来实现绘画。
image.png

在实现上我用最简单的绘图API, 不过为了区分对手与我画的,我用了2种颜色。
image.png

设置自定义鼠标响应事件
image.png

并在代码里创建1个scene用于加载自定义view.

上下层打通

object c 调用原生C++,我的做法是加一层代理。
我将代码结构设计如下

image.png

含义

CoreData 应用层协议结构
CoreAdaptor object c 适配
CoreDelegate 代码接口
Core c++适配

适配架构

image.png

在开发的时候,我希望上层在发送消息时,不需要指定IP与端口,而只需要索引就行,因此在framework层
建立一个 地址与索引的对应关系。
image.png

所以适配层调用接口只需要指定index就行了
image.png

应用层通信实现

结合之前设计的流程图,这个游戏过程的生命周期用viewcontroller 中的代码表示如下:
image.png

所以最终连接建立要么在confirm后,要么在onConfirm后。
image.png

image.png

start函数其实只是负责切换到画图场景
image.png

OK,整体代码写完后,我们来演示一下效果。

程序演示

先看下截图

image.png

明天我上传下视频,我画的有点丑,不过没关系,大家可以上github上拉下来自己画。
https://github.com/70207/draw.git

目录
相关文章
|
7月前
|
物联网 BI
PCB设计及制作-数字钟-物联网应用系统设计项目开发
PCB设计及制作-数字钟-物联网应用系统设计项目开发
98 0
|
5月前
|
监控 BI 数据处理
LabVIEW与欧陆温控表通讯的实现与应用:厂商软件与自主开发的优缺点
LabVIEW与欧陆温控表通讯的实现与应用:厂商软件与自主开发的优缺点
41 0
|
7月前
|
存储 传感器 内存技术
嵌入式硬件系统的基本组成部分
嵌入式硬件系统的基本组成部分
116 1
|
物联网 数据处理
嵌入式系统与硬件设计:连接物联世界的智慧之源
本篇深入研究了物联网中嵌入式系统与硬件设计的关键内容。我们探讨了嵌入式系统的概述,介绍了微控制器与嵌入式开发板在物联网应用中的应用,以及硬件设计的基本原则和接口。通过Arduino示例代码,读者可以了解如何使用嵌入式开发板控制LED灯。设计原则和硬件接口部分帮助读者更好地理解硬件设计的关键考虑因素,包括电路设计、电源管理和接口选择。通过本篇内容,读者将更加了解嵌入式系统与硬件设计在物联网中的作用,为创造智能化的嵌入式应用提供了有益的指导。
188 0
|
JavaScript 前端开发 测试技术
研发思维06----嵌入式智能硬件量产过程性设计(下)
研发思维06----嵌入式智能硬件量产过程性设计
322 0
研发思维06----嵌入式智能硬件量产过程性设计(下)
|
JavaScript 智能硬件
研发思维06----嵌入式智能硬件量产过程性设计(上)
嵌入式智能硬件产品从EVT到MP过程分析
192 0
研发思维06----嵌入式智能硬件量产过程性设计(上)
|
存储
嵌入式网络设备一次盲点补报的开发经验(二)
嵌入式网络设备一次盲点补报的开发经验(二)
111 0
|
小程序 物联网
物联网小程序定制开发怎么做?
物联网小程序(IoT)是到处都在谈论的最新流行语,但是许多人并不完全理解该短语背后的概念或该技术的当前位置。人们普遍认为距离物联网小程序还需要几年的时间,其实物联网小程序正在迅速扩展。
235 14
|
物联网 Linux 芯片
启明云端分享:基于工业级嵌入式核心板卡制作而成的核心模块
WT-ARM9X25-S2 核心模块是基于 ATMEL AT91SAM9X25 ARM9 处理器的工业级嵌入式核心板卡,采用表贴式邮票口封装, 4cm X 4cm 超小尺寸, 108 引脚。该产品主要面向工业控制,仪表仪器,医疗电子,物联网网关等应用, 可以帮助客户快速开发高可靠性产品。
192 0
启明云端分享:基于工业级嵌入式核心板卡制作而成的核心模块
|
传感器 自动驾驶 安全
5G涉及到的领域(上) | 《5G移动无线通信技术》之四
本节从使用者的角度,介绍了 2020 年和未来社会发展的预期和展望,包括具体的用例目标和挑战。通过一系列不同的用例,介绍为了应对挑战并达到目标,5G 系统所 需要满足并达到的各项要求。
5G涉及到的领域(上) | 《5G移动无线通信技术》之四
下一篇
无影云桌面