zoukankan      html  css  js  c++  java
  • BSD socket编程学习

    1.socket简介

    BSD是实现TCP/IP协议通信的软件系统,socket是应用编程接口,为app提供使用TCP/IP协议通信的接口。

    网络层IP提供点到点服务(IP地址标识),传输层TCP和UDP提供端到端的服务(端口号标识)。

    2.socket地址结构

    2.1 两种socket结构

    socket则需要包含了所有这些信息,IP地址,端口号等,那么socket的包含所有这些信息的数据结构和使用方式又是什么样的呢?

    有两种socket地址包含了这些信息,一种是linux内核kernel所采用的存储结构sockaddr, 另外一种是具有互联网风格的sockaddr_in,这两种格式是兼容的

    //sys/socket.h
    /*
    * [XSI] Structure used by kernel to store most addresses. */ struct sockaddr { __uint8_t sa_len; /* total length */ sa_family_t sa_family; /* [XSI] address family */ char sa_data[14]; /* [XSI] addr value (actually larger) */ };

    可以看到OS采用的这种sockaddr结构 存储绝大部分的地址

    //netinet/in.h
    /*
    * Socket address, internet style. */ struct sockaddr_in { __uint8_t sin_len; sa_family_t sin_family; in_port_t sin_port; struct in_addr sin_addr; char sin_zero[8]; };

    /*
     * Internet address (a structure for historical reasons)
     */
    struct in_addr {
        in_addr_t s_addr;
    };

    sockaddr_in这种风格的数据结构便于进行(因特网)网络通信,所以常常需要在这两种格式间进行转换。

    2.2 两种socket地址结构转换

    对于转换函数htons,htonl,inet_addr,inet_aton,inet_ntoa等

    2.2.1 本地->网络

    • 将主机字节顺序转化为网络字节顺序:htons,htonl
    1. htons 将主机的无符号短整型数转换成网络字节顺序,与之相反的是ntohs;
    2. htonl 将主机的无符号长整型的网络字节顺序,与之相反的是ntohl;
    • IP地址,将字符串转换为32bit的IP地址:inet_addr,inet_aton
    1. inet_addr 将字符串转换为32bit二进制网络字节序的ipv4地址(in_addr)   e.g."127.0.0.1"-> uint32_t, 点分形式“a.b.c.d”任何一项都不能超过255,否则返回INADDR_NONE;
    2. inet_aton将一个字符串IP地址转化为一个32bit的网络序列ipv4地址, 与inet_addr的区别就是它认为“a.b.c.d”中任意一项=255都是有效地, 与之相反的是inet_ntoa;

    2.2.2 网络->本地

    • 将网络字节顺序转化为主机字节顺序:ntohs,ntohl
    • IP地址,将32bit的网络IP地址 转换为 点分形式字符串: inet_aton

    2.2.3大端序和小端序

    为什么要进行这些麻烦的转化呢?

    主要原因是在进行网络通信时候,使用的是网络字节顺序NBO(Network Byte Order),按从高位到低位的顺序存储、发送,即MSB(高位字节优先),这样避免兼容问题;

    但是在本地主机存储的时候,却使用的是主机字节顺序HBO(Host Byte Order),这是跟具体的CPU设计相关的。

    这就引出另外一个问题:大端序和小端序。

    • 大端序 最高字节数存储在内存地址最低位(起始位)(可以简单理解成尾端最大(高)字节)

    假如现在内存中地址位为0x10的位置处,存储了一个4B数据0x07654321 ->

    地址 内容 数的字节位
    0x13 0x21  
    0x12 0x43  
    0x11 0x65  
    0x10 0x07 最高位
    • 小端序最低字节数存储在内存地址最低位(起始位)(可以简单理解成尾端最小(低)字节)

    假如现在内存中地址位为0x10的位置处,存储了一个4B数据0x07654321 ->

    地址 内容 数的字节位
    0x13 0x07  
    0x12 0x65  
    0x11 0x43  
    0x10 0x21 最低位

    判断方法,最好只看起始位(地址低位)是最高字节数据(大端序)还是最低字节数据(小端序)。

    3.编程模型

    Server

    步骤 内容 data structure/API 备注
    1

    初始化socket地址(internet风格 协议簇, IP地址, 端口号)

    struct sockaddr_in

    2 创建socket (tcp/udp, 字节流等) socket()
    3 绑定socket和socket地址(本地系统风格) bind()
    4 监听socket(IP地址和端口) listen()
    5* 接收连接请求 accept() 响应客户端连接请求connect()
    6* 发送数据 send() 向连接的客户端发送数据
    7* 接收数据 recv() 接收连接的客户端发送数据
    8 关闭socket close()
  • 相关阅读:
    R语言入门视频笔记--2--一些简单的命令
    Java 虚拟机内存优化
    Apollo 配置中心
    Apollo本地缓存文件
    SpringBoot 远程调试
    SpringCloud微服务架构下 部署在ECS上 403
    Nginx 常用命令
    阿里云数据库Redis版 ERR invalid password
    Apollo配置中心搭建
    Gateway 访问超时 返回504
  • 原文地址:https://www.cnblogs.com/fortunely/p/4886413.html
Copyright © 2011-2022 走看看