11月17日笔记网络编程2_Socket套接字及TCP\UDP

1.Socket套接字
    Socket套接字是一个编程接口(网络编程接口)
    是一个特殊的文件描述符(read/write)
    socket可以用于TCP/IP,也可用于IPC,
    蓝牙....、

    socket是独立与具体协议的编程接口,这个接口位域
    TCP/IP的四层模型中的应用层和传输层之间

    Sokcet套接字类型由三种
    (1)流式套接字(SOCK_STREAM)
        面向字节流 针对采用TCP的应用
    (2)数据报套接字(SOCK_DGRAM)
        针对采用UDP通信的应用 比如视频 ,可能掉包,TCP不会掉包
    (3)原始套接字(SOCK_RAW)
        直接跳过传输层


2.基本的TCP套接字编程流程
    任何一个网络应用都有 通信双方
        Client   客户端
        Server 服务端
    
    TCP网络应用
        TCP Server
        TCP Client
    
    任何一个网络应用
        传输层协议(TCP/UDP) + IP + 端口
    
    “网络地址”
        任何网络应用一方都需要一个网络地址来标识自己
    
    TCP网络应用的数据传输流程的大概过程
        建立连接:
            “三次握手”
        
        发送/接收网络数据
            write/send/sendto
            read/recv/recvfrom
        关闭连接
            “四次挥手”

    TCP网络应用的编程流程
        TCP Server
            socket :创建一个socket套接字
            bind:    把服务器的套接字和网络地址绑定在一起
                如果你想要别人来主动连接你,你就需要
                bind一个地址,并且把这个地址告诉别人

                不调用bind,不代表你的socket没有地址
                相反,无论是否调用bind ,socket通信时,
                内核都会动态的为你socket指定一个地址

            listen:      监听 让套接字进入一个监听的状态
            accept:接收客户端的连接
                    如果你多次调用accept,就可以和不同的
                    客户建立连接

            至此 你们就可以等待用户来连接你  三次握手

            write/send/sendto
            read/recv/recvfrom
            ......

            close/shutdown:“四次挥手”
        
        TCP Client
            socket    :创建套接字
            bind        :可要可不要 如果需要别人来连接你 就需要
            connect :主动和TCP Server建立连接
                三次握手

            write/send/sendto
            read/recv/recvfrom
            ......   
            
            close/shutdown:“四次挥手”    


3.socket具体的API函数解析
    (1)socket:创建一个套接字

        NAME
                socket - create an endpoint for communication

        SYNOPSIS
            #include <sys/types.h>          /* See NOTES */
            #include <sys/socket.h>

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

        int domain:指定域 协议族,socket接口不仅仅局限于
                        TCP/IP,还能用于蓝牙 IPC ...
                        每一种下面又有很多自己的协议,所以我们把Ipv4
                        下面的所有协议都归类到一个域去
                        AF_INET       Ipv4协议族
                        AF_INET6     Ipv6协议族

       int type   :指定你要创建套接字的类型
                 SOCK_STREAM:流式套接字 -》tcp
                 SOCK_DGRAM:  数据包套接字 -》UDP
                 SOCK_RAW:        原始套接字

          int protoco  :指定具体的应用层协议的时候
                        指定为0  (私有协议)
                
                返回值
                    成功返回一个套接字描述符(>2 文件描述符   任意一个进程 系统都会为他打开三个文件 标准输入标准输出标准出错)
                    失败返回-1 同时errno被设置

            (2)网络地址结构体
                socket接口不经用于ipv4也用于ipv6
                .....
                不同的协议族,它们地址的类型也是不一样
                socket编程接口有一个通用的“网络地址接口

虚拟机里面的地址:    /usr/src/linux-headers-5.4.0-89-generic/include/linux

               struct sockaddr {
                    sa_family_t    sin_family;    /* address family, AF_xxx    */0
                                                                指定协议族
                    char                sa_data[14];    /* 14 bytes of protocol address    */
                };

                IPV4 协议地址的结构

                struct sockaddr_in
                {
                    sa_family_t       sin_family;//指定协议族为 AF_INET
                    u_int16_t          sin_port;//端口号
                    struct in_addr   sin_addr;//ip地址
                    char                  sin_zero[8];//凑字数的 为了和sockaddr结构体保持大小一致
                };

                struct in_addr
                {
                    in_addr_t   s_addr;
                };


                把  主机的字节序  转为  网络字节序

                NAME
                    htonl,  htons,  ntohl,  ntohs  - convert values between host and network byte
                    order
                    h host
                    n network
                        l long 32bits
                        s short 16bits

                SYNOPSIS
                    #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);


            IP地址间的转化函数
            点分式 《===》socket 接口的类型

            SYNOPSIS
                    #include <sys/socket.h>
                    #include <netinet/in.h>
                    #include <arpa/inet.h>

                            a: addr 点分式字符串
                            n: network 网络地址
                            a to n  点分式转网络地址
                    int inet_aton(const char *cp, struct in_addr *inp);

      const char *cp    :指向要转换的点分式字符串
                                "192.168.31.4"
      struct in_addr *inp :指向接收地址的结构 用来保存转换后的IP地址
                        返回值
                            成功返回0
                            失败返回-1 同时errno被设置

                    inet_addr  把cp指向的点分式ip字符串转化为
                            ip地址的结构中的成员

                    in_addr_t inet_addr(const char *cp);

                   inet_network 和 inet_addr的功能是一样的 
                                实现的方式不一样

                    in_addr_t inet_network(const char *cp);

                  网络地址 转化为  点分式IP地址字符串

                    char *inet_ntoa(struct in_addr in);

   
    (3) bind 把ipv4的网络地址 绑定到一个socket上面去

        NAME
            bind - bind a name to a socket

        SYNOPSIS
            #include <sys/types.h>          /* See NOTES */
            #include <sys/socket.h>

            int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

                sockfd    :要绑定的套接字文件描述符
                addr        :通用的网络地址结构体的指针 强制转换
                addrlen   :指定addr指向的地址结构的长度 sizeof
                返回值 
                    成功返回0
                    失败返回-1 同时errno被设置
    
    (4)listen:让套接字进入监听模式

        NAME
            listen - listen for connections on a socket

        SYNOPSIS
            #include <sys/types.h>          /* See NOTES */
            #include <sys/socket.h>

            int listen(int sockfd, int backlog);

                sockfd        :要监听的套接字的描述符
                backlog      : 同时能够处理请求(同时进行三次握手)的数目
                    5,10
                返回值
                    成功返回0
                    失败返回-1 同时errno被设置
    (5)accept:用于TCP Server接收一个客户端的tcp connection建立的请求

        NAME
            accept, accept4 - accept a connection on a socket

        SYNOPSIS
            #include <sys/types.h>          /* See NOTES */
            #include <sys/socket.h>

            int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

                    sockfd   :一个监听套接字;
                    addr      :网络地址的指针 指向的空间用于保存客户端的地址信息的
                    addrlen :上一个参数的指向的空间大小是多少呢?

            返回值
                        成功返回与该客户端的 连接套接字的描述符
                            后续与该客户端的数据交换都是通过这个套接字描述符。
                        失败返回-1 同时errno被设置

    (6)connect 主要用于tcp client 去连接tcp server

    NAME
        connect - initiate a connection on a socket

    SYNOPSIS
        #include <sys/types.h>          /* See NOTES */
        #include <sys/socket.h>

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

                sockfd    :套接字文件描述符
                addr        :你要和谁建立连接
                addrlen   :网络地址结构体的长度是多少
            返回值
                成功返回0
                失败返回 -1;
        
    (7)往套接字上面发送数据
        write/send/sendto

        NAME
            send, sendto, sendmsg - send a message on a socket

        SYNOPSIS
            #include <sys/types.h>
            #include <sys/socket.h>

            ssize_t send(int sockfd, const void *buf, size_t len, int flags);

                    sockfd:套接字的文件描述符
                    buf     : 要发送的数据在哪里
                    len     : 要发送的数据有多大
                    flags  : 一般填0
                返回值:
                    成功返回实际发送的字节数
                    失败返回-1 同时errno被设置

                sendto 可以用于TCP 也可以用于UDP
                UDP只能使用sendto发送数据

 

            ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                            const struct sockaddr *dest_addr, socklen_t addrlen);

                        socket buf len flags 同上面一样
                        dest_addr :要发送给谁 目标的地址和端口
                        addrlen     :地址结构的大小
                    返回值
                        成功返回实际发送的字节数
                        失败返回-1 同时errno被设置
    
    (8)从套接字上接收数据
        read/recv/recvfrom

        NAME
            recv, recvfrom, recvmsg - receive a message from a socket

        SYNOPSIS
            #include <sys/types.h>
            #include <sys/socket.h>
                从套接字上面接收数据
            ssize_t recv(int sockfd, void *buf, size_t len, int flags);

                    sockfd   :要从那个套接字上面接收数据
                    buf        :数据放哪里
                    len        :想要接收多大的数据 要小于buf大小(单位:字节)
                    flags     :一般为0   阻塞接收数据
                        MSG_DONTWAIT   非阻塞接收数据
                    
                    返回值
                        成功返回实际接收的字节数
                        失败返回-1 同时errno被设置

                    UDP只能用recvfrom ,recvfrom可以用于TCP也可以用与UDP

            ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                                struct sockaddr *src_addr, socklen_t *addrlen);

                        src_addr: 发送者的网络地址信息,不是指你要接收谁的信息
                                    可以填NULL 表示不关心谁发给我
                                    是一个sockaddr指针
                        addrlen: src_addr指向空间的大小                    返回值
                        成功返回实际接收的字节数
                        失败返回-1 同时errno被设置
    (9)关闭套接字
        close/shutdown

        NAME
            shutdown - shut down part of a full-duplex connection

        SYNOPSIS
            #include <sys/socket.h>

            int shutdown(int sockfd, int how);

                sockfd    :要关闭那个套接字
                how        :有三个选项
                    SHUT_RD:关闭读
                    SHUT_WR:关闭写
                    SHUT_RDWR:关闭读写 等效与 close
                返回值
                    成功返回0
                    失败返回-1 同时errno被设置



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值