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

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

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

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

需求分析

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

需求原型

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

目录
相关文章
|
4天前
|
存储 人工智能 安全
AI 越智能,数据越危险?
阿里云提供AI全栈安全能力,为客户构建全链路数据保护体系,让企业敢用、能用、放心用
|
7天前
|
域名解析 人工智能
【实操攻略】手把手教学,免费领取.CN域名
即日起至2025年12月31日,购买万小智AI建站或云·企业官网,每单可免费领1个.CN域名首年!跟我了解领取攻略吧~
|
6天前
|
数据采集 人工智能 自然语言处理
3分钟采集134篇AI文章!深度解析如何通过云无影AgentBay实现25倍并发 + LlamaIndex智能推荐
结合阿里云无影 AgentBay 云端并发采集与 LlamaIndex 智能分析,3分钟高效抓取134篇 AI Agent 文章,实现 AI 推荐、智能问答与知识沉淀,打造从数据获取到价值提炼的完整闭环。
404 93
|
6天前
|
SQL 人工智能 自然语言处理
Geo优化SOP标准化:于磊老师的“人性化Geo”体系如何助力企业获客提效46%
随着生成式AI的普及,Geo优化(Generative Engine Optimization)已成为企业获客的新战场。然而,缺乏标准化流程(Geo优化sop)导致优化效果参差不齐。本文将深入探讨Geo专家于磊老师提出的“人性化Geo”优化体系,并展示Geo优化sop标准化如何帮助企业实现获客效率提升46%的惊人效果,为企业在AI时代构建稳定的流量护城河。
399 156
Geo优化SOP标准化:于磊老师的“人性化Geo”体系如何助力企业获客提效46%
|
6天前
|
数据采集 缓存 数据可视化
Android 无侵入式数据采集:从手动埋点到字节码插桩的演进之路
本文深入探讨Android无侵入式埋点技术,通过AOP与字节码插桩(如ASM)实现数据采集自动化,彻底解耦业务代码与埋点逻辑。涵盖页面浏览、点击事件自动追踪及注解驱动的半自动化方案,提升数据质量与研发效率,助力团队迈向高效、稳定的智能化埋点体系。(238字)
291 158
|
14天前
|
机器人 API 调度
基于 DMS Dify+Notebook+Airflow 实现 Agent 的一站式开发
本文提出“DMS Dify + Notebook + Airflow”三位一体架构,解决 Dify 在代码执行与定时调度上的局限。通过 Notebook 扩展 Python 环境,Airflow实现任务调度,构建可扩展、可运维的企业级智能 Agent 系统,提升大模型应用的工程化能力。