CocoaAsyncSocket (二)

iOS - 基于CocoaAsyncSocket搭建完整的IM体系大体思路详解 想要搭建一个完善 ,且自定义程度较高 , 又便于后期维修和修改的IM体系 , 采用环信或者融云等实际上是非常消耗精力和时间的 ,因为他们做得也不完善 . 目前咱们已知的通信协议大概有MQTT , XMPP等 .. 然而 , 通信协议是别人制定好的规则 , 想要不受约束 , 就需要自定义一套属于自己的通信协议 . 其实通信协议并不难 , 无非就是iOS端,安卓端,web端和服务器共同协商一套,大 阅读详情

参考了一篇机器人控制的文章,总结一下:

【iOS与EV3混合机器人编程系列之四】iOS_WiFi_EV3_Library 剖析之一:WiFi UDP和TCP

其中

1)拥有一个连接界面来搜索并连接WiFi局域网内的EV3设备。
2)实时接收EV3的端口数据并且能非常方便地对数据进行处理。
3)能够发送直接命令(Direct Command)到EV3实现对EV3的实时控制。

和路由器的直连需求是一样的

我们只需要使用库中的四个文件:
GCDAsyncSocket.h // 实现TCP传输
GCDAsyncSocket.m
GCDAsyncUdpSocket.h // 实现UDP传输
GCDAsyncUdpSocket.m

1.UDP的使用

Step 1:创建实例instance
GCDAsyncUdpSocket
Step 2:连接UDP到特定端口
这里我们使用这个类中的方法:

1)连接API:bindToPort:error:
2)接收数据API:beginReceiving:
3)关闭API:close

Step 3:接收UDP数据
通过delegate方法
UDPsocket已收到数据
Step 4:发送UDP数据

2、TCP的使用

Step 1:创建实例instance GCDAsyncSocket类
Step 2:连接TCP
Step 3:发送TCP数据
Step 4:接收数据
Step 5:数据处理 通过Delegate方法实现
// TCP socket已连接
// TCP socket已断开
// TCP socket已写入数据
支持多机连接,因此我们在每个EV3Device中处理数据。从EV3那边接收的任何数据包含端口数据这是在这里进行处理。
这里可以做一些设备相关的信息存储,比较灵活。
// TCP socket已发送数据

这篇文章也提供了源码:

songrotek/iOS_WiFi_EV3_Library

看一下资源结构

uml类图

类图的连接地址

EV3CommandDefinitions.h

这个是枚举的.h文件,将16进制的枚举全部写进来,typedef enum {
EV3ParameterSizeByte = 0x81, // 1 byte
EV3ParameterSizeInt16 = 0x82, // 2 bytes
EV3ParameterSizeInt32 = 0x83, // 4 bytes
EV3ParameterSizeString = 0x84 // null-terminated string
}EV3ParameterSize;

类似上文,这样写的时候引入枚举就能够进行16进制的拼接转化等就像这样`
- (void)addParameterWithInt8:(Byte)parameter
{
buffer[cursor] = EV3ParameterSizeByte;
cursor++;
buffer[cursor] = parameter;
cursor++;

EV3Device.h
EV3Device.m

这个是设备信息模型,会由EV3WifiManager.h 管理初始化和信息处理,连接到某个设备,以及EV3WifiManager管理多台设备的设备列表
设备来管理TCP的操作,因为每台设备才会和业务相关,因此将业务有关的控制机器人、路由器的操作都在这里 类内部只用了[self.tcpSocket writeData:data withTimeout:-1 tag:MESSAGE_CLEAR]; 这个方法

//EV3WifiManager中对设备的操作
// 连接或者断开ev3到iOS。连接之后,就可以发送直接命令了。
- (void)connectTCPSocketWithDevice:(EV3Device *)device;
 // udp接收到数据就要建立一个设备,给设备添加一个tcp的连接
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
{
 NSString *msg = [[NSString alloc]     initWithData:data  encoding:NSUTF8StringEncoding];
    if (msg)
    {
 NSString *serialNumber = [msg substringWithRange:NSMakeRange(14, 12)];
 //主机mac地址
 NSString *host = [GCDAsyncUdpSocket hostFromAddress:address];
 //取出device设备数据
 EV3Device *device = [self.devices objectForKey:host];
 //如果没有设备就信息
 if (!device && host.length < 20) {
  //初始化一个设备
  EV3Device *aDevice = [[EV3Device alloc] initWithSerialNumber:serialNumber address:host tag:self.devices.count isConnected:NO];
 // 启动 TCP/IP socket
 dispatch_queue_t tcpSocketQueue = dispatch_queue_create("com.manmanlai.tcpSocketQueue", DISPATCH_QUEUE_CONCURRENT);
 GCDAsyncSocket *tcpSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:tcpSocketQueue];
 //把这个tcpSocket 给设备的tcpSocket对象
aDevice.tcpSocket = tcpSocket;
// 将设备添加到设备列表里
[self.devices setObject:aDevice forKey:aDevice.address];
//发送消息去刷新列表
if ([self.delegate respondsToSelector:@selector(updateView)]) {
 dispatch_async(dispatch_get_main_queue(), ^{
                    [self.delegate updateView];
                });
            }
        }
    }
    else
    {
        NSLog(@"Error converting received data into UTF-8 String");
    }
//udp发送数据 --------
[self.udpSocket sendData:data toAddress:address withTimeout:-1 tag:0];
}
//tcp发送数据 --------
#pragma mark - GCDAsyncSocket
- (void)connectTCPSocketWithDevice:(EV3Device *)device
{   //获取到设备socket并且建立连接时在这里,这样设备里面可以克控制这个socket ,这些代理方法也能够控制socket,这样变得两个类都能对tcpsocket进行控制,可能需要把当前的这些操作打包给device类来做,来减少依赖关系。
//作者在这里这样使用应该是为了同时能够管理udp连接和tcp设备管理所有的socket问题,
   //获取到tcp socket 
    GCDAsyncSocket *tcpSocket = device.tcpSocket;
    // 建立连接
    NSError *error = nil;
    if (![tcpSocket connectToHost:device.address
                                onPort:5555
                                 error:&error])
    {
        NSLog(@"Error connecting: %@", error);

    } else {
        NSLog(@"Connected");
        // write data
        NSLog(@"writing...");
        NSString *unlockMsg = [NSString stringWithFormat:@"GET /target?sn=%@ VMTP1.0 Protocol: EV3",device.serialNumber];
        NSData *unlockData = [unlockMsg dataUsingEncoding:NSUTF8StringEncoding];
        //写数据
        [tcpSocket writeData:unlockData withTimeout:-1 tag:MESSAGE_UNLOCK];
        //读取数据
        [tcpSocket readDataWithTimeout:-1 tag:MESSAGE_UNLOCK];  
    }
}
- (void)disconnectTCPSocketWithDevice:(EV3Device *)device
{
    //设备停止扫描
    [device stopScan];
    //设备断开连接
    [device.tcpSocket disconnect];
    //设备列表移除这个设备地址-----我的app需求可能不太一样这里
    [self.devices removeObjectForKey:device.address];
    //刷新界面
    if ([self.delegate respondsToSelector:@selector(updateView)]) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.delegate updateView];
        });
    }
}

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{ 
    NSString *host = sock.connectedHost;
    EV3Device *device = [self.devices objectForKey:host];
    [device handleReceivedData:data withTag:tag];
}

EV3DirectCommander.h
EV3DirectCommander.m

16进制操作的类,所有16进制的操作都会在这里,参数的发送都在这里,EV3Device设备管理了业务的收发,而收发消息的过程中,都需要进行16进制的拼接,就引入了这个类,

使用的时候就一直调用+方法,具体例子
NSData *data = [EV3DirectCommander turnMotorAtPort:port power:power];
[self.tcpSocket writeData:data withTimeout:-1 tag:MESSAGE_NO_REPLY];
至于内部---调用初始化方法后添加必要参数返回即可
+ (NSData *)playToneWithVolume:(int)volume frequency:(UInt16)frequency duration:(UInt16)duration
{
EV3DirectCommander *command = [[EV3DirectCommander alloc] initWithCommandType:EV3CommandTypeDirectNoReply globalSize:0 localSize:0];
[command addOperationCode:EV3OperationSoundTone];
[command addParameterWithInt8:(Byte)volume];
[command addParameterWithInt16:frequency];
[command addParameterWithInt16:duration];
return [command assembledCommandData];
}

宏定义ios向机器人发送信息的类型

define Ev3WifiFit_EV3MessageType_h
define MESSAGE_UNLOCK 1 // 发送ev3解锁信息
define MESSAGE_NO_REPLY 11
define MESSAGE_GET_SENSOR_TYPE_AND_MODE 12
define MESSAGE_READ_DATA 13
define MESSAGE_SCAN_PORTS 14
define MESSAGE_SCAN_SENSOR_TYPE_AND_MODE 15
define MESSAGE_SCAN_SENSOR_DATA 16
define MESSAGE_CLEAR 17
define MESSAGE_UNDEFINE 0
具体使用:
[self.tcpSocket writeData:data withTimeout:-1 tag:MESSAGE_NO_REPLY];

EV3Sensor.h
EV3Sensor.m

Device设备里的元器件,组成部分,每个设备有8个元器件

EV3WifiBrowserViewController.h
EV3WifiBrowserViewController.m

这个是简单的界面显示控制,对不同状态的连接情况显示不同的图表TableView

EV3WifiManager.h
EV3WifiManager.m

这个是单例管理类 ,添加到控制器中,遵循其代理方法,控制udp管理和设备tcp的管理

// 具体使用 
// init ev3WifiManager
self.ev3WifiManager = [EV3WifiManager sharedInstance];
self.ev3WifiManager.delegate = self;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(ev3DeviceConnected:) name:EV3DeviceConnectedNotification object:nil];

[self.ev3WifiManager startUdpSocket];
//[self.udpSocket close];
[self.ev3WifiManager stopUdpSocket];

//devices count info
NSUInteger count = [self.ev3WifiManager.devices  count];
EV3Device *device = [[self.ev3WifiManager.devices allValues] objectAtIndex:indexPath.row];

//connect device
[self.ev3WifiManager connectTCPSocketWithDevice:device];
[self.ev3WifiManager disconnectTCPSocketWithDevice:device]; 
#pragma mark - ev3 wifi manager delegate
- (void)updateView
{
    [self update];
}

GCDAsyncSocket.h
GCDAsyncSocket.m
GCDAsyncUdpSocket.h
GCDAsyncUdpSocket.m

是socket TCP 和UDP 需要包含的第三方库CocoaAsyncSocket

iOS高级理论:CocoaAsyncSocket 介绍与使用 CocoaAsyncSocket为Mac和iOS提供了易于使用和功能强大的异步套接字库,主要包含两个类:GCDAsyncSocket:用GCD搭建的基于TCP/IP协议的socket网络库GCDAsyncUdpSocket:用GCD搭建的基于UDP/IP协议的socket网络库.本文主要介绍 GCDAsyncSocket的使用,他是一个TCP库,建在Grand Central Dispatch上面的。TCP是面向连接的,面向流的,提供高可靠性服务。 阅读详情

相关推荐

ios-CocoaAsyncSocket模拟服务器和客户端的搭建.zip

CocoaAsyncSocket模拟服务器和客户端的搭建, 能实现客户端和服务器之间的发送和接受信息...

CocoaAsyncSocket学习

以下内容翻译自: http://code.google.com/p/cocoaasyncsocket/ CocoaAsyncSocket支持tcp和udp。其中: AsyncSocket类是支持TCP的 AsyncUdpSocket是支持UDP的 AsyncSocket是封装了CFSocket和CFSteam的TCP/IP socket网络库。它提供了异步操作,本地coc...

weixin_34232744的博客 238

STM32F103 RTC闹钟唤醒Stop模式的EXTI17中断实现

本文详细介绍了STM32F103如何通过RTC闹钟触发EXTI17中断实现从Stop模式的高效唤醒。针对低功耗应用场景,提供了完整的硬件配置、CubeMX设置及代码实现方案,包括时间格式转换、中断处理和功耗优化技巧,帮助开发者可靠实现定时唤醒功能。

ol78901234的博客 230

CocoaAsyncSocket UDP发送数据超过包大小限制(Message too long)

最近在做iOS上,基于UDP传输音视频时遇到的一个问题,这边纪录一下: 由于考虑实时性比较高,所以采用了 CocoaAsyncSocket 的UDP框架来实现,将视频切割成一帧帧的图片发给服务端,不过,在发送图片的过程中,发现: 当图片大于9k大小时,会发送失败; 在didclose代理方法里,会打印错误信息:Message too long func udpSocketDidClo...

weixin_34111819的博客 917

NRF52832调试方法1——HardFault_Handler问题定位

一、遇到问题 keil debug模式下,直接点击全速运行(Run)发现程序卡死,点击stop按钮后,停到了HardFault_Handler位置,如下图所示。 此时使用navigate backwards(蓝色左箭头)是无效的,找不到程序卡在哪里。 二、解决办法 此时首先观察register窗口 若Stack为MSP,则复制R13(SP)的值到memory观察窗的地址搜索栏。每一行显示连续的28个地址上的存储信息,每个地址上存有一个字节。 从第21个位置起的连续四个字节是LR的值,

小梁的博客 3650

Cadence Allegro 17.4学习记录开始02-原理图Capture CIS 17.4

Allegro的第一方网表与第三方网表有以下几个区别点;Ø 与Allegro实现交互式操作的是第一方网表,第三方网表时不可以实现交互式操作;Ø 第三方网表不能将器件的Value属性导入到PCB中,输出时以封装属性来代替Value属性,第一方网表是可以的;Ø 网表导入到PCB中时,第三方的网表需要指定事先指定好PCB封装库文件,并产生Device文件,才可以将网表导入到PCB中,第一方网表则可以直接导入。

qq_31444421的博客 1万+

iOS即时通讯进阶 - CocoaAsyncSocket源码解析(Connect篇)

原文前言:CocoaAsyncSocket是谷歌的开发者,基于BSD-Socket写的一个IM框架,它给Mac和iOS提供了易于使用的、强大的异步套接字库,向上封装出简单易用OC接口。省去了我们面向Socket以及数据流Stream等繁琐复杂的编程。本文为一个系列,旨在让大家了解CocoaAsyncSocket是如何基于底层进行封装、工作的。注:文中涉及代码...

MinggeQingchun的博客 1045

LeGO-LOAM运行kitti数据集

文章目录1. kitti-lego-loam2. 改动3. 实验结果4. evo轨迹测评 1. kitti-lego-loam 链接:kitti-lego-loam kitti-lego-loam提供了将kitti序列转化成rosbag的代码,在kittibag中. 需要注意下数据文件的存放顺序,以00序列为例: datafolder          |____results          &

Zlp19970106的博客 8703

【Appium踩坑】Building for iOS, but the linked and embedded framework ‘xxx‘ was built for iOS + iOS Simu

【Appium踩坑】Building for iOS, but the linked and embedded framework ‘xxx‘ was built for iOS + iOS Simulator

青禾tester 2034

CDO批量处理nc文件:5分钟搞定CMIP6数据双线性插值(附完整代码)

本文详细介绍了如何使用CDO工具链中的`remapbil`命令,快速实现CMIP6数据的批量双线性插值处理。通过环境配置、核心操作步骤、高级优化技巧及典型报错解决方案,帮助科研人员高效处理大规模nc文件,显著提升气象数据处理效率。

weixin_29267307的博客 291

horizon之为connection服务器配置证书

打开connection1服务器(connection2 同connection1)再输入connection1的IP地址 可通过域名和IP地址进行登录。这时候用域名登录就发现证书已经没有警告了。win+R 调出“运行”,输入mmc。connection2 同上。如果还有报错请重启一下服务器。打开connection1。可以把这个先删掉 没用。打开DC_01服务器。右键选择证书颁发机构。友好名称只能是vdm。重启之后就没有报错了。

送个祝福给小豪的博客 2959

Socket学习总结系列(二) -- CocoaAsyncSocket

这是系列的第二篇 这是这个系列文章的第二篇,要是没有看第一篇的还是建议看看第一篇,以为这个是接着第一篇梳理的 先大概的总结一下在上篇的文章中说的些内容: 1、 整理了一下做IM我们有那些途径,以及我们怎样选择最适合自己的 2、在做IM的时候协议你又该怎样选择,以及这些协议之间一些的对比等等 3、接下来梳理了一下Socket的我们该怎样理解,它的心跳,pingpong,重连机制等...

weixin_30454481的博客 254

专为AI打造的浏览器:内存占用仅为Chrome的1/9、比Chrome快11倍(Docker部署教程,支持飞牛nas等服务器部署)

🚀 专为AI打造的无头浏览器来了! 用Zig从零构建,内存仅Chrome的1/9,速度快11倍,原生CDP协议支持Docker部署,适合爬虫、自动化测试和AI代理应用。✨

XiaoqiangClub的博客 730

iOS即时通讯之CocoaAsyncSocket源码解析二

原文 前言 本文承接上文:iOS即时通讯之CocoaAsyncSocket源码解析一 上文我们提到了GCDAsyncSocket的初始化,以及最终connect之前的准备工作,包括一些错误检查;本机地址创建以及socket创建;服务端地址的创建;还有一些本机socket可选项的配置,例如禁止网络出错导致进程关闭的信号等。 上文讲到了本文方法八--创建Socket,其中有这么一行代码: ...

weixin_30552811的博客 492

ASPICE标准快速掌握「总目录」

欢迎大家来到雪云飞星的《ASPICE标准快速掌握》,开始前博主先列出本专栏学习的大纲,同时这也可以作为大家学习ASPICE协议知识点的参考。本专栏可以帮助大家快速掌握如何在项目中使用ASPICE,ASPICE的学习通常仅需要半天时间左右,掌握方法后完全就可以结合快查表来指导具体项目的质量提升了。

雪云飞星的博客 3008

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

CocoaAsyncSocket网络通信使用之数据编码和解码(二)

在上一篇CocoaAsyncSocket网络通信使用之tcp连接(一)中,我们已经利用CocoaAsyncSocket封装了自己的socket connection。 本篇主要是通过引入编码器和解码器,将可以共用的内容模块化。 简述: 在tcp的应用中,都是以二机制字节的形式来对数据做传输。 一般会针对业务协议构造对应的数据结构/数据对象,然后在使用的时候针对协议转换成二进制数

銟麯的博客 915

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

[XMPP]简易的聊天室实现[二](使用CocoaAsyncSocket)

@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css); @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@...

weixin_30508241的博客 70

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

CocoaAsyncSocket--mac Or iOS下封装好的Socket编程库(二)

接下来的两篇,我就使用两个例子来说明下CocoaAsyncSocket的基本使用方法。 首先,在这里,先看看服务端的例子。这里使用的是EchoServer,例子在上一篇的github地址里面可以下载到。 由于这个服务端是mac下的应用,对于只做iOS客户端的我来说,这还真是比较新鲜的内容,不过看着看着,感觉还能明白,也算是略懂而已。 先看下初始化时候,做了哪些处理: - (id)ini...

weixin_34218890的博客 132

网络聊天室二 --- cocoaAsyncSocket客户端和服务端实现(实现客户端与服务器简单通信)...

一、流程图(思维导图) 二、代码如下 1、服务端 2、客户端 转载于:https://www.cnblogs.com/TheYouth/p/6407043.html

weixin_30423977的博客 145

使用CocoaAsyncSocket适配IPv6

处理近期很棘手的app因为IPv6的问题被苹果拒绝的问题,顺利审核通过

piratest的专栏 7153

CocoaAsyncSocket 使用指南

**CocoaAsyncSocket** 是一个专为 macOS、iOS 和 tvOS 设计的异步套接字网络库。它以 Grand Central Dispatch(GCD)为基础,提供了面向对象的、易于使用的Objective-C接口,简化了TCP/IP和UDP/IP网络编程。无论是构建服务器端监听还是客户端连接,该库都能提供强大的功能,支持IPv4/IPv6双栈,并且内置TLS/SSL安全特性。...

gitblog_00665的博客 1270

iOS开发之CocoaAsyncSocket使用

本文介绍了CocoaAsyncSocket库中GCDAsyncSocket类的使用、粘包处理以及时间延迟测试.一.CocoaAsyncSocket介绍CocoaAsyncSocket中主要包含两个类:1.GCDAsyncSocket. 用GCD搭建的基于TCP/IP协议的socket网络库 GCDAsyncSocket is a TCP/IP socket networking libra

路漫漫其修远兮,吾将上下而求索. 1852
上一篇: CocoaAsyncSocket
下一篇: mac 内网外网搭建
csdn_Damon
博客等级 码龄10年 37粉丝 143原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值