SocketUdp的实现代码
2015-12-16 16:42
246 查看
socketUdp的使用
在我们与硬件进行通讯的时候将使用到socket通讯协议,我在做socket时使用的是简单的收发数据,核心就在于一个IP地址和Port端口号,至于需不需要绑定端口号,我在做UDP时是没有绑定端口号,下面我把具体的代码放在上面供大家参考:在操作之前首先先要到github上下载GCDAsyncUdpScoket一个第三方封装的socket方法[这是socket封装的地址]:https://github.com/search?utf8=%E2%9C%93&q=asyncsocket
//服务端的代码 #import <UIKit/UIKit.h> //包含了udp的socket(GCD/Blocks版本) #import "GCDAsyncUdpSocket.h" //这是一个接收 消息界面 @interface ViewController : UIViewController<GCDAsyncUdpSocketDelegate>{ //udp对象 GCDAsyncUdpSocket *udpServerSoket; } @end #import "ViewController.h" #import "SendViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.navigationItem.title = @"接收消息"; [self showNavItem]; [self createUdpSocket]; } -(void)showNavItem{ UIBarButtonItem *sendMyself = [[UIBarButtonItem alloc] initWithTitle:@"发送自己" style:UIBarButtonItemStylePlain target:self action:@selector(sendMyself)]; self.navigationItem.rightBarButtonItem = sendMyself; } -(void)sendMyself{ SendViewController *svc = [[SendViewController alloc] init]; [self.navigationController pushViewController:svc animated:YES]; } -(void) createUdpSocket{ //创建一个后台队列 等待接收数据 dispatch_queue_t dQueue = dispatch_queue_create("My socket queue", NULL); //第一个参数是该队列的名字 //1.实例化一个udp socket套接字对象 // udpServerSocket需要用来接收数据 udpServerSoket = [[GCDAsyncUdpSocket alloc]initWithDelegate:self delegateQueue:dQueue socketQueue:nil]; //2.服务器端来监听端口12345(等待端口12345的数据) [udpServerSoket bindToPort:12345 error:nil]; //3.接收一次消息(启动一个等待接收,且只接收一次) [udpServerSoket receiveOnce:nil]; } #pragma mark -GCDAsyncUdpSocketDelegate -(void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data fromAddress:(NSData *)address withFilterContext:(id)filterContex { //取得发送发的ip和端口 NSString *ip = [GCDAsyncUdpSocket hostFromAddress:address]; uint16_t port = [GCDAsyncUdpSocket portFromAddress:address]; //data就是接收的数据 NSString *s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"[%@:%u]%@",ip, port,s); [self sendBackToHost: ip port:port withMessage:s]; //再次启动一个等待 [udpServerSoket receiveOnce:nil]; } -(void)sendBackToHost:(NSString *)ip port:(uint16_t)port withMessage:(NSString *)s{ NSString *msg = @"我已接收到消息"; NSData *data = [msg dataUsingEncoding:NSUTF8StringEncoding]; [udpServerSoket sendData:data toHost:ip port:port withTimeout:60 tag:200]; } @end //客户端代码 #import <UIKit/UIKit.h> #import "GCDAsyncUdpSocket.h" @interface SendViewController : UIViewController<GCDAsyncUdpSocketDelegate>{ //这个socket用来做发送使用 当然也可以接收 GCDAsyncUdpSocket *sendUdpSocket; } @end #import "SendViewController.h" @implementation SendViewController #pragma mark ===发送指令==== - (void)SendMessage:(UIButton *)Send { NSString *host = @"192.168.12.12" //IP地址 uint16_t port = 8080//port端口号; //初始化udpsocket udpSocket = [[GCDAsyncUdpSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)]; //开始发送 //改函数只是启动一次发送 它本身不进行数据的发送, 而是让后台的线程慢慢的发送 也就是说这个函数调用完成后,数据并没有立刻发送,异步发送 /* unsigned char sendout[512]={0}; unsigned int i= 0; for( ; i < _RemoveArray.count; i++) { NSNumber *b = _RemoveArray[i]; sendout[i] = (unsigned char)b.intValue; } int Intag = 0; for (int i = 0; i < _InArray.count; i++) { NSNumber *number = _InArray[i]; Intag = number.intValue; } kice_t kic = signal_map_cmd(Intag, sendout, i , [SignalValue ShareValue].Integer);*/ //以上注释的是我做的data数据,使用C++写的命令做成IOS中NSData类型的数据 //这里是你要发送的数据为data类型的数据; NSData *data = [NSData dataWithBytes:(void *)&kic length:kic.size]; [udpSocket sendData:data toHost:host port:port withTimeout:60 tag:200]; //这里的withTimeout没有实际的意义,只是做一个标记用的tag也是一样,只是在下面的代理方法中标示一下是否是发送成功还是失败,返回的信息方便我们知道状态; //bind端口,可以写可以不写,建议不写在实际的操作中在某一个页面如果没有发送指令,本页面的其他发送数据指令后是接受不到数据的,不写就可以操作 [udpSocket bindToPort:_port error:nil]; [udpSocket receiveOnce:nil]; //表示只接受一次数据 // [[SignalValue ShareValue].GetMessage removeAllObjects];//这个是自己本人写的,对数组的操作,不要写 } #pragma mark === udpSocket执行的代理方法======= //发送成功 -(void)udpSocket:(GCDAsyncUdpSocket *)sock didSendDataWithTag:(long)tag { if (tag == 200) { NSLog(@"标记为200的数据发送完成了"); } } //发送失败 - (void)udpSocket:(GCDAsyncUdpSocket *)sock didNotSendDataWithTag:(long)tag dueToError:(NSError *)error { // NSLog(@"标记为tag %ld的发送失败 失败原因 %@",tag,error); } //接收数据成功后执行的方法 -(void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data fromAddress:(NSData *)address withFilterContext:(id)filterContext { //这几部是固定的格式三步 NSString *ip = [GCDAsyncUdpSocket hostFromAddress:address]; uint16_t port = [GCDAsyncUdpSocket portFromAddress:address]; NSString *str = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]; /*注释部分是我自己在接受导数据后做的处理,接受到数据后怎么处理就看自己的了 unsigned char *a= [data bytes]; kice_t *kic = (kice_t *)a; unsigned char cmd = kic->data[0]; if(cmd == 0x27) { sw_state_t *sw = (sw_state_t *)(&((kice_t *)a)->data[3]); _count = (unsigned int)(sw->input); [SignalValue ShareValue].Integer = _count; unsigned int buf[512] ={0}; for(int i = 0; i < _count; i++) { buf[i] = (unsigned char)sw->group[_count + i]; NSInteger value = (NSInteger)buf[i]; NSNumber *number = [NSNumber numberWithInteger:value]; [[SignalValue ShareValue].GetMessage addObject:number]; } } */ [sock receiveOnce:nil]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self SendBackToHost:ip port:port withMessage:str]; }); } -(void)SendBackToHost:(NSString *)ip port:(uint16_t)port withMessage:(NSString *)str { NSString *Msg = @"我在发送消息"; NSData *data = [Msg dataUsingEncoding:NSUTF8StringEncoding]; [udpSocket sendData:data toHost:ip port:[SignalValue ShareValue].SignalPort withTimeout:60 tag:201]; }
以上是我在开发中写的客户端的代码,UDP是一种面向无连接实现起来很简单,注意线程问题在使用中,传值时可能会出现显示慢的问题,这时只要在主线程中操作返回的数据就好了代码如下
dispatch_async(dispatch_get_main_queue(), ^{ //在这里操作数据 }
相关文章推荐
- 老李分享:JAVA性能监控工具
- php将远程图片下载保存到本地
- C++ 获取变量名称 & 获取类型的名称
- 老李分享:《Java Performance》笔记2——JVM命令行选项及垃圾收集日志解析 2
- zend studio 8 提示和代码字体如何修改
- 老李分享:《Java Performance》笔记2——JVM命令行选项及垃圾收集日志解析 1
- struts_05 各种验证器,ognl表达式,struts2常用标签,防止表单重复提交,jfreeChart插件的运用
- 老李分享:《Java Performance》笔记1——性能分析基础 2
- 老李分享:《Java Performance》笔记1——性能分析基础 1
- Java多线程总结(4)— 线程范围内数据操作的隔离及ThreadLocal类
- struts2_04 常见servlet对象的获取,文件上传
- struts2_03 自定义类型转换器 拦截器
- PDO浅谈之php连接mysql
- Spring下面的@Transactional注解标志的讲解
- struts2_02
- struts2_01
- Java获取当前日期的前一个月,前一天的时间
- Python的流程控制
- python os.system os.popen 区别
- java处理url中的特殊字符%等