c/c++中的网络通信基本套接字套(网络架构概念、字节序列、IP地址转换、袜子数据结构、系带功能、TCP通信流程)

      最后更新:2021-12-04 17:25:05 手机定位技术交流文章

      目录

      1. 概念

      1. 网络设计模式

      - B/S

      - C/S

      - IP和端口

      - 基于OSI/ISO的网络分层模式

      2. 协议格式

      三. 用插座编程

      3.1 字节序

      - 接口转换函数

      3.2 IPIP地址转换

      储存附加数据结构为3.3。

      3.4 套接字函数

      四、TCP来文程序

      tcp 服务器服务器-服务器通信过程 :

      tcp 客户阴蒂通讯程序如下:


      1. 概念
      1. 网络设计模式
      - B/S

      - 客户:网络浏览器
      - 服务器:服务器

      跨平台兼容性和低廉的开发成本是其主要优势。

      劣势:

      是的,它已得到更正:https, https

      无法关闭临时文件夹:%s。
      - C/S

      - 客户:桌面程序
      - 后台服务器

      好处包括能够处理大量的磁盘数据。

      缺点:如果你跨过平台,你必须付出巨大的代价重建平台。


      - IP和端口

      - IP地址

      - IPV4

      - 实际是一个32位的整形数 -> 本质 -> 4字节   int a;
      - 我们看的的不是这个整形数, 点分十进制字符串 -> 192.168.247.135
      - 分成了4份, 每份1字节, 8bit   ->  char , 最大值为 255  -> 最大取值: 255.255.255.255
      - 有几个IP地址?

      - IPV6

      - 事实上,这是一个128位数的矫形号码
      - xxx:xxx:xxx:xxx:xxx:xxx:xxx:xxx ,  分成了8分, 每份16位 -> 每一部分以16进制的方式表示
      - 有几个IP地址?
      - IP地址的作用:
      我们可以使用IP地址找到主机

      - 端口

      -主机有很多程序在运行
      - 向东道方进程提供数据
      - 程序如果要联网,可以与港口连接。
      - 有了这个港口,我们可能会决定一个过程
      - 端口号: unsigned short int   ->   16位
      - 提取港口范围:0 - 65535(216)


      - 基于OSI/ISO的网络分层模式

      > OSI(Open System Interconnect),即开放式系统互联。 一般都叫OSI参考模型,是ISO(国际标准化组织组织)在1985年研究的网络互联模型。

      - 七层模型

      底层 --------->上层
      信息应以下列方式在互联网上传播:

      > - 物理层:

      >   - 物理层负责最后将信息编码成电流脉冲或其它信号用于网上传输

      > - 数据链路层:

      >   - 数据链路层通过物理网络链路供数据传输。
      >   - 规定了0和1的分包形式,确定了网络数据包的形式;

      > - 网络层

      >   - 网络层负责在源和终点之间建立连接;
      >   - 此处需要确定计算机的位置,怎么确定?IPv4,IPv6

      > - 传输层

      >   - 传输层向高层提供可靠的端到端的网络数据流服务。
      >   - 每一个应用程序都会在网卡注册一个端口号,该层就是端口与端口的通信

      > - 会话层

      >   - 会话层建立、管理和终止表示层与实体之间的通信会话;
      >   - 建立一个连接(自动的手机信息、自动的网络寻址);

      > - 表示层:

      >   - 对应用层数据编码和转化, 确保以一个系统应用层发送的信息 可以被另一个系统应用层识别;
      >   - 可以理解为:解决不同系统之间的通信,eg:手机上的QQ和Windows上的QQ可以通信;

      > - 应用层:

      >   - 规定数据的传输协议

      四层模型




      2. 协议格式


      三. 用插座编程

      套接字通信分为两部分:
      - 服务器端:被动连接接受,而不是主动连接启动
      - 客户通信:与服务器建立连接。

      Socket是Linux和Windows都可以使用的通信界面的集合,但变化不大。


      3.1 字节序

      如名称所示,字节顺序是指将字节类型的数据存储在内存中的顺序。

      - 概念

      - Little-Endian -> 主机字节序
      - 在内存中保存一个数据点:0x12345678。
      - 内存低地址存储数据以低字节储存,而内存高地址存储数据以高字节储存。
      - Big-Endian -> 网络字节序
      - 内存低地址数据储存字节、内存高地址数据储存字节

      - 字节序举例

      为了表示这两个整数,请使用16点内存,即:
      - 0x12 34 56 78   -> 四字节   char -> 255 -> ff
      - 0x11223344   -> 四字节

      - 小端

      低地址位 -------------> 高地址位
      0x78     0x56    0x34    0x12
      0x44    0x33    0x22    0x11

      - 大端

      低地址位 -------------> 高地址位
      0x12    0x34    0x56    0x78
      0x11    0x22    0x33    0x44

      - 接口转换函数

      BSD Socket 提供一种密封的转换界面,程序员可以随时访问。

      htons 和 htonl 是网络 byte (n) 转换例行程序的主机 byte (h) 。

      以下函数将网络字节(n)转换为主机字节(h):nohs,nothl。

      #include <arpa/inet.h>
      // shot int -> 4字节(64位)
      // h -> host
      // n -> network
      // s -> short
      // l -> long
      // xtoxs() -> 进行端口转换
      uint16_t htons(uint16_t hostshort);
      参数: 主机字节数的short型数值 -> 要转换的数(主机)
      转换后获得的数据(网络字节顺序)为返回值
      uint16_t ntohs(uint16_t netshort);

      // long -> 8字节(64位)
      // xtoxl() -> 进行IP转换
      uint32_t htonl(uint32_t hostlong);
      uint32_t ntohl(uint32_t netlong);


      3.2 IPIP地址转换

      #include <arpa/inet.h>
      (小数字符串中的点)
      // p -> 点分十进制字符串 IP
      // n -> network
      // 将主机字节序的 字符串IP -> 网络字节序的 整形数
      int inet_pton(int af, const char *src, void *dst);
      参数:
      - 如果满足下列条件:地址家庭协议、IPv4、IPv6
      ipv4: AF_INET, ipv6:AF_INET6
      -src:指向字符串 IP 地址
      - dst: 传输参数, 执行内存地址, 并记录此内存中已转换网络字节的整数 。
      返回值:
      -1: 失败
      1: 成功
      0: 查字典

      // 网络字节序的整形IP -> 点分十进制字符串 IP
      const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
      参数:
      - 如果满足下列条件:地址家庭协议、IPv4、IPv6
      ipv4: AF_INET, ipv6:AF_INET6
      - src: 指向要转换的网络字节顺序的可选 IP 地址 。
      - dst: 当转换完成时保存点的位置 。
      - 大小:经修改后为与第三个 dst 参数相关的内存大小。
      返回值:
      NULL: 失败
      一个非空的指针指向三根手指的记忆:


      储存附加数据结构为3.3。

      对于网络连接,则使用结构套装机和套装机。

      用于进程间通信,使用 sockaddr_un 结构。

      IPv6 通信的 sockaddr_ in 结构

      由于结构套装机需要用手指切换来添加IP地址,这很难,在现实中,我们使用套装机来添加端口号码和 IP 地址。 转换成套装机型会得到加强, 因为两个结构的大小相同, 而后端服务器客户程序也会被提供 。

      struct sockaddr {
      sa_ family_t sa_ family; / ipv4, ipv6 地址家庭协议
      char        sa_data[14];
      }

      struct sockaddr_in
      {
      IP选择 AF_INET( Ipv4) 和 AF_INET6( Ipv6) 。
      (网络字节顺序: htons ()), in_port_t sin_port
      IP 位址( 网络字节顺序: inint_ pton () ), 以 _ addr sin_ addr 的 Struct
      //预留空间:
      unsigned char sin_zero[sizeof (struct sockaddr) - __SOCKADDR_COMMON_SIZE -
      sizeof (in_port_t) - sizeof (struct in_addr)];
      };

      struct in_addr
      {
      IP 地址 (网络字节顺序: inint_pton ()), in_addr_t s_addr
      };

      typedef unsigned short  uint16_t;
      typedef unsigned int    uint32_t;
      typedef uint16_t in_port_t;
      typedef uint32_t in_addr_t;
      typedef unsigned short int sa_family_t;
      #define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int))



      3.4 套接字函数

      #include <arpa/inet.h>
      做一个套接字
      int socket(int domain, int type, int protocol);
      参数:
      - 域域:关于地址家庭的协议
      AF_INET: ipv4
      AF_INET6: ipv6
      AF_UNIX,AF_LOCAL 本地共享(流程间通信)
      - 议定书:一种通讯议定书
      SOCK_STREAM:适应协议
      SOCK_DGRAM 是新闻协议 。
      - 一般而言,协议:0。
      - SOCK_STREAM:适应协议默认使用使用: tcp
      - SOCK_DGRAM 是新闻协议 。默认使用使用: udp
      返回值:内核缓冲由此文件描述符管理。
      成功: 文件描述符 > 0
      失败: -1

      // 绑定函数 -> 将fd 和本地的 IP + Port进程绑定
      int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
      参数:
      - 套接字功能 - 套接字功能 - A sockfdd:
      这一结构必须与IP和Port一起初始化。
      - 内存结构的第二个参数

      // 设置监听
      int listen(int sockfd, int backlog);    // /proc/sys/net/core/somaxconn
      参数:
      - 套接字功能 - 套接字功能 - A sockfdd:
      - 后向: 连接成功, 但是为未处理连接请求的值不能超过 / proc/ sys/ net/ core/ somaxconn 中记录的数据, 默认情况下该数据为 128 。

      / 默认是一个屏蔽功能, 暂停等待客户端请求。 请求到达、 客户端连接和文件描述
      int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
      参数:
      - Sockfd: 正在监听文件描述符( 设置)
      - 添加:为了连接到成功的客户端,提供参数并记录IP和端口信息。
      第二个参数结构的内存大小。
      返回值:
      - 成功: 通信的文件描述符 > 0
      - 失败: -1

      此函数被客户端用于连接到服务器 。
      int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
      参数:
      - Sockfd: 通信文件说明
      - Addr: 客户端想要连接的服务器地址 。
      - 内存结构的第二个参数
      返回值:
      连接成功: 0
      连接失败: -1

      // 写数据
      ssize_t write(int fd, const void *buf, size_t count);
      // 读数据
      ssize_t read(int fd, void *buf, size_t count);


      四、TCP来文程序

      // tcp / udp-> 传输层协议
      TCP代表“连接、安全、当前传输协议”。
      - 我们不会失去数据
      udp: 无连接、 危险、 报告传输协议

      tcp 服务器通信方法 :

      一,做一个监听插座
      - 倾听:注意客户的联系。
      文件描述符是一个插座。
      二. 将监听文件的说明连接到本地IP和端口(IP和端口=服务器地址信息)。
      - 当客户端连接到服务器时,使用IP地址和端口。
      三,当你安装窃听器时,窃听器开始运作。
      四. 当客户开始连接时,它会解开连接的屏障,接受客户连接,并接收用户对社区(fd)的连接。
      5. 通信
      - 接收数据
      - 发送数据
      六,对话结束了,解开装置

      tcp 客户通信程序:

      一. 创建通信套接字(fd)
      二. 连接服务器,它需要一个 IP 地址和一个端口号来表示您想要连接到的服务器 。
      三. 如果连接成功,客户可以直接交谈并接受服务。
      - 接收数据
      - 发送数据
      4. 断开连接

      tcp 服务器服务器-服务器通信过程 :

      #include <stdio.h>
      #include <stdlib.h>
      #include <unistd.h>
      #include <string.h>
      #include <arpa/inet.h>

      int main()
      {
      / 1. 创建监听套接字
      int fd = socket(AF_INET, SOCK_STREAM, 0);
      if (fd == -1)
      {
      perror("socket");
      exit(0);
      }

      // 2.绑定
      struct sockaddr_in addr;
      addr.sin_family = AF_INET;            //ipv4
      我不知道你在说什么,Adr. 我不知道你在说什么,sin_addr.s_addr = InDID_ANY;//IP进入内核
      // 上面的代码等价于:inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
      我不知道你指的是什么,Ardr.sin_port = htons(8989);//port
      int ret = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
      if (ret == -1)
      {
      perror("bind");
      exit(0);
      }

      // 3.设置监听
      int lis_ret = listen(fd, 100);
      if (lis_ret == -1)
      {
      perror("listen");
      exit(0);
      }

      /4. 等待连接
      struct sockaddr_in addr_cli;
      int len = sizeof(addr_cli);
      int connfd = accept(fd, (struct sockaddr*)&addr_cli, &len);
      if (connfd == -1)
      {
      perror("accept");
      exit(0);
      }

      // 通讯
      while (1)
      {
      // 读数据
      char recvBuf[1024];
      read(connfd, recvBuf, sizeof(recvBuf));
      printf("recv buf : %sn", recvBuf);
      // 写数据
      write(connfd, recvBuf, strlen(recvBuf));
      }

      //释放
      close(fd);
      close(connfd);

      return 0;
      }


      tcp 客户阴蒂通讯程序如下:

      #include <stdio.h>
      #include <stdlib.h>
      #include <unistd.h>
      #include <string.h>
      #include <arpa/inet.h>

      int main()
      {
      / 1. 创建通信套接字
      int fd = socket(AF_INET, SOCK_STREAM, 0);
      if(fd == -1)
      {
      perror("socket");
      exit(0);
      }

      //2. 与服务器的链接
      struct sockaddr_in addr;
      addr.sin_family = AF_INET;  // ipv4
      我不知道你是什么意思, Ardr.sin_port = htons (8989); / 服务器听众端口, 字节顺序应该是网络字节顺序
      inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
      int ret = connect(fd, (struct sockaddr*)&addr, sizeof(addr));
      if(ret == -1)
      {
      perror("connect");
      exit(0);
      }


      int i = 0;
      // 通信
      while(1)
      {
      // 读数据
      char recvBuf[1024];
      // 写数据
      sprintf(recvBuf, "data: %dn", i++);
      write(fd, recvBuf, strlen(recvBuf));
      / 如果客户端不提供数据,则使用默认区块。
      read(fd, recvBuf, sizeof(recvBuf));
      printf("recv buf: %sn", recvBuf);
      sleep(1);
      }

      // 释放资源
      close(fd);

      return 0;
      }

      本文由 在线网速测试 整理编辑,转载请注明出处,原文链接:https://www.wangsu123.cn/news/14194.html

          热门文章

          文章分类