• Linux应用程序9--linux网络编程


    1 网络通信基础

    1.1 TCP/IP协议族

    2 网络框架

    3 TCP

    4 Socket

    4.1 Socket概述

      socket是在应用层和传输层之间的一个抽象层,他把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用,以实现进程在网络中通信。

    4.2 API详解

    4.2.1  socket():创建socket文件描述符

      为一个socket数据结构分配存储空间,成功时,返回一个用于监听的socket描述符。

    所需头文件 #include <sys/types.h> 
    #include <sys/socket.h>
    函数原型

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

     输入值    
    domain
     协议族
    AF_UNIX/AF_LOCAL:Unix域协议
    AF_INET:IPv4
    AF_INET6:IPv6
      type SOCKET_STREAM:TCP
    SOCKET_DGRAM:UDP
    SOCKET_RAW:提供传输层以下的协议,可以访问内部网络接口,例如接收和发送ICMP报文
    protocol 0,系统会根据type自动选择默认协议类型
    当type=SOCKET_RAW时需要设置此值说明协议类型
    返回值 -1,失败,失败原因存在于error中
    !=-1, 成功, 监听的socket描述符

     4.2.2 bind():将一个本地协议地址与监听socket文件描述符关联 

    所需头文件 #include <sys/types.h> 
    #include <sys/socket.h>
    函数原型

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

     输入值     sockfd 要关联的socket文件描述符
    addr 指向sockaddr,包含IP地址和端口信息的结构体
    addrlen sockaddr结构的大小,可设置sizeof(struct sockaddr)
    返回值 -1,失败,失败原因存在于error中
    0 , 成功

     4.4.3 listen() 实施监听服务

    所需头文件 #include <sys/types.h> 
    #include <sys/socket.h>
    函数原型

    int listen(int sockfd, int backlog);

     输入值     sockfd 要监听的socket文件描述符
    backlog 套接字排队的最大连接个数
    返回值 -1,失败,失败原因存在于error中
    0 , 成功, 

    4.4.4 accept()阻塞等待客户端接入 

      accept()函数仅被TCP类型的服务器程序调用,将从连接请求队列中获得连接信息,创建新的套接字,并返回该套接字的文件描述符,客户端可以通过这个描述符与服务器通信。

      通常我们把accept()第一个参数成为监听套接字(listening socket),把accept()功能返回值成为已连接套接字(connected socket)。

    所需头文件 #include <sys/types.h> 
    #include <sys/socket.h>
    函数原型

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

     输入值     sockfd 要关联的监听socket文件描述符
    addr 指向sockaddr,包含IP地址和端口信息的结构体
    addrlen sockaddr结构的大小,可设置sizeof(struct sockaddr)
    返回值 -1,失败,失败原因存在于error中
    成功,已连接的socket描述符

    4.4.5 connect()客户端调用来与服务器建立连接

    所需头文件 #include <sys/types.h> 
    #include <sys/socket.h>
    函数原型

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

     输入值     sockfd 要关联的监听socket文件描述符
    addr 指向sockaddr,包含IP地址和端口信息的结构体
    addrlen sockaddr结构的大小,可设置sizeof(struct sockaddr)
    返回值 -1,失败,失败原因存在于error中
    0 , 成功

    4.4.6 close()关闭连接的socket文件描述符

    所需头文件 #include <unistd.h> 
    函数原型

    int close(int sockfd)

     输入值     sockfd 要关联的socket文件描述符
    返回值 -1,失败,失败原因存在于error中
    0 , 成功

     4.4.7 shutdown()终止socket通信

    所需头文件
    #include <sys/socket.h>
    函数原型

    int shutdown(int s, int how)

     输入值     sockfd 要关联的socket文件描述符
    how 0(SHUT_RD):关闭socket连接的读这一半,不再接收套接字中的数据且现留在收缓冲区的数据作废
    1(SHUT_WR):关闭socket连接的写这一半(半关闭),但留在套接字发送缓冲区中的数据都会被发送,后跟TCP连接终止序列,不管访问计数是否大于0,此后将不能再执行对套接字的任何写操作
    2(SHUT_RDWR):socket连接的读、写都关闭
    返回值 -1,失败,失败原因存在于error中
    0 , 成功

     4.4.8 send()TCP类型数据发送

    所需头文件 #include <sys/types.h> 
    #include <sys/socket.h>
    函数原型

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

     输入值     sockfd 要关联的socket文件描述符
    addr 指向sockaddr,包含IP地址和端口信息的结构体
    addrlen sockaddr结构的大小,可设置sizeof(struct sockaddr)
    返回值 -1,失败,失败原因存在于error中
    0 , 成功

    4.4.9 recv()TCP类型数据接收

    所需头文件 #include <sys/types.h> 
    #include <sys/socket.h>
    函数原型

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

     输入值     sockfd 要关联的socket文件描述符
    *buf 接收缓冲区地址
    len 接收缓冲区数据长度(按字节计算)
    flags 0
    返回值 -1,失败,失败原因存在于error中
    !=-1 , 返回接收到的数据字节数

    4.4.10 sendto()UDP类型数据发送

    4.4.11 recvfrom()UDP类型数据接收

    4.2.12 htonl()、htons()、ntohl()、ntohs()

    网络字节序与本地字节序互相转换,规定网络字节序一律是大端模式,h——本机字节序(大端或者小端),n——网络字节序(大端)

    #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);  //网络字节序转换成本机字节序

    示例:

    uint32_t addr=0x12345678, result=0; 
    printf("%#x,    %#x
    ", addr, htonl(addr));

    结果:0x78563412

    4.2.11 inet_addr()

    in_addr_t inet_addr(const char *cp);  //将一个字符串形式的点分十进制IP地址转换为32位二进制网络字节序

    示例:

    addr = inet_addr(“192.168.0.11”);    //网络字节序:规定使用大端模式
    printf("addr=%#X
    ", addr);

    结果:addr=0XB00A8C0

     4.2.12 inet_ntoa()、inet_aton()

    int inet_aton(const char *cp, struct in_addr *inp);
    char *inet_ntoa(struct in_addr in);

    4.2.13 inet_ntop()、inet_pton()

      对于IPv4地址和IPv6地址都适用。

    #include <arpa/inet.h>
    /*将数值格式转化为点分十进制的ip地址格式*/ 
    const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);  //返回值:1,成功; 0,输入无效; -1,出错
    /*点分十进制IP地址转换为用于网络传输的数值格式*/
     int inet_pton(int af, const char *src, void *dst);  //返回值:NULL,出错

    示例:

    #include    <stdio.h>
    #include    <arpa/inet.h>
    int main(void)
    {
        /*1. inet_pton转换:点分十进制 转 网络数值格式*/
        struct in_addr addr;
        int ret=0;
        ret = inet_pton(AF_INET, "192.168.0.11", &addr);
        if(ret != 1){
            printf("inet_pton error
    ");
            return -1;
        }
        printf("addr=%#X.
    ", addr.s_addr);
    
        /*2. inet_ntop转换:网络数值格式 转 点分十进制*/
        char buf[50]={0};
        const char *p_ret=NULL;
        addr.s_addr = 0xB00A8C0;
        p_ret = inet_ntop(AF_INET, &addr, buf, sizeof(buf));
        if(p_ret == NULL){
            printf("inet_pton error
    ");
            return -1;
        }
        printf("addr=%s.
    ", buf);
    }

    结果:addr=0XB00A8C0.

       addr=192.168.0.11.

    4.2.14 sockaddr和sockaddr_in

     

     sinport和sin_addr都必须是网络字节序(NBO)。

    sockaddr缺陷是把sin_port和sin_addr混在一起放在了sa_data[14]里了;

    两者长度都是16个字节,因此可以互相转换;

    sockaddr常用于bind, connect, recvfrom, sendto等函数的参数

    4.3 实例

  • 相关阅读:
    asp.net微信开发第八篇----永久素材管理
    selenium模块
    request模块
    爬虫基本概念
    反向生成url
    admin的路由系统剖析
    popup方法
    ModelForm
    Django数据库操作性能相关
    缓存
  • 原文地址:https://www.cnblogs.com/Mike2019/p/12091077.html
Copyright © 2020-2023  润新知