zoukankan      html  css  js  c++  java
  • 20191325第十三章学习笔记

    第十三章 TCP/IP和网络编程

    一、梗概

    本章论述了 TCP/IP和网络编程,分为两个部分。第一部分论述了 TCP/IP协议及其应 用,具体包括TCP/IP栈、IP地址、主机名、DNS、IP数据包和路由器;介绍了 TCP/IP网 络中的UDP和TCP协议、端口号和数据流;阐述了服务器-客户机计算模型和套接字编程 接口;通过使用UDP和TCP套接字的示例演示了网络编程。第一个编程项目可实现一对通 过互联网执行文件操作的TCP服务器-客户机,可让用户定义其他通信协议来可靠地传输 文件内容。本章的第二部分介绍了 Web和CGI编程,解释了 HTTP编程模型、Web页面和Web浏 览器;展示了如何配置Linux HTTPD服务器来支持用户Web页面、PHP和CG1编程;阐释了客户机和服务器端动态Web页面;演示了如何使用PHP和CGI创建服务器端动态Web 页面。第二个编程项目可让读者在Linux HTTPD服务器上通过CGI编程实现服务器端动态Web页面。

    二、知识点归纳

    1、计算机网络知识

    • TCP/IP协议包括ICMP、IP、telnet、udp等协议,是利用IP进行通信时所必须用到的协议群的统称。 img

    • IP主机和IP地址:主机是支持TCP/IP 协议的计算机或设备。每个主机由一个32位的IP地址来标识。为了方便起见,32位的P地址号通常用点记法表示,例如:134.121.64.1,其中各个字节用点号分开。主机也可以用主机名来表示,如dns1.eec.wsu.edu。IP地址分为两部分,即 NetworkID字段和HostID字段。根据划分,IP地址分为A~E类。例如,一个B类P地址被划分为一个16位NetworkID,其中前2位是10,然后是一个16位的HostID字段。发往P地址的数据包首先被发送到具有相同networkID 的路由器。路由器将通过HostID将数据包转发到网络中的特定主机。每个主机都有一个本地主机名localhost,默认P地址为127.0.0.1。本地主机的链路层是一个回送虚拟设备,它将每个数据包路由回同一个 localhost。

    • IP协议:用于在IP主机之间发送/接收数据包。IP尽最大努力运行。IP主机只向接收主机发送数据包,但它不能保证数据包会被发送到它们的目的地,也不能保证按顺序发送。

    • IP数据包:由IP头、发送方地址和接收方I地址以及数据组成。每个数据包的大小最大为64KB。IP头包含有关数据包的更多信息,例如数据包的总长度、数据包使用TCP还是UDP、生存时间(TTL)计数、错误检测的校验和等。 img

    • 路由器:是接收和转发数据包的特殊IP主机。一个IP数据包可能会经过许多路由器,或者跳跃到达某个目的地。每个IP包在IP报头中都有一个8位生存时间(TTL)计数,其最大值为255。在每个路由器上,TTL会减小1。如果TTL减小到0,而包仍然没有到达目的地,则会直接丢弃它。这可以防止任何数据包在IP网络中无限循环。

    • UDP:在IP上运行,用于发送/接收数据报。与IP类似,UDP不能保证可靠性,但是快速高效。ping是一个向目标主机发送带时间戳UDP包的应用程序。接收到一个pinging数据包后,目标主机将带有时间戳的UDP包回送给发送者,让发送者可以计算和显示往返时间。如果目标主机不存在或宕机,当TTL减小为0时,路由器将会丢弃pinging UDP数据包。在这种情况下,用户会发现目标主机没有任何响应。用户可以尝试再次ping,或者断定目标主机宕机。

    • TCP:是一种面向连接的协议,用于发送/接收数据流。TCP也可在IP上运行,但它保证了可靠的数据传输。通常,UDP类似于发送邮件的USPS,而TCP类似于电话连接。

    • 端口编号:端口号是分配给应用程序的唯一无符号短整数。要想使用UDP或TCP,应用程序(进程)必须先选择或获取一个端口号。前1024个端口号已被预留。其他端口号可供一般使用。应用程序可以选择一个可用端口号,也可以让操作系统内核分配端口号。

    • 网络和主机字节序:计算机可以使用大端字节序,也可以使用小端字节序。在互联网上,数据始终按网络序排列,这是大端。在小端机器上,例如基于Intel x86的PC,htons()、htonl()、ntohs()、ntohl()等库函数,可在主机序和网络序之间转换数据。例如,PC中的端口号1234按主机字节序(小端)是无符号短整数。必须先通过htons(1234)把它转换成网络序,才能使用。相反,从互联网收到的端口号必须先通过ntohs(port)转换为主机序。

    • TCP/IP网络中的数据流 img

    2、套接字编程

    套接字编程

    • 在网络编程中,TCP/IP的用户界面是通过一系列C语言库函数和系统调用来实现的, 这些函数和系统调用统称为套接字API (( Rago 1993; Stevens等2004 )。为了使用套接宇 API,我们需要套接字地址结构,它用于标识服务器和客户机。netdb.h和sys/socket.h中有 套接字地址结构的定义:

    struct sockaddr_in ( sa_family_t sin_family; in_port_t sin_port; struct in_addr sin_addr;
    );
    struct in_addr {
    uint32_t s_addr;
    • 在套接字地址结构中,TCP/IP 网络的 sin_family 始终设置为 AF_INET,sm_port包含按网络字节顺序排列的端口号,sin_addr是按网络字节顺序排列的主机IP地址。

    • 服务器必须创建一个套接字,并将其与包含服务器IP地址和端口号的套接字地址绑 定。它可以使用一个固定端口号,或者让操作系统内核选择一个端口号(如果sin_port为 0)o为了与服务器通信,客户机必须创建〜个套接字。对于UPD套接字,可以将套接字绑定到服务器地址。如果套接字没有绑定到任何特定的服务器,那么它必须在后续的sendto()/ recvfromO调用中提供一个包含服务器IP和端口号的套接字地址。下面给出了socket。系统调用,它创建一个套接字并返回一个文件描述符。

    • UDP套接字使用scndto()/recvfrom()来发送/接收数据报。

    aendto(int aockfdr const void *bufr size.t len, lot flags,
    const struct sockaddr •de8t_addrf socklen_t addrlen)|
    asize_t recvfrora(int sock£d, void *buf, aiza_t len, int flags, struct sockaddr *Btc_addr, aocklen_t *addrlen};
    • 在创建套接字并将其绑定到服务器地址之后,TCP服务器使用listen()和acccpt()来接 收来自客户机的连接int Iistcn(int sockfd, int backlog);listen()将sockfd引用的套接字标记为将用于接收连入连接的套接字。backlog参数定义了等待连接的最大队列长度。

    • 建立连接后,两个TCP主机都可以使用send()/write()发送数据,并使用recv()/read。接收数据。它们唯一的区别是send和recv()中的nag参数不同,通常情况下可以将其设置为0。

    ssize_t send(int Bockfd, const void *bufr size.t len« int flags);
    write(sockfd/ void *buf, aize_t, l«n)
    S0izo_t recv(int sockfd, void *buf# size_t len, int flags);
    ssize_t read(sockfd, void *buf, size_t len);
    • 库函数gethostname(char *name, sizeof(name))在name数组中返回计算机的主机名字符串,但它可能不是用点记法表示的完整正式名称, 也不是其IP地址。库函数struct hostent *gethostbyname(void *addr, socklen_t len, int typo)可以用来获取计算机的全名及其IP地址。它会返回一个指向<netdb.h>中hostent结构体的指针:

    struct hostent {
    char *h_name;
    char **h_aliases;
    int h_addrtype;
    int h_length;
    char **h_addr_list;
    }
    #define h_addr h_addr_list[0]
    • 下面的代码段展示了如何使用gethostbyname()和getsockname()来获取服务器1P地址 和端口号(若是动态分配)。服务器必须发布其主机名或IP地址和端口号,以便客户机连接。

    char myname[64];
    struct sockaddr_in server_addr, sock_addr;
    // gethostname(), gethostbyname() gethostname(myname,64);
    struct hostent *hp = gethostbyname(myname); if (hp == 0)(
    printf("unknown host %s\n", myname); exit(1);
    // initialize the server_addr structure server_addr.sin_family = AF.INET; // for TCP/IP
    server_addr.Bin_addr・ s_addr = *(long *)hp->h_addr; server_addr.sin_port = 0; // let kernel assign port number
    // create a TCP socket
    int mysock = socket(AF_INET, SOCK_STREAM, 0);
    bind socket with server_addr bind(mysock,(struct
    to show port number assigned by kernel
    (struct sockaddr *)&name_addr, &length)/
    // show server host name and port number
    printf("hostname=%s IP=%s port=%d\n", hp->h_name,
    inet_ntoa(*(long *)hp->h_addr), ntohs(name_addr.sin_port));
    struct sockaddr_in server_addr, sock_addr;
    // 1. get server IP by name
    struct hostent *hp = gethostbyname(argv[l]);
    SERVER_IP = *(long *)hp->h_addr;
    SERVER_PORT = atoi(argv[2]);
    // 2. create TCP socket
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    // 3. fill server_addr with server IP and PORT#
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = SERVER_IP;
    server_addr.sin_port = htons(SERVER_PORT);
    // 4. connect to server
    connect(sock,(struct sockaddr *)&server_addr, sizeof(server_addr));
    • 在命令行中,根据命令的不同,路径名可以是文件或目录。有效命令有:

    mkdir:创建一个带路径名的目录。 rmdir:删除名为路径名的冃录。 rm:删除名为路径名的文件。 cd:将当前工作目录(CWD)更改为路径名。 pwd:显示当前工作目录的绝对路径名。 Is:按照与Linux的Is -1相同的格式列出当前工作目录或路径名。 get:从服务器下载路径名文件。 put:将路径名文件上传到服务器。

    • 对于传输文件内容的get/put命令,不能使用特殊ASCII字符作为文件的开始和结束标记。这是因为二进制文件可能包含ASCII代码。

    • 用标准HTML编写的Web页面都是静态的。当从服务器获取并用浏览器显示时,Web 页面的内容不会变化。要显示包含不同内容的Web页面,必须再次从服务器获取不同的 Web页面文件。

    • 动态Web页面有两种,分别称为 客户机端动态Web页面和服务器端动态Web页面。客户机端动态Web页面文件包含JavaScript写的代码,这些代码由JavaScript解释器在客户机上执行。它可以响应用户输入、时间事件等来对Web页面进行本地修改,而不需要与服务器进行任何交互。服务器端动态Web页面是真正的动态页面,因为它们是根据URL请求中的用户输入动态生成的。服务器 端动态Web页面的核心在于服务器在HTML文件中执行PHP代码,或CGI程序通过用户输入生成HTML文件的能力。

    • CGI代表通用网关接口,它是一种协议,允许Web服务器执行程序, 根据用户输入动态生成Web页面。使用CGI, Web服务器不必维护数百万个静态Web页面文件来满足客户机请求。相反,它通过动态生成Web页面来满足客户机请求。

     

    三、实践

        #include <stdio.h>
        #include <stdlib.h>
        #include <sys/types.h>
        #include <sys/socket.h>
        #include <netinet/in.h>
        #include <arpa/inet.h>
        #include <time.h>
        #include <string.h>
        #include <unistd.h>
        
        #define MAXLINE 256
        #define PORT 7777
        void sys_err(char *msg){
            perror(msg);
            exit(-1);
        }
        int main(int argc , char **argv){
        
        
            int sockFd,n;
            char recvLine[MAXLINE];
            struct sockaddr_in servAddr;
            
        
        if (argc != 2) {
                sys_err("usage: a.out <IPaddress>");
            }
        
            sockFd=socket(AF_INET,SOCK_STREAM,0);
        
        
            memset(&servAddr,0,sizeof(servAddr));
            
            servAddr.sin_family = AF_INET;
            servAddr.sin_port = htons(PORT);
            if (inet_pton(AF_INET,argv[1],&servAddr.sin_addr) <= 0) {
            
                sys_err("inet_pton error");
            }
            
            connect(sockFd,(struct sockaddr *)&servAddr,sizeof(servAddr));
        
        
            while((n=read(sockFd,recvLine,MAXLINE)) >0 ){
                recvLine[n] = '\0';
                if(fputs(recvLine,stdout) == EOF){
        
         sys_err("fputs error");
                }
            }
            if(n <0){
                sys_err("read error");
            }
            return 0;
        }

  • 相关阅读:
    第4月第1天 makefile automake
    第3月30天 UIImage imageWithContentsOfFile卡顿 Can't add self as subview MPMoviePlayerControlle rcrash
    第3月第27天 uitableviewcell复用
    learning uboot fstype command
    learning uboot part command
    linux command dialog
    linux command curl and sha256sum implement download verification package
    learning shell script prompt to run with superuser privileges (4)
    learning shell get script absolute path (3)
    learning shell args handing key=value example (2)
  • 原文地址:https://www.cnblogs.com/2902480848sy/p/15609430.html
Copyright © 2011-2022 走看看