• Socket编程(day14)


    一、基于TCP传输层的编程模型
    TCP是面向连接的,安全可靠的。
    三次握手
    服务器端编程模型
    1、创建一个用于网络通讯的设备 通讯端点
    socket(2)
    #include  <sys/types.h>
    #include <sys/socket.h>
    int socket(int domain, int type, int protocol);
    功能:创建一个用于通讯的端点
    参数:
    domain:
    AF_INET:应用于IPV4地址家族的
    AF_INET6:应用于IPV6地址家族的
    type:
    SOCK_STREAM:可靠的、基于连接的 双向的、队列式的 TCP
    SOCK_DGRAM:支持数据包    不可靠的  无连接的  UDP
    
    protocol:
    0
    返回值:
    -1  错误 errno被设置
    返回一个新的文件描述符
    
    2、将这个通讯端点和本机的ip地址、端口号做绑定
    bind(2)
    int bind(int sockfd, const struct sockaddr *addr,
                    socklen_t addrlen);
    功能:绑定名字到地址。创建socket以后,socket中有地址空间但是没有具体地址放在这个地址空间。需要将具体的地址和socket的地址空间绑定。
    参数:
    sockfd:已经创建好的socket,但是这个socked没有具体的地址
    addr:指定了具体的地址,将这个地址绑定到sockfd中
    addrlen:指定了addr的大小、字节数
    返回值:
    0  成功
    -1  错误  errno被设置
    
    地址家族的通用结构
    
    struct sockaddr{
        sa_family_t sa_family;
            char        sa_data[14];
    };
    
    ipv4和ipv6
    man in.h
    #include <netinet/in.h>
    in_port_t    uint16_t
    in_addr_t    uint32_t
    sa_family_t  <sys/socket.h>
    
    struct in_addr{
        in_addr_t  s_addr;
    };
    
    ipv4的具体地址
    struct sockaddr_in{
        sa_family_t     sin_family;   //AF_INET.
            in_port_t       sin_port;     //Port number.
            struct in_addr  sin_addr;     //IP address.
    };
    
    INADDR_ANY   IPv4 local host address
    这是一个宏,宏的本质是一个整数。代表了本机的所有的地址。
    
    
    
    端口号   0~65535
    但是5000以下最好不要用。因为已经被国际组织使用了。
    
    sin_port  采用网络字节序
    需要将本机字节序的数字转换为网络字节序
    系统提供了函数。处理本机字节序和网络字节序的问题
    #include <arpa/inet.h>
    uint32_t htonl(uint32_t hostlong);
    
    uint16_t htons(uint16_t hostshort);
    
    uint32_t ntohl(uint32_t netlong);
    
    uint16_t ntohs(uint16_t netshort);
    
    h   host      n    net
    s   short     l    long    to
    
    
    ip地址  字符串格式    二进制格式  互相转换
    inet_pton(3)
    #include <arpa/inet.h>
    int inet_pton(int af, const char *src, void *dst);
    功能:从字符串格式转换为二进制格式   IPV4 IPV6
    参数:
    af:
    AF_INET or AF_INET6
    
    src:字符串格式的ip地址
    dst:存储了网络地址结构的信息
    返回值:
    1   成功
    0  src无效
    -1  错误  errno被设置
    
    struct in_addr
     
    #include <arpa/inet.h>
    const char *inet_ntop(int af, const void *src,
                                 char *dst, socklen_t size);
    功能:二进制到字符串的转化
    参数:
    af:
    AF_INET or AF_INET6
    src: struct  in_addr
    dst:用来存储字符串的空间
    size:指定了空间的有效字节数
    返回值:
    NULL   错误  errno被设置
    非空  返回dst的地址,字符串的首地址。
    
    ip地址  127.0.0.1  本地地址   环回地址
    测试机器的网络设备工作是否正常。
    
    setsockopt(2)
    
    3、在这个通讯端点上监听客户端连接的到来,如果有连接的到来,将到达的连接存放在缓冲区中(队列的数据结构)
    listen(2)
    int listen(int sockfd, int backlog);
    功能:在socket监听连接。将sockfd标记为被动连接。接收即将到来的客户端请求。
    参数:
    sockfd:指定了被监听的socket
    backlog:指定了未决连接的最大数。
    返回值:
    0  成功
    -1   错误   errno被设置
    
    4、从这个缓冲区队列中取出一个客户端连接,返回一个连接描述符用于和客户端的通讯。(这个连接描述符称为conn_fd)
    accept(2)
    int accept(int sockfd, struct sockaddr *addr, 
            socklen_t *addrlen);
    功能:在socket上接收一个连接
    参数:
    sockfd:指定了监听的socket
    addr:在这个地址空间里填充了客户端的地址和端口号
    addrlen:空间里指定了addr的长度。如果addr为NULL,那么也要设置为NULL
    返回值:
    -1  错误   errno被设置
    返回一个非负的整数,就是连接描述符
    
    5、使用conn_fd和客户端通讯
    (1)获取客户端的请求
    read(2)
    (2)处理客户端请求
    (3)响应客户端
    write(2)
    
    6、关闭conn_fd,终止和客户端的通讯
    close(conn_fd);
    
    客户端的编程模型
    1、创建一个用于通讯的设备(通讯端点)
    socket(2)
    2、使用这个端点连接到服务器(IP地址和端口号)
    connect(2)
    int connect(int sockfd, const struct sockaddr *addr,
                       socklen_t addrlen);
    功能:在socket上发起一个连接
    参数:
    sockfd:指定socket,将这个socket连接到addr的地址空间
    addr:指定具体的地址空间,要连接到的地址空间。server
    addrlen:指定了addr的长度
    返回值:
    0  成功
    -1 错误  errno被设置
    
    3、向服务器发送消息
    4、等待服务器端的响应消息
    5、处理服务器的响应消息
    6、关闭设备,结束本次通讯。
    
    举例说明  编写基于TCP的通讯模型
    服务器端代码  参见   server.c
    客户端代码参见   client.c
    172.30.3.93
    
    二、并发服务器的实现
    三种方法实现服务器的并发    多进程   多线程    多路复用
    使用多进程实现服务器的并发功能
    什么时候?什么地方?子进程才登场。
    fork(2)
    
    子进程负责的任务
    子进程负责和客户端的通讯
    关闭s_fd。
    信息处理
    关闭和客户端的连接
    
    
    父进程负责的任务
    父进程负责从未决连接队列中取出一个连接,创建和客户端通讯的文件描述符
    创建子进程
    
    关闭和客户端的连接
    负责对子进程收尸。非阻塞收尸
  • 相关阅读:
    Yii2框架之旅(三)
    Yii2框架之旅(二)
    Redis本地集群搭建(5版本以上)
    Redis入门笔记
    Java如何使用elasticsearch进行模糊查询--转载
    springboot集成elasticsearch7.6.1,常用api调用,创建,查找,删除索引,crud,高亮。。。--转载
    SpringBoot整合Elasticsearch7.2.0的实现方法-转载
    Spring Webflux 入门 -转载
    java 视频流截屏,形成缩略图
    记录一下 spring boot 线程处理返回数据
  • 原文地址:https://www.cnblogs.com/Kernel001/p/7732646.html
Copyright © 2020-2023  润新知