Unix/Linux方案拟订第13章学习说明

      最后更新:2021-11-29 17:24:51 手机定位技术交流文章

      Unix/Linux方案拟订第13章学习说明

      知识点总结

      TCP/IP协议

      • 在字面上,人们可以假定TCP/IP既指TCP协议,也指IPIP协议。 两种类型的协议在现实生活中也偶尔被指。 然而,在许多情况下,只有包件的一般名称才能用来使用IP进行互动。 具体地说,IP或IPCMP、TCP或UDP、TELNET或FTP以及HTTP都是TCP/IP协议。 与TCP或IP密切关联是IP的一个重要方面。
      • 当互联网互动时,匹配的网络协议是必要的,TCP/IP最初是作为使用互联网的用户建立的,TCP/IP是互联网协议。

      IP主机和IP地址

      IP 地址分为两个部分, 网络ID 字段和 HostID 字段。 分解后, IP 地址被分类为 A- E 。 例如, B 类中的IP 地址被分为16位网络ID, 其中前两位为 10, 后一位是 16 位 HostID 字段。 发送到 IP 地址的软件包先被发送到与同一网络WorkingID 相同的路由器。 路由器将通过 HostID 将软件包转发给网络中的特定主机 。 每个主机都有一个本地主机名, 本地主机, 以及默认的 IP 地址 。 本地主机链层是一个返回虚拟设备, 将每个数据包返回同一本地主机 。 此功能允许我们在同一计算机上运行 TCP/ IP 应用程序, 而不实际连接互联网 。

      IP协议

      IP 协议用于在 IP 主机之间发送/接收数据包 。 IP 主机仅将软件包传送给接收者, 但不保证软件包将转移到目的地或连续发送。 这意味着 IP 不是一个可靠的协议 。 如果需要可靠性, 必须在 IP 层上方提供 。

      UDP/TCP

      UDP(用户数据报告协议)(RFC768,1980年;Comer 1988年)是一个关于IP的协议,用于传输和接收数据报告。 和IP一样,UDP并不保证可靠性,而是快速有效的,可以在可靠性并不关键的情况下使用。

      TCP(传输控制协议)是用于传输/接收数据流的以连接为导向的协议。 TCP也可能在 IP 上运行,但它提供一致的数据传输。 UDP通常用于发送邮件,但TCP被用于发送数据流。

      端口编号

      应用程序 = (主机IP地址、协议和端口)
      协议是 TCP 或 UDP, 端口号是分配给程序的唯一未签名的短整数 。 要使用 UDP 或 TCP, 应用程序( process) 必须首先选择或获得端口号 。 保留了第一个 1024 端口号 。 其他端口号可供一般使用 。 应用程序可以选择可用的端口号, 也可以在操作系统中进行核分配 。

      套接字编程

      (1)套接字地址

      struct sockaddr_in {
      sa_family_t sin_family; // AF_INET for TCP/IP
      // port number
      in_port_t sin_port;
      struct in_addr sin_addr;// IP address );
      // internet address struct in_addr {
      // IP address in network byte order
      s_addr;
      uint32_t
      );
      

      (2)套接字API

      服务器必须构造套接字, 并将其绑在带有服务器 IP 地址和端口号的套接字地址上。 它可以使用预设端口号码, 或者使操作系统能够选择端口号码( 如果罪过端口为零 ) 。 为了连接服务器, 客户端必须创建一个套接字 。 对于 UPD 设置, 您可以将其附加到服务器 地址构建器上。 对于 UPD 设置, 您可以将套接字附加到服务器 地址和端口号的套接字地址上。 它可以使用预设端口号码, 或者使操作系统能够选择端口号( 如果罪过端口为零 ) 。 为了连接服务器, 客户端口必须创建套接字。 For UPD 设置, 您可以将其附加到服务器地址 。

      实践

      #include <stdio.h>
      #include <arpa/inet.h>//inet_addr() sockaddr_in
      #include <string.h>//bzero()
      #include <sys/socket.h>//socket
      #include <unistd.h>
      #include <stdlib.h>//exit()
      
      #define BUFFER_SIZE 1024
      
      int main() {
      
          char listen_addr_str[] = "0.0.0.0";
          size_t listen_addr = inet_addr(listen_addr_str);
          int port = 8080;
          int server_socket, client_socket;
          struct sockaddr_in server_addr, client_addr;
          socklen_t addr_size;
          char buffer[BUFFER_SIZE];//缓冲区大小
          int str_length;
          server_socket = socket(PF_INET, SOCK_STREAM, 0);//创建套接字
          bzero(&server_addr, sizeof(server_addr));//初始化
          server_addr.sin_family = INADDR_ANY;
          server_addr.sin_port = htons(port);
          server_addr.sin_addr.s_addr = listen_addr;
          if (bind(server_socket, (struct sockaddr *) &server_addr, sizeof(server_addr)) == -1) {
              printf("绑定失败n");
      
              exit(1);
      
          }
      
          if (listen(server_socket, 5) == -1) {
      
              printf("监听失败n");
      
              exit(1);
      
          }
      
          printf("创建tcp服务器成功n");
      
       
      
       
      
          fd_set reads,copy_reads;
      
          int fd_max,fd_num;
      
          struct timeval timeout;
      
       
      
          FD_ZERO(&reads);//初始化清空socket集合
      
          FD_SET(server_socket,&reads);
      
          fd_max=server_socket;
      
       
      
       
      
          while (1) {
      
              copy_reads = reads;
      
              timeout.tv_sec = 5;
      
              timeout.tv_usec = 5000;
      
       
      
              //无限循环调用select 监视可读事件
      
              if((fd_num = select(fd_max+1, &copy_reads, 0, 0, &timeout)) == -1) {
      
                  perror("select error");
      
                  break;
      
              }
      
              if (fd_num==0){//没有变动的socket
      
                  continue;
      
              }
      
       
      
              for(int i=0;i<fd_max+1;i++){
      
                  if(FD_ISSET(i,&copy_reads)){
      
                      if (i==server_socket){//server_socket变动,代表有新客户端连接
      
                          addr_size = sizeof(client_addr);
      
                          client_socket = accept(server_socket, (struct sockaddr *) &client_addr, &addr_size);
      
                          printf("%d 连接成功n", client_socket);
      
                          char msg[] = "恭喜你连接成功";
      
                          write(client_socket, msg, sizeof(msg));
      
                          FD_SET(client_socket,&reads);
      
                          if(fd_max < client_socket){
      
                              fd_max=client_socket;
      
                          }
      
                      }else{
      
                          memset(buffer, 0, sizeof(buffer));
      
                          str_length = read(i, buffer, BUFFER_SIZE);
      
                          if (str_length == 0)    //读取数据完毕关闭套接字
      
                          {
      
                              close(i);
      
                              printf("连接已经关闭: %d n", i);
      
                              FD_CLR(i, &reads);//从reads中删除相关信息
      
                          } else {
      
                              printf("%d 客户端发送数据:%s n", i, buffer);
      
                              write(i, buffer, str_length);//将数据发送回客户端
      
                          }
      
                      }
      
                  }
      
              }
      
       
      
          }
      
       
      
          return 0;
      
      }
      

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

          热门文章

          文章分类