iOS Socket自定义数据格式传输协议

这片文章主要包括两个技术点:

  • 服务端和客户端示例(GCDAsyncSocket应用)
  • Socket自定义数据格式传输协议


利用GCDAsyncSocket写一个服务端的小案例

1.把GCDAsyncSocket.h/GCDAsyncSocket.m两个文件导入到项目中就可以了
2.案例分析流程

  • 1.服务器绑定端口
  • 2.监听客户端的连接
  • 3.允许客户端建立连接
  • 4.读取客户端的请求数据
  • 5.处理客户端的请求数据
  • 6.响应客户端的请求数据

3.服务是有开启和关闭的两个状态

4.接收客户端的请求数据时的注意点

  • 接收客户端的请求数据的代理方法是
    -(void)socket: didReadData:withTag:
  • 要使用这个代理方法读取数据前,需要调用一个方法 客户端的 readDataWithTimeout:tag:方法
  • 下次还想接收数据 ,也需要调用一个方法 客户端的 readDataWithTimeout:tag:方法
![Uploading Snip20170830_6_504104.png . . .]
Snip20170830_6.png

#import "ServerListener.h"
#import "GCDAsyncSocket.h"

@interface ServerListener ()<GCDAsyncSocketDelegate>

@property (strong, nonatomic)  GCDAsyncSocket *serverSocket;
@property (strong, nonatomic)  NSMutableArray *socketMarray;

@end
@implementation ServerListener

- (NSMutableArray *)socketMarray{
    if (_socketMarray == nil) {
        _socketMarray = [NSMutableArray array];
    }
    return _socketMarray;
}

- (void)start{
    
    
// 1.服务器绑定端口
    
    //1>创建服务对象,绑定端口
    self.serverSocket = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];
    NSError *error = nil;
    [self.serverSocket acceptOnPort:5288 error:&error];
    if (error) {
        NSLog(@"开启失败");
    }else{
        NSLog(@"开启成功");
    }
    
}
//2.监听客户端的连接
    //代理方法
- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket{
    NSLog(@"有链接");
    //3.允许客户端建立连接(防止释放,创建持久连接)
    [self.socketMarray addObject:newSocket];

    /*
     *  -1代表没有超时约束  0用不到
     */
    [newSocket readDataWithTimeout:-1 tag:0];
}
    
//3.允许客户端建立连接
//代理方法
#warning 使用这个代理之前必须调用一个方法(客户端方法)

//sock readDataWithTimeout:<#(NSTimeInterval)#> tag:<#(long)#>

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
    
    // 4.读取客户端的请求数据
    NSString *dataStr = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
#warning 想接受多次还要调用这方法
    [sock readDataWithTimeout:-1 tag:0];
    
    //5.处理客户端的请求数据
    //6.响应客户端的请求数据
    
    NSString *huida = @"我是回答\n";
    [sock writeData:[huida dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
    
    if ([dataStr isEqualToString:@"esc\r\n"]) {
        [self.socketMarray removeObject:sock];
        
    }
}




- (void)stop{

}

Snip20170830_7.png
Snip20170831_1.png

-----------------------------------------------

利用GCDAsyncSocket写一个客户端的小案例

Socket的客户端编程

  • 1.连接到服务器(IP+Port)
  • 2.监听连接服务器是否成功
  • 3.如果连接成功,就可发送消息给服务器
  • 4.监听服务器转发过来的消息

(其中在接受服务端发来数据刷新的时候需要在主线程刷新,因为接收是在子线程里接收)


#import "ViewController.h"
#import "GCDAsyncSocket.h"

@interface ViewController ()<GCDAsyncSocketDelegate>
@property (weak, nonatomic) IBOutlet UITextField *field;
@property(nonatomic,strong)GCDAsyncSocket *clientSocket;
@property(nonatomic,strong)NSMutableArray *messages;
@end

//1.连接到服务器(IP+Port)
//2.监听连接服务器是否成功
//3.如果连接成功,就可发送消息给服务器
//4.监听服务器转发过来的消息
//5.发送时,刷新表格显示数据
//6.接收聊天消息时,刷新表格显示数据
@implementation ViewController

-(NSMutableArray *)messages{
    if(!_messages){
        _messages = [NSMutableArray array];
    }
    
    return _messages;
}

//1.连接到服务器(IP+Port)
- (IBAction)connectToHostAction:(id)sender {
    //创建一个Socket对象
    self.clientSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];
    
    //连接服务器
    NSError *err = nil;
    [self.clientSocket connectToHost:@"192.168.8.111" onPort:5288 error:&err];
    
    //err实际上没有什么太大的作用
    if(!err){
        NSLog(@"连接请求发送成功");
    }else{
        NSLog(@"连接请求发送失败");
    }
    
}

//2.监听连接服务器是否成功
-(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{
 
    NSLog(@"连接服务器成功");
#warning 调用下面的方法,目的是为了读取数据的代理方法能调用
    [self.clientSocket readDataWithTimeout:-1 tag:0];
}

-(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{
    NSLog(@"连接服务器失败 %@",err);
}


//3.如果连接成功,就可发送消息给服务器
- (IBAction)sendAction:(id)sender {
    
    //获取发送的聊天内容
    NSString *text = self.field.text;
    
    //添加换行
    text = [NSString stringWithFormat:@"%@\n",text];
    
    //发送
    [self.clientSocket writeData:[text dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
    
    //清空内容
    self.field.text = nil;
    
    //5.发送时,刷新表格显示数据
    [self.messages addObject:text];
    
    [self.tableView reloadData];


}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}



//4.监听服务器转发过来的消息
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
    //默认读取数据的方法是不会调用
    //Data - String
    NSString *recStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    
    #warning 调用下面的方法,目的是为了下次还能接收数据
    [self.clientSocket readDataWithTimeout:-1 tag:0];
    
    NSLog(@"%@",recStr);
    NSLog(@"%@",[NSThread currentThread]);
    
    //6.接收聊天消息时,刷新表格显示数据
    [self.messages addObject:recStr];
    
#warning 此方法是在是在子线程调用的,所以不能刷新UI
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        [self.tableView reloadData];
    }];
}



#pragma 表格数据源方法
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return self.messages.count;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    static NSString *ID = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    if(cell == nil){
        cell = [[UITableViewCell alloc] initWithStyle:0 reuseIdentifier:ID];
    }
    
    //显示内容
    cell.textLabel.text = self.messages[indexPath.row];
    
    return cell;
    
}
@end


自定义数据格式传输协议(重点)

实现目标:想传输一个较大的文件给服务端
存在问题:传输时候不能保证一次性传输

Snip20170831_3.png

代码在下面这里主要讲解一下这张图片和这段代码,socket通信报文要保留前8个字节 是前四位指定文件总大小,后四位是文件传输格式,除了定义请求头,还要定义响应!!!!

其实主要思路就是根据下图所示,传输的时候一块一块向下扒,在三方监听方法里监听data

  • 第一次扒文件大小

  • 第二层扒文件格式

  • 第三次扒文件主体


    Snip20170831_4.png
// 把图片转在NSData
    UIImage *img = [UIImage imageNamed:@"IMG_2427.JPG"];
    NSData *imgData = UIImagePNGRepresentation(img);

    
    //定义数据格式传输协议
    //请求头和请求体 / 响应头和响应体
    
    NSMutableData *totalDataM = [NSMutableData data];
    
    // 1.拼接长度(0~3:长度)
    unsigned int totalSize = 4 + 4 + (int)imgData.length;
    NSData *totalSizeData = [NSData dataWithBytes:&totalSize length:4];
    [totalDataM appendData:totalSizeData];
    
    // 2.拼接指令类型(4~7:指令) 这里就是请求头,用于判断你的床底数据类型
    // 0x00000001 = 图片
    // 0x00000002 = 文字
    // 0x00000003 = 位置
    // 0x00000004 = 语音
    unsigned int commandId = 0x00000001;
    NSData *commandIdData = [NSData dataWithBytes:&commandId length:4];
    [totalDataM appendData:commandIdData];
    
    // 3.拼接图片(8~N) 图片数据
    [totalDataM appendData:imgData];
  
    // 发数据
    [self.clientSocket writeData:totalDataM withTimeout:-1 tag:0];

完整代码


#import "ViewController.h"
#import "GCDAsyncSocket.h"

@interface ViewController ()<GCDAsyncSocketDelegate>


@property (weak, nonatomic) IBOutlet UILabel *statusLabel;

/** 客户端的Socket */
@property (nonatomic ,strong) GCDAsyncSocket *clientSocket;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

//与服务器连接
- (IBAction)connectToHost:(id)sender {
 
    // 1.创建一个socket对象
    if (self.clientSocket == nil) {
        self.clientSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    }
    
    // 2.连接服务器
    NSError *error = nil;
    [self.clientSocket connectToHost:@"127.0.0.1" onPort:5288 error:&error];
    if (error) {
        NSLog(@"%@",error);
    }
    
}

// 与服务器连接成功
-(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{

    self.statusLabel.text = @"连接中..";
    self.statusLabel.backgroundColor = [UIColor greenColor];
    
#warning 读取数据
    [sock readDataWithTimeout:-1 tag:0];
}


-(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{
    NSLog(@"%@",err);
    self.statusLabel.text = @"断开..";
    self.statusLabel.backgroundColor = [UIColor redColor];
}

// 与服务器断开
- (IBAction)closeToHost:(id)sender {
    [self.clientSocket disconnect];
}

// 发图片
- (IBAction)sendImag:(id)sender {
    
    // 把图片转在NSData
    UIImage *img = [UIImage imageNamed:@"IMG_2427.JPG"];
    NSData *imgData = UIImagePNGRepresentation(img);

    
    //定义数据格式传输协议
    //请求头和请求体 / 响应头和响应体
    
    NSMutableData *totalDataM = [NSMutableData data];
    
    // 1.拼接长度(0~3:长度)
    unsigned int totalSize = 4 + 4 + (int)imgData.length;
    NSData *totalSizeData = [NSData dataWithBytes:&totalSize length:4];
    [totalDataM appendData:totalSizeData];
    
    // 2.拼接指令类型(4~7:指令)
    // 0x00000001 = 图片
    // 0x00000002 = 文字
    // 0x00000003 = 位置
    // 0x00000004 = 语音
    unsigned int commandId = 0x00000001;
    NSData *commandIdData = [NSData dataWithBytes:&commandId length:4];
    [totalDataM appendData:commandIdData];
    
    // 3.拼接图片(8~N) 图片数据
    [totalDataM appendData:imgData];
    NSLog(@"图片的字节大小:%ld",imgData.length);
    NSLog(@"发送数据的总字节大小:%ld",totalDataM.length);
    
    // 发数据
    [self.clientSocket writeData:totalDataM withTimeout:-1 tag:0];
}


- (IBAction)sendText:(id)sender {
    
    NSString *text = @"Hello,自定义协议";
    NSData *textData = [text dataUsingEncoding:NSUTF8StringEncoding];
    
    NSMutableData *totalDataM = [NSMutableData data];
    
    // 1.拼接长度(0~3:长度)
    unsigned int totalSize = 4 + 4 + (int)textData.length;
    NSData *totalSizeData = [NSData dataWithBytes:&totalSize length:4];
    [totalDataM appendData:totalSizeData];
    
    // 2.拼接指令类型(4~7:指令)
    // 0x00000001 = 图片
    // 0x00000002 = 文字
    // 0x00000003 = 位置
    // 0x00000004 = 语音
    unsigned int commandId = 0x00000002;
    NSData *commandIdData = [NSData dataWithBytes:&commandId length:4];
    [totalDataM appendData:commandIdData];
    
    // 3.拼接(8~N) 文字数据
    [totalDataM appendData:textData];
    
    
    //发送
    [self.clientSocket writeData:totalDataM withTimeout:-1 tag:0];
    
    
}

// 接收服务器响应的数据
-(void)socket:(GCDAsyncSocket *)clientSocket didReadData:(NSData *)data withTag:(long)tag{

    /**
     *  解析服务器返回的数据
     */
    
    // 获取总的数据包大小
    NSData *totalSizeData = [data subdataWithRange:NSMakeRange(0, 4)];
    unsigned int totalSize = 0;
    [totalSizeData getBytes:&totalSize length:4];
    NSLog(@"响应总数据的大小 %u",totalSize);
    
    
    // 获取指令类型
    NSData *commandIdData = [data subdataWithRange:NSMakeRange(4, 4)];
    unsigned int commandId = 0;
    [commandIdData getBytes:&commandId length:4];
    
    // 结果
    NSData *resultData = [data subdataWithRange:NSMakeRange(8, 4)];
    unsigned int result = 0;
    [resultData getBytes:&result length:4];
    
    
    NSMutableString *str = [NSMutableString string];
    if (commandId == 0x00000001) {//图片
        [str appendString:@"图片 "];
    }else if(commandId == 0x00000002){//文字
        [str appendString:@"文字 "];
    }
    
    
    if(result == 1){
        [str appendString:@"上传成功"];
    }else{
        [str appendString:@"上传失败"];
    }
    
    NSLog(@"%@",str);
    
    
#warning 可以接收下一次数据
    [clientSocket readDataWithTimeout:-1 tag:0];
    
}

自定义协议服务端

#import "ServerListener.h"
#import "GCDAsyncSocket.h"

#define kCommandId_Img 0x00000001// = 图片
#define kCommandId_Txt 0x00000002// = 文字
#define kCommandId_Location 0x00000003// = 位置
#define kCommandId_Voice 0x00000004// = 语音

@interface ServerListener()<GCDAsyncSocketDelegate>
/** 服务端的Socket对象 */
@property (nonatomic ,strong) GCDAsyncSocket *serverSocket;
/** 客户端的Socket数组 */
@property (nonatomic ,strong) NSMutableArray *clientSockets;

/** <#注释#> */
@property (nonatomic ,strong) NSMutableData *dataM;

/** 总的数据包大小*/
@property(nonatomic ,assign)unsigned int totalSize;

/**当前的指令类型*/
@property(nonatomic ,assign)unsigned int currentCommandId;
@end

@implementation ServerListener


-(NSMutableData *)dataM{
    if (!_dataM) {
        _dataM = [NSMutableData data];
    }
    
    return _dataM;
}

-(NSMutableArray *)clientSockets{
    if (!_clientSockets) {
        _clientSockets = [NSMutableArray array];
    }
    
    return _clientSockets;
}

-(void)start{
    // 1.创建一个服务端的Socket对象
    self.serverSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];
    
    // 2.绑定端口监听
    NSError *error = nil;
#warning 失败原因:端口号被占用
    BOOL success = [self.serverSocket acceptOnPort:5288 error:&error];
    if (success == YES) {
        NSLog(@"服务开启成功");
    }else{
        NSLog(@"服务开启失败");
    }
}

// 新的socket客户端连接
-(void)socket:(GCDAsyncSocket *)serverSocket didAcceptNewSocket:(GCDAsyncSocket *)clientSocket{
    NSLog(@"当前客户端的IP:%@ 端口号%d",clientSocket.connectedHost,clientSocket.connectedPort);
    
    
    
    // 1.存储客户端面的Socket对象
    [self.clientSockets addObject:clientSocket];
    NSLog(@"当前有%ld个客户端连接",self.clientSockets.count);
    
    // 2.客户连接建立后,设置可以读取数据
    [clientSocket readDataWithTimeout:-1 tag:0];
    
}

// 读取客户端面提交数据
-(void)socket:(GCDAsyncSocket *)clientSocket didReadData:(NSData *)data withTag:(long)tag{
    // 1.第一次接收数据
    if(self.dataM.length == 0){
        // 获取总的数据包大小
        NSData *totalSizeData = [data subdataWithRange:NSMakeRange(0, 4)];
        unsigned int totalSize = 0;
        [totalSizeData getBytes:&totalSize length:4];
        NSLog(@"接收总数据的大小 %u",totalSize);
        self.totalSize = totalSize;
        
        
        // 获取指令类型
        NSData *commandIdData = [data subdataWithRange:NSMakeRange(4, 4)];
        unsigned int commandId = 0;
        [commandIdData getBytes:&commandId length:4];
        self.currentCommandId = commandId;
        switch (commandId) {
            case kCommandId_Img:
                NSLog(@"此次请求是上传图片 ");
                break;
            case kCommandId_Txt:
                NSLog(@"此次请求是上传文字");
                break;
            default:
                break;
        }
    }
    
    // 2.拼接二进度
    [self.dataM appendData:data];
    
    // 3.图片数据已经接收完成
    // 判断当前是否是图片数据的最后一段?
    NSLog(@"此次接收的数据包大小 %ld",data.length);
    if (self.dataM.length == self.totalSize) {
        NSLog(@"数据已经接收完成");
        if (self.currentCommandId == kCommandId_Img) {//图片
            [self saveImage];
        }else if(self.currentCommandId == kCommandId_Txt){//文字
            [self handleText];
        }
        
        
        // 响应客户端
        [self responseToClient:clientSocket];
        
    }
    
    
    
#warning 接收下一次的数据
    [clientSocket readDataWithTimeout:-1 tag:0];
}


-(void)responseToClient:(GCDAsyncSocket *)clientSocket{
    //1.总的字节长度
    unsigned int totalSize = 4 + 4 + 4;
    NSData *totalSizeData = [NSData dataWithBytes:&totalSize length:4];
    
    //2.响应指令类型
    unsigned int commandId = self.currentCommandId;
    NSData *commandIdData = [NSData dataWithBytes:&commandId length:4];
    
    //3.上传的结果 //1:上传成功 0://上传失败
    unsigned int result = 0;
    NSData *resultData = [NSData dataWithBytes:&result length:4];
    
    NSMutableData *totalData = [NSMutableData data];
    [totalData appendData:totalSizeData];
    [totalData appendData:commandIdData];
    [totalData appendData:resultData];
    
    // 写入
    [clientSocket writeData:totalData withTimeout:-1 tag:0];
}

-(void)handleText{
    
    // 1.截取文字NSData
    NSData *txtData = [self.dataM subdataWithRange:NSMakeRange(8, self.dataM .length - 8)];
    
    // 2.转化字符串
    NSString *receviceStr = [[NSString alloc] initWithData:txtData encoding:NSUTF8StringEncoding];
    NSLog(@"%@",receviceStr);
    
    // 重新赋值
    self.dataM = [NSMutableData data];

}


-(void)saveImage{
    // 4.把图片写入一个文件
    // 4.1获取图片的NSData
    NSData *imgData = [self.dataM subdataWithRange:NSMakeRange(8, self.dataM.length - 8)];
    
    // 4.2生成图片路径
    NSString *imgPath = @"/Users/a1/Desktop/img/xxxx.png";
    
    // 写入文件
    [imgData writeToFile:imgPath atomically:YES];
    
    // 清除数据
    self.dataM = [NSMutableData data];
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,817评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,329评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,354评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,498评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,600评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,829评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,979评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,722评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,189评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,519评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,654评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,940评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,762评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,993评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,382评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,543评论 2 349

推荐阅读更多精彩内容

  • socket,究竟是什么东东,面试时,笔试有他,面试也有他,如果做智能硬件,肯定会用到socket,所以,今天带大...
    AirZilong阅读 2,401评论 2 24
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,633评论 18 139
  • 一、网络各个协议:TCP/IP、SOCKET、HTTP等 网络七层由下往上分别为物理层、数据链路层、网络层、传输层...
    杯水救车薪阅读 2,260评论 0 17
  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,930评论 6 13
  • 第一部分、概念的理解1、什么是Socket?Socket又称之为“套接字”,是系统提供的用于网络通信的方法。它的实...
    Hevin_Chen阅读 2,444评论 0 5