• TCP/IP 网络编程(一):基础知识


    声明:本系列文章参考书:《TCPIP网络编程 》[韩] 尹圣雨 

    本人仅作笔记使用

    目录

    一、网络编程和套接字

    二、Linux文件操作

    文件描述符

    打开文件

    关闭文件

    将数据写入文件

    读取文件中的数据

    三、套接字类型与协议设置

    协议:计算机间对话需遵守的通信规则

    创建套接字

    协议族

    套接字类型1:面向连接(SOCK_STREAM)

    套接字类型2:面向消息(SOCK_DGRAM)

    四、地址族和数据序列

    IPV4的地址族ABCDE类型:

    端口号:区分套接字(应用程序)

    表示IPv4地址的结构体

    网络字节序与地址变换

    IP字符串转换为整数型

    网络字节序整数型IP转换为字符串


    一、网络编程和套接字

    网络编程:编写程序使得两台联网的计算机相互交换数据。

    套接字:操作系统提供的软件设备,用来连接网络的工具。

    直观理解:

    socket:电话机

    bind:分配电话号码(IP地址和端口号)

    listen:连接电话线,等待来电

    accpet:接电话,拿起话筒

    服务端的套接字创建过程:

    • 调用socket创建套接字
    • 调用bind分配IP地址和端口好
    • 调用listen转为可接受请求状态
    • 调用accept受理连接请求
    1. #include
    2. int socket(int domain,int type,int protocol);
    3. int bind(int sockfd,struct sockaddr *myaddr,socklen_t addrlen);
    4. int listen(int sockfd,int backlog);
    5. int accept(int sockfd,struct sockaddr*,socklen_T *addrlen);
    6. //成功返回0,失败返回-1

    客户端的套接字创建过程:

    • 调用socket创建套接字
    • 调用connect向服务器发送连接请求
    1. #include
    2. int connect(int sockfd,struct sockaddr* serv_addr,socklen_t addrlen);
    3. //成功返回0,失败返回-1

    二、Linux文件操作

    文件描述符

    文件句柄。但句柄主要是Windows中的术语,Linux主要叫描述符。每当生成文件或套接字,操作系统将返回分配给它们的整数。这个整数将成为程序员与操作系统之间良好沟通的渠道。实际上,文件描述符只不过是为了方便称呼操作系统创建的文件或套接字而赋予的数而已。

    直白理解:论文号相当于文件描述符论文相当于文件或套接字

    打开文件

    1. #include
    2. #include
    3. #include
    4. int open(const char *path, int flag);

    path:文件名的字符串地址

    flag:文件打开模式信息,若传递多个参数通过或运算(|)组合

    关闭文件

    1. #include
    2. int close(int fd);

    fd:需要关闭的文件或套接字的文件描述符

    Linux操作系统不区分与套接字,此函数不仅可以关闭文件,也可以关闭套接字

    将数据写入文件

    向文件输出(传输)数据。

    1. #include
    2. ssize_t write(int fd, const void* buf, size_t nbytes);

    fd:数据传输对象的文件描述符

    buf:要传输数据的缓冲地址值

    nbytes:传输数据的字节数

    (注:size_t为unsigned int类型,ssize_t为signed,同时操作系统为了与程序员的代码区分加了后缀_t)

    读取文件中的数据

    输入(接受)数据

    1. #include
    2. ssize_t read(int fd, void *buf, size_t nbytes);

    fd:数据接收对象文件描述符

    buf:接收数据缓冲地址值

    nbytes:接收数据最大字节数

    三、套接字类型与协议设置

    协议:计算机间对话需遵守的通信规则

    创建套接字

    1. #include
    2. int socket(int domain, int type, int protocol);

    domain:套接字中使用的协议族

    type:套接字数据类型

    protocol:使用的协议

    协议族

    套接字类型1:面向连接(SOCK_STREAM)

    特点:

    • 传输过程中数据不会丢失
    • 按序传输
    • 传输的数据不存在数据边界
    • 套接字必须一一对应

    总结:可靠的按序传递的基于字节的面向连接的数据传输方式的套接字。

    100个糖果是分批传递的,但接收者凑齐100个后才装袋

    也就是说接受和发送的套接字内部有缓冲,简言之字节数组,通过传输的数据保存在该数组。

    因此收到数据并不意味着马上调用read函数。

    有可能装满缓冲后调用1次read。

    接受缓冲满了,发送端将停止传输。

    int tcp_socket = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);

    套接字类型2:面向消息(SOCK_DGRAM)

    特点:

    • 强调快速传输而非传输顺序
    • 传输的数据可能丢失也可能损毁
    • 传输的数据有数据边界
    • 限制每次传输的数据大小

    总结:不可靠的不按序传递的以数据的高速传输为目的的套接字。

    int udp_socket = socket(PF_INET,SOCK_DGRAM,IPPROTE_UDP);

    四、地址族和数据序列

    网络地址:

    • IPV4:4字节地址族
    • IPV6:16字节地址族

    IPV4的地址族ABCDE类型:

    • A类地址首字节范围:0-127(首位从0开始)
    • B类地址首字节范围:128-191(首位从10开始)
    • C类地址首字节范围:192-223(首位从110开始)

    端口号:区分套接字(应用程序)

    • NIC(Network Interface Card,网卡)
    • 端口号不能重复,但TCP和UDP可以使用同一个端口

    表示IPv4地址的结构体

    1. struct sockaddr_in{
    2. sa_family_t sin_family; //地址族
    3. uint16_t sin_port; //16位TCP/UDP端口号
    4. struct in_addr sin_addr; //32位IP地址
    5. char sin_zero[8]; //不适用
    6. };
    7. struct in_addr{
    8. In_addr_t s_addr;//32位IPv4地址
    9. };

    初始化:

    1. struct sockaddr_in addr;
    2. char *serv_ip = "211.217.168.13";
    3. char *serv_port = "9190";
    4. memset(&addr, 0 ,sizeof(addr));
    5. addr.sin_family = AF_INET;
    6. addr.sin_addr.s_addr = inet_addr(serv_ip);
    7. addr.sin_port = htons(atoi(serv_port));

    POSIX(Portable Operating System Interface,可以指操作系统接口),为UNIX系列操作系统设立的标准。

    网络字节序与地址变换

    大端序:

    小端序:

    网络字节序统一为大端序。

    字节序转换:

    1. unsigned short htons (unsigned short);
    2. unsigned short ntohs (unsigned short);
    3. unsigned long htonl (unsigned long);
    4. unsigned long ntohl (unsigned long);

    h代表主机(host)字节序,n代表网络(network)字节序 

    IP字符串转换为整数型

    1. #include
    2. in_addr_t inet_addr(const char *string);
    3. //成功返回32位大端序整数值,失败返回INADDR_NONE
    1. #include
    2. int inet_aton(const char* string, struct in_addr *addr);

    网络字节序整数型IP转换为字符串

    1. #include
    2. char *inet_ntoa(struct in_addr adr);

     注意,该函数返回字符串地址意味着字符串已保存到内存空间,但并未向程序员要求分配内存,而是在内部申请内存并保存了字符串。

    也就是说,调用完该函数,需要立即字符串复制到其他内存空间。

  • 相关阅读:
    做题杂记333
    cnpm i报错:node-sass@^6.0.1 run postinstall node scripts/build.js error
    第20篇 Vue命令简介
    【内核的设计与实现笔记】| 【01】初步了解内核
    学生HTML个人网页作业作品 HTML+CSS校园环保(大学生环保网页设计与实现)
    SpringCloud - Nacos 结合 K8s 优雅关闭服务(平滑升级)
    STM32F103标准库开发---SPI实验---底层驱动程序
    如何使用Linux DataEase数据可视化分析工具结合内网穿透实现远程办公
    toPlainString()
    java获取字符串集合中每个字符并且组成一个新的集合实现
  • 原文地址:https://blog.csdn.net/Jason6620/article/details/127832039