美文网首页
socket client 篇章

socket client 篇章

作者: f8d1cf28626a | 来源:发表于2022-07-12 06:20 被阅读0次

    socket

    • 查看端口 lsof -i:8040

    • 杀掉端口 kill -9 17870

    • socket 是一个抽象层的API,具备双向性

    • 127.0.0.1 和本地回环地址进行通讯

    终端 拦截代理

    • nc -l 8040
    c: missing hostname and port
    usage: nc [-46AacCDdEFhklMnOortUuvz] [-K tc] [-b boundif] [-i interval] [-p source_port]
          [--apple-recv-anyif] [--apple-awdl-unres]
          [--apple-boundif ifbound]
          [--apple-no-cellular] [--apple-no-expensive]
          [--apple-no-flowadv] [--apple-tcp-timeout conntimo]
          [--apple-tcp-keepalive keepidle] [--apple-tcp-keepintvl keepintvl]
          [--apple-tcp-keepcnt keepcnt] [--apple-tclass tclass]
          [--tcp-adp-rtimo num_probes] [--apple-initcoproc-allow]
          [--apple-tcp-adp-wtimo num_probes]
          [--setsockopt-later] [--apple-no-connectx]
          [--apple-delegate-pid pid] [--apple-delegate-uuid uuid]
          [--apple-kao] [--apple-ext-bk-idle]
          [--apple-netsvctype svc] [---apple-nowakefromsleep]
          [--apple-notify-ack] [--apple-sockev]
          [--apple-tos tos] [--apple-tos-cmsg]
          [-s source_ip_address] [-w timeout] [-X proxy_version]
          [-x proxy_address[:port]] [hostname] [port[s]]
    

    解释

    目的主机监听
    nc -l 监听端口<未使用端口>  > 要接收的文件名
    nc -l 4444 > cache.tar.gz
     
    源主机发起请求
    nc  目的主机ip    目的端口 < 要发送的文件
    nc  192.168.0.85  4444 < /root/cache.tar.gz
     
    netstat  如下
    
    netstat -tpln
     
    tcp        0      0 0.0.0.0:4444                0.0.0.0:*                   LISTEN      18166/nc  
     
    英文描述如下
     
    DATA TRANSFER
     
     Start by using nc to listen on a specific port, with output captured into a file:
               $ nc -l 1234 > filename.out
     Using a second machine, connect to the listening nc process, feeding it the file which is to be transferred:
               $ nc host.example.com 1234 < filename.in
     
     
    另附nc的其他选项说明:
     
    语  法:nc [-hlnruz][-g<网关...>][-G<指向器数目>][-i<延迟秒数>][-o<输出文件>][-p<通信端口>][-s<来源位址>][-v...][-w<超时秒数>][主机名称][通信端口...]
    
    补充说明:执行本指令可设置路由器的相关参数。
    
    参  数:
      -g<网关>   设置路由器跃程通信网关,最丢哦可设置8个。
      -G<指向器数目>   设置来源路由指向器,其数值为4的倍数。
      -h   在线帮助。
      -i<延迟秒数>   设置时间间隔,以便传送信息及扫描通信端口。
      -l   使用监听模式,管控传入的资料。
      -n   直接使用IP地址,而不通过域名服务器。
      -p<通信端口>   设置本地主机使用的通信端口。
      -r   乱数指定本地与远端主机的通信端口。
      -s<来源位址>   设置本地主机送出数据包的IP地址。
      -u   使用UDP传输协议。
      -v   显示指令执行过程。
      -w<超时秒数>   设置等待连线的时间。
      -z   使用0输入/输出模式,只在扫描通信端口时使用
    
    • socket 参数描述
    /**
         1: 创建socket
         参数
         domain:协议域,又称协议族(family)。常用的协议族有AF_INET、AF_INET6、AF_LOCAL(或称AF_UNIX,Unix域Socket)、AF_ROUTE等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。
         
         type:指定Socket类型。常用的socket类型有SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等。流式Socket(SOCK_STREAM)是一种面向连接的Socket,针对于面向连接的TCP服务应用。数据报式Socket(SOCK_DGRAM)是一种无连接的Socket,对应于无连接的UDP服务应用。
        
         protocol:指定协议。常用协议有IPPROTO_TCP、IPPROTO_UDP、IPPROTO_STCP、IPPROTO_TIPC等,分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。
         注意:1.type和protocol不可以随意组合,如SOCK_STREAM不可以跟IPPROTO_UDP组合。当第三个参数为0时,会自动选择第二个参数类型对应的默认协议。
         返回值:
         如果调用成功就返回新创建的套接字的描述符,如果失败就返回INVALID_SOCKET(Linux下失败返回-1)
         */
    

    自定义socket实现

    #import <sys/socket.h>
    #import <netinet/in.h>
    #import <arpa/inet.h>
    

    步骤一:定义IP地址和端口

    #define SocketPort htons(8040)
    
    #define SocketIP inet_addr("127.0.0.1")
    

    步骤二:创建socket对象

    int socketID = socket(AF_INET, SOCK_STREAM, 0);
        self.clinenId= socketID;
        if (socketID == -1) {
            NSLog(@"创建socket 失败");
            return;
        }
    

    步骤三:将端口和地址 赋值给socket api

        // 端口
        struct sockaddr_in socketAddr;
        socketAddr.sin_family = AF_INET;
        socketAddr.sin_port   = SocketPort;
        // IP
        struct in_addr socketIn_addr;
        socketIn_addr.s_addr  = SocketIP;
        // 端口 绑定 IP(小尾顺序)
        socketAddr.sin_addr   = socketIn_addr;
    

    步骤四:连接 connect

    /**
         参数
         参数一:套接字描述符
         参数二:指向数据结构sockaddr的指针,其中包括目的端口和IP地址
         参数三:参数二sockaddr的长度,可以通过sizeof(struct sockaddr)获得
         返回值
         成功则返回0,失败返回非0,错误码GetLastError()。
         */
        int result = connect(socketID, (const struct sockaddr *)&socketAddr, sizeof(socketAddr));
    
        if (result != 0) {
            NSLog(@"链接失败");
            return;
        }
        NSLog(@"链接成功");
    
         // 在异步子线程中循环接收消息
    
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            [self recvMsg];
        });
    
    • [self recvMsg]
    -(void)recvMsg{
        NSLog(@"来到了接受消息");
        // 4. 接收数据
        /**
         参数
         1> 客户端socket
         2> 接收内容缓冲区地址
         3> 接收内容缓存区长度
         4> 接收方式,0表示阻塞,必须等待服务器返回数据
         
         返回值
         如果成功,则返回读入的字节数,失败则返回SOCKET_ERROR
         */
        while (1) {
            uint8_t buffer[1024];
            ssize_t recvLen = recv(self.clinenId, buffer, sizeof(buffer), 0);
            // 当没有接收到消息的时候会阻塞在这里不会往下执行,处理完消息进入循环继续阻塞
            if (recvLen == 0) {
                // 容错判断:如果消息为空,啥也不做,进入循环开启阻塞
                NSLog(@"接收到了0个字节");
                continue;
            }
            // buffer -> data -> string
            NSData *data = [NSData dataWithBytes:buffer length:recvLen];
            NSString *str= [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            NSLog(@"%@---%@",[NSThread currentThread],str);
            
            dispatch_async(dispatch_get_main_queue(), ^{
                 // 1 接收来自服务端的消息
                [self showMsg:str msgType:1];
                self.sendMsgContent_tf.text = @"";
            });
        }
    }
    

    步骤五:客户端发送消息

     /**
         发送消息
         s:一个用于标识已连接套接口的描述字。
         buf:包含待发送数据的缓冲区。
         len:缓冲区中数据的长度。
         flags:调用执行方式。
         
         返回值
         如果成功,则返回发送的字节数,失败则返回SOCKET_ERROR
         一个中文对应 3 个字节!UTF8 编码!
         */
        if (self.sendMsgContent_tf.text.length == 0) {
            return;
        }
        // 处理输入文本框的内容
        const char *msg = self.sendMsgContent_tf.text.UTF8String;
        // 发送消息到服务端
        ssize_t sendLen = send(self.clinenId, msg, strlen(msg), 0);
        NSLog(@"发送 %ld 字节",sendLen);
        // 处理消息并且在文本框显示
        [self showMsg:self.sendMsgContent_tf.text msgType:0];
        // 清除文本框
        self.sendMsgContent_tf.text = @"";
    

    步骤六:处理消息显示到文本视图UITextView

    • 补充:这个TextView不一般,绝不是大家所想象的简单的现实文本,为啥呢->自己研究文档

    这里是简单的富文本处理

    - (void)showMsg:(NSString *)msg msgType:(int)msgType{
        
        // 发送消息0 接收消息1
        
        // 时间处理
        NSString *showTimeStr = [self getCurrentTime];
        if (showTimeStr) {
            NSMutableAttributedString *dateAttributedString = [[NSMutableAttributedString alloc] initWithString:showTimeStr];
            NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
            // 对齐方式
            paragraphStyle.alignment = NSTextAlignmentCenter;
            [dateAttributedString addAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:13],NSForegroundColorAttributeName:[UIColor blackColor],NSParagraphStyleAttributeName:paragraphStyle} range:NSMakeRange(0, showTimeStr.length)];
            [self.totalAttributeStr appendAttributedString:dateAttributedString];
            [self.totalAttributeStr appendAttributedString:[[NSMutableAttributedString alloc] initWithString:@"\n"]];
        }
        
        NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
        paragraphStyle.headIndent = 20.f;
        NSMutableAttributedString *attributedString;
        if (msgType == 0) { // 我发送的
            attributedString = [[NSMutableAttributedString alloc] initWithString:msg];
    
            paragraphStyle.alignment = NSTextAlignmentRight;
            [attributedString addAttributes:@{
                                              NSFontAttributeName:[UIFont systemFontOfSize:15],
                                              NSForegroundColorAttributeName:[UIColor whiteColor],
                                              NSBackgroundColorAttributeName:[UIColor blueColor],
                                              NSParagraphStyleAttributeName:paragraphStyle
                                              }
                                      range:NSMakeRange(0, msg.length)];
        }else{
            msg = [msg substringToIndex:msg.length];
            attributedString = [[NSMutableAttributedString alloc] initWithString:msg];
    
            [attributedString addAttributes:@{
                                              NSFontAttributeName:[UIFont systemFontOfSize:15],
                                              NSForegroundColorAttributeName:[UIColor blackColor],
                                              NSBackgroundColorAttributeName:[UIColor whiteColor],
                                              NSParagraphStyleAttributeName:paragraphStyle
                                              }
                                      range:NSMakeRange(0, msg.length)];
        }
        [self.totalAttributeStr appendAttributedString:attributedString];
        [self.totalAttributeStr appendAttributedString:[[NSMutableAttributedString alloc] initWithString:@"\n"]];
    
        self.allMsgContent_tv.attributedText = self.totalAttributeStr;
    
    }
    

    步骤七:[self getCurrentTime]

    - (NSString *)getCurrentTime{
        NSDate *date = [NSDate date];
        NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
        dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";
        NSString *dateStr = [dateFormatter stringFromDate:date];
        if (!self.recoderTime || self.recoderTime.length == 0) {
            self.recoderTime = dateStr;
            return dateStr;
        }
        NSDate *recoderDate = [dateFormatter dateFromString:self.recoderTime];
        self.recoderTime = dateStr;
        NSTimeInterval timeInter = [date timeIntervalSinceDate:recoderDate];
        NSLog(@"%@--%@ -- %f",date,recoderDate,timeInter);
        if (timeInter<30) {
            return @" ";
        }
        return dateStr;
    }
    
    • 补充

    大端 & 小端

    • 判断系统时大端还是小端
    #include <</SPAN>stdio.h>
    #include <</SPAN>stdlib.h>
    
    int main(void)
    {
        short int a = 0x1234;
        char *p = (char *)&a;
    
        printf("p=%#hhx\n", *p);
    
        if (*p == 0x34) {
            printf("little endian\n");    
        } else if (*p == 0x12) {
            printf("big endia\n");    
        } else {
            printf("unknown endia\n");    
        }
        return 0;
    }
    

    socket server 篇章明天发布

    相关文章

      网友评论

          本文标题:socket client 篇章

          本文链接:https://www.haomeiwen.com/subject/wdmobrtx.html