zoukankan      html  css  js  c++  java
  • 网络编程实战 1

    • Ethernet frame
    • IP packet
    • TCP segment
    • Application message

    三个层次

    • 充分理解TCP/IP网络模型和协议
    • 结合对协议的理解, 增强对异常情况的处理能力
    • 可以写出支持大规模高并发的网络处理程序

    TCP/IP 四层模型

    img

    MAC层的传输单位是帧(frame), IP层的传输单位是包(packet), TCP层的传输单位是段(segment), HTTP的传输单位是消息或报文(message).

    TCP --> stream socket, 字节流套接字, SOCK_STREAM

    UDP --> datagram socket, 数据包套接字, SOCK_DGRAM

    OSI网络分层模型

    OSI (开放式系统互联通信参考模型, open system interconnection reference model),

    img

    TCP/IP是一个纯软件的栈, 没有网络应有的网卡, 光缆等设备的位置. 而OSI填补了这一层次的缺失, 使得理论层面描述的网络更为完整.

    socket是什么

    img

    客户端发起连接请求之前, 需要服务端初始化. 服务端首先初始化socket, 然后执行bind函数, 将服务能力绑定在约定好的地址和端口, 接着执行listen操作, 监听特定端口, 然后在accept函数处阻塞, 等待客户端连接请求的到来.

    三次握手完成之后, 建立连接, 数据的传输就不再是单向的而是双向的.

    通用套接字地址格式

    /* POSIX.1g 规范规定了地址族为2字节的值.  */
    typedef unsigned short int sa_family_t;
    /* 描述通用套接字地址  */
    struct sockaddr {
        sa_family_t sa_family;  /* 地址族.  16-bit*/
        char sa_data[14];       /* 具体的地址值 112-bit */
    }; 
    

    sa_family指定为AF_LOCAL表示本地地址, AF_INET表示使用IPv4, AF_INET6表示使用IPv6. AF_表示的是Address Family, PF_表示的是Protocal Family, 常用AF_XXX初始化socket地址, PF_XXX初始化socket.

    IPv4套接字格式地址

    /* IPV4套接字地址,32bit值.  */
    typedef uint32_t in_addr_t;
    struct in_addr {
    	in_addr_t s_addr;
    };
    /* 描述IPV4的套接字地址格式  */
    struct sockaddr_in
    {
        sa_family_t sin_family;       /* 16-bit, IPv4为AF_INET */
        in_port_t sin_port;          /* 端口口  16-bit*/
        struct in_addr sin_addr;    /* Internet address. 32-bit */
        
        /* 这里仅仅用作占位符,不做实际用处  */
        unsigned char sin_zero[8];
    };
    

    服务端准备连接的过程

    创建套接字

    int socket(int domain, int type, int protocol)
    

    domainPF_INET, PF_INET6, PF_LOCAL. type 对于TCP为SOCK_STREAM, UDP为SOCK_DGRAM.

    绑定套接字和套接字地址

    bind(int fd, sockaddr *addr, socklen_t len)
    

    sockaddr *可以看作是一个void *类型的参数

    struct sockaddr_in name;
    bind(sock, (struct sockaddr *)&name, sizeof(name))
    

    对于IPv4地址, 可按照如下方式设置通配地址:

    struct sockaddr_in name;
    name.sin_addr.s_addr = htonl(INADDR_ANY);  // IPv4通配地址
    

    让服务器处于可监听的状态

    int listen(int sockfd, int backlog);
    

    listen函数可以将"主动"的套接字转换为"被动"套接字, 告诉操作系统内核该套接字是用于等待用户请求的. 参数backlog为未完成连接队列的大小.

    成功应答

    int accept(int listen_sock_fd, struct sockaddr *cli_addr, socklen_t *addrlen)
    

    其中参数cli_addraddrlen是函数的返回值, cli_addr是客户端的地址, addrlen指明了地址的大小, 函数返回的是一个新的套接字, 代表了与客户端的连接.

    Q: 为什么需要有监听套接字已连接套接字?

    A: 这是考虑到网络程序需要具有一定的并发性, 监听套接字需要一直存在才能够服务多个客户端. 而一个客户端和服务端连接成功后, 就会生成一个已连接套接字, 使用已连接套接字和客户进行通信处理. 如果对该客户的服务已经完成, 那么将释放这一个客户的连接.

    客户端发起连接的过程

    客户端建立套接字的方法和服务端大致相同. 不同之处是客户端需要调用connect向服务端发起请求.

    int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen)
    

    sockfd是连接套接字, servaddraddrlen代表指向套接字地址结构的指针和该结构的大小. 套接字地址结构需要有服务器的IP地址和端口号.

    对于TCP套接字, 调用connect函数将会引发TCP的3次握手过程. 函数会在建立连接成功或出错时返回.

    以上就是阻塞式网络编程模型的服务端与客户端.

    image-20220104211720004

    思考题

    数据流从应用程序发送端一直到应用程序接收端, 总共经历多少次拷贝?

    image-20220104210154993

    7次以上(中间还需要经过网络设备拷贝数据). 应用程序将数据送到发送缓冲区时, 调用send或是write方法, 如果缓存中没有空间, 系统调用就会失败或被阻塞. 这个动作是显式拷贝. 之后, 数据将按照TCP/IP的分层进行拷贝, 这些拷贝对我们而言是透明的.

  • 相关阅读:
    DecimalPercentageConverter
    Asp.Net 性能 ViewState 压缩的2种方法
    Listbox template
    Datagrid template for listbox and textbox
    ToPercentConverter : IValueConverter
    繁體中文
    Silverlight ComboBox 设置选中项
    鲁迅:纪念刘和珍君
    ASP.NET系统整合DiscuzNT3.6之注意事项
    [转]js动态创建json类型
  • 原文地址:https://www.cnblogs.com/tedukuri/p/15768776.html
Copyright © 2011-2022 走看看