Socket TCP

前一段的做的项目使用的是Sockt TCP协议,在这家公司一直都是用的UDP,这一次做的集成控制平台,对数据的完整性要求比较严格,数据量也比较大所以使用了TCP协议,由于是第一次做TCP协议前前后后弄了一整天,

当数据量大的时候一般服务端会分包发送数据,但是我这后台使用的是一次性将数据都发送出去,由于数据太大,tcp会自己将数据拆分发送,我在刚开始的时候总是不能一次将数据接收完,是一个不完整的数据,数据都是以 “\n” 作为结束的标记,最后查了很多博客才弄好,下面是我的源码贴出来,希望看到的对你有帮助,

我的Socket TCP是基于第三方GCDAsyncSocket https://github.com/robbiehanson/CocoaAsyncSocket实现的,这个第三方封装的很好,用起来很方便

这里是我写的一个单例类方便数据的读取
//
//  DataHelp.h
//  N-mix
//
//  Created by chenq@kensence.com on 16/4/21.
//  Copyright © 2016年 times. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "GCDAsyncSocket.h"


@interface DataHelp : NSObject<GCDAsyncSocketDelegate>
@property (nonatomic ,strong)GCDAsyncSocket *ClientSocket;//Socket
@property (nonatomic ,strong)NSMutableData *mutData; //接受的数据
//创建单例
+(DataHelp *)shareData;

//连接服务器,在这我写一个方法方便使用
- (void)CreatTcpSocketWithIP:(NSString *)Host port:(uint16_t)Port;

@end
//
//  DataHelp.m
//  N-mix
//
//  Created by chenq@kensence.com on 16/4/21.
//  Copyright © 2016年 times. All rights reserved.
//

#import "DataHelp.h"
#import <UIKit/UIKit.h>
@interface DataHelp ()

@property (nonatomic ,strong)NSMutableArray *mutArray; //临时数组
@property (nonatomic ,strong)NSMutableArray *MutTXArray;
@end
@implementation DataHelp

//GCD单例方法
+ (DataHelp *)shareData
{
    static DataHelp * help = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        help = [DataHelp new];
    });
    return help;   
}




//创建连接
- (void)CreatTcpSocketWithIP:(NSString *)Host port:(uint16_t)Port
{

    //创建一个队列,等待接收数据
    dispatch_queue_t Queue = dispatch_queue_create("client tcp socket", NULL);
    //创建一个tcp和服务端通讯
    _ClientSocket  = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:Queue socketQueue:nil];

    //初始化一个Nsmutabledata用于接收数据
    _mutData = [NSMutableData data];

    //连接服务器 60s连接不上出错服务器在线时
    NSString *host = Host;
    uint16_t port = Port;
    //    _ClientSocket.delegate = self; //这里不用再写
    //连接服务器
    [_ClientSocket connectToHost:host onPort:port withTimeout:-1 error:nil];

}

#pragma mark ===代理方法

- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
{
    //连接成功
    NSLog(@"连接成功");
    [_ClientSocket readDataWithTimeout:-1 tag:200]; //读取数据,只有读取数据后面的代理方法DidReaddata这个代理方法才会走。


}

//连接失败重连
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
    //这里我是将IP port都保存在本地从本地直接去取
    NSString *host1 = [[NSUserDefaults standardUserDefaults]objectForKey:@"HostKey"];
    NSString *port1 = [[NSUserDefaults standardUserDefaults]objectForKey:@"PortKey"];

    //重新连接(如果连接失败就会自动继续连接)
    unsigned short utfString = [port1 integerValue]; 
    [_ClientSocket connectToHost:host1 onPort:utfString withTimeout:10 error:nil]; //这里的10是代表10秒后会继续执行,写成-1也可以代表不延时

}

- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
    NSLog(@"消息发送成功");

    //消息发送成功调用,这里必须调用,不然后面的DidReadData不会执行
    [_ClientSocket readDataWithTimeout:-1 tag:200];
}

//接受到服务器返回的数据
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    NSString *dataString = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
    if (_mutData == nil) {
        _mutData = [[NSMutableData alloc]init];

    }else
    {
        //拼接接受到的数据
        [_mutData appendData:data];
        //标记结束符 这里是以(“\n”)大多是以(\r\n),这个和后台的兄弟问
        NSRange rang = [dataString rangeOfString:@"\n"];
        if (rang.location != NSNotFound) { //一直向后找

            //由于接受到的数据都是data类型,这里转为string
            NSString *String = [[NSString alloc]initWithData:_mutData encoding:NSUTF8StringEncoding];
            NSLog(@"%@",String);

            //从string转为data
            NSData *data = [String dataUsingEncoding:NSUTF8StringEncoding];
    //再从data转回dictionary
            NSDictionary *AlDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
    }
    //这里调用和上面的一个一次,
  [_ClientSocket readDataWithTimeout:-1 tag:200];

}

- (void)dealloc
{
    [_ClientSocket disconnect];
    _ClientSocket = nil;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值