zoukankan      html  css  js  c++  java
  • 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 实例

  • 相关阅读:
    Android 编程下 Eclipse 恢复被删除的文件
    Android 编程下背景图片适配工具类
    Android 编程下 Managing Your App's Memory
    Android 编程下代码之(QQ消息列表滑动删除)
    Android 编程下 Canvas and Drawables
    Android 编程下 AlarmManager
    Android 编程下去除 ListView 上下边界蓝色或黄色阴影
    Java 编程下字符串的 16 位、32位 MD5 加密
    C#枚举类型和int类型相互转换
    MVC和普通三层架构的区别
  • 原文地址:https://www.cnblogs.com/Mike2019/p/12091077.html
Copyright © 2011-2022 走看看