day-02 套接字类型与协议设置、地址族和数据序列

一.套接字类型

1.面向连接的套接字(SOCK_STREAM)

特点:

  • 传输过程中数据不会消失
  • 按顺序传输数据
  • 传输的数据不存在数据边界

2.面向消息的套接字(SOC_DGRAM)

特点:

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

 二.地址信息的表示

1.结构体 sockaddr_in 的成员分析

struct sockaddr_in {sa_family_t sin_family; // 地址族(一般为AF_INET)in_port_t sin_port;     // 端口号struct in_addr sin_addr; // IPv4地址char sin_zero[8];       // 用于对齐的填充字段
};
  • sin_family :每种协议族适用的地址族均不同,用来存储协议地址族,区分协议
  • sin_port:保存16位端口号,并且是以网络字节序保存
  • sin_addr:保存32位IP地址信息,并且也以网络字节序保存
  • sin_zero:无特殊含义。

三.网络字节序和地址变换

1.字节序和网络字节序

00000000 00000000 00000000 00000001  //小端序格式00000001 00000000 00000000 00000000  //大端序格式

cpu向内存保存数据的方式有2种,这意味着cpu解析数据的方式也有两种。

在网络传输数据时约定统一方式,也就是网络字节序,统一为大端序。(即先把数据数组转换为大端序格式再进行网络传输)。

2.字节序转换

在网络编程中,字节序转换是指将数据在不同字节序(大端字节序和小端字节序)之间进行转换的过程。在进行网络通信时,为了确保数据在发送和接收的过程中能够正确解析,需要进行字节序的转换。
常用的字节序转换函数有以下两个:
htons和ntohs:用于16位无符号整数的字节序转换。

  • htons(host to network short)用于将主机字节序转换为网络字节序。
  • ntohs(network to host short)用于将网络字节序转换为主机字节序。

htonl和ntohl:用于32位无符号整数的字节序转换。

htonl(host to network long)用于将主机字节序转换为网络字节序。
ntohl(network to host long)用于将网络字节序转换为主机字节序。
这些函数可以帮助我们在不同字节序之间进行转换,确保数据在网络传输过程中的正确性和可靠性。例如,如果要将一个16位整数从主机字节序转换为网络字节序,可以使用htons函数进行转换:uint16_t hostValue = 0x1234;
uint16_t networkValue = htons(hostValue);
//类似地,如果要将一个32位整数从主机字节序转换为网络字节序,可以使用htonl函数进行转换:uint32_t hostValue = 0x12345678;
uint32_t networkValue = htonl(hostValue);
//在接收数据时,可以使用相应的ntohs和ntohl函数将网络字节序转换为主机字节序。

3.网络地址的初始化与分配

(1)inet_addr 函数

        用于将IPv4地址的点分十进制表示形式转换为32位无符号整数。它位于<arpa/inet.h> 头文件中,并且返回类型是in_addr_t在使用inet_addr函数时需要检查返回值是否等于INADDR_NONE,以判断是否转换成功。如果返回值等于INADDR_NONE(-1),则表示转换失败,可能是因为输入的IP地址格式不正确。
#include <iostream>
#include <arpa/inet.h>int main() {const char* ipStr = "192.168.0.1";// 将点分十进制形式的IPv4地址转换成32位无符号整数in_addr_t ipAddr = inet_addr(ipStr);if (ipAddr == INADDR_NONE) {std::cout << "Invalid IP address" << std::endl;} else {std::cout << "IP address in network byte order: " << ipAddr << std::endl;}return 0;
}in_addr_t inet_addr(const char *cp);inet_addr函数转换网络主机地址(如192.168.1.10)为网络字节序二进制值,如果参数char *cp无效,函数返回-1(INADDR_NONE),这个函数在处理地址为255.255.255.255时也返回-1,255.255.255.255是一个有效的地址,不过inet_addr无法处理;

(2)inet_pton 函数

        一个用于将IPv4和IPv6地址字符串转换为网络字节序的二进制形式的函数。若成功则返回值为1,否则返回值为0.

#include <iostream>
#include <arpa/inet.h>int main() {const char* ipv4Address = "192.168.0.1";struct in_addr ipv4Binary;if (inet_pton(AF_INET, ipv4Address, &ipv4Binary) > 0) {std::cout << "IPv4 address in binary form: 0x" << std::hex << ntohl(ipv4Binary.s_addr) << std::endl;} else {std::cout << "Invalid IPv4 address" << std::endl;}const char* ipv6Address = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";struct in6_addr ipv6Binary;if (inet_pton(AF_INET6, ipv6Address, &ipv6Binary) > 0) {std::cout << "IPv6 address in binary form: ";for (int i = 0; i < 16; ++i) {std::cout << std::hex << static_cast<int>(ipv6Binary.s6_addr[i]);}std::cout << std::endl;} else {std::cout << "Invalid IPv6 address" << std::endl;}return 0;
}

(3)inet_ntop 函数

        一个用于将二进制形式的IPv4或IPv6地址转换回点分十进制表示的函数,该函数不涉及字节序的转换。返回值:若成功则为指向结构的指针,若出错则为NULL。

#include <iostream>
#include <arpa/inet.h>int main() {// IPv4地址转换struct in_addr ipv4Addr;inet_pton(AF_INET, "192.168.0.1", &(ipv4Addr.s_addr));char ipv4Str[INET_ADDRSTRLEN];inet_ntop(AF_INET, &(ipv4Addr.s_addr), ipv4Str, INET_ADDRSTRLEN);std::cout << "IPv4 address: " << ipv4Str << std::endl;// IPv6地址转换struct in6_addr ipv6Addr;inet_pton(AF_INET6, "2001:0db8:85a3:0000:0000:8a2e:0370:7334", &(ipv6Addr.s6_addr));char ipv6Str[INET6_ADDRSTRLEN];inet_ntop(AF_INET6, &(ipv6Addr.s6_addr), ipv6Str, INET6_ADDRSTRLEN);std::cout << "IPv6 address: " << ipv6Str << std::endl;return 0;
}

(4)网络地址初始化

  • 客户端(服务器初始化只需要将IP地址参数设置为 INADDR_ANY,自动获取服务端的IP地址)

#include <iostream>
#include <arpa/inet.h>  // 包含网络地址相关的头文件int main() {// 初始化网络地址结构struct sockaddr_in serverAddress;serverAddress.sin_family = AF_INET;  // 设置地址族为IPv4serverAddress.sin_port = htons(8080);  // 设置端口号(使用htons函数进行字节序转换)serverAddress.sin_addr.s_addr = inet_addr("192.168.0.1");  // 设置IP地址(使用inet_addr函数将字符串IP转换为二进制形式)// 打印初始化的网络地址信息std::cout << "IP地址: " << inet_ntoa(serverAddress.sin_addr) << std::endl;  // 使用inet_ntoa函数将二进制IP转换为字符串形式std::cout << "端口号: " << ntohs(serverAddress.sin_port) << std::endl;  // 使用ntohs函数将端口号从网络字节序转换为主机字节序return 0;
}

  • 向套接字分配网络地址

bind()函数是在网络编程中常用的函数之一,它用于将一个套接字(socket)与特定的IP地址和端口号绑定起来。以下是关于bind()函数的一些详细说明:

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);参数解释:sockfd:表示要绑定的套接字描述符(socket file descriptor)。addr:指向sockaddr结构体的指针,其中包含了要绑定的IP地址和端口号信息。addrlen:表示addr结构体的长度。返回值:若绑定成功,则返回0。若出现错误,则返回-1,并设置对应的错误码(可以使用errno全局变量查看具体错误信息)。简单示例:#include <iostream>
#include <arpa/inet.h>
#include <sys/socket.h>int main() {int sockfd = socket(AF_INET, SOCK_STREAM, 0);  // 创建套接字if (sockfd == -1) {std::cerr << "Failed to create socket." << std::endl;return 1;}struct sockaddr_in serverAddr;serverAddr.sin_family = AF_INET;  // 使用IPv4地址族serverAddr.sin_port = htons(8080);  // 绑定端口号为8080serverAddr.sin_addr.s_addr = INADDR_ANY;  // 绑定所有可用的IP地址if (bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {std::cerr << "Failed to bind socket." << std::endl;return 1;}std::cout << "Socket bound successfully." << std::endl;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/54594.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++】const成员 | 取地址运算符重载

Ⅰ. const成员 两种const 我们知道&#xff0c;用const修饰 能起到保护&#xff0c;使之不被修改的作用。 修饰指针的const有两种位置&#xff1a; 我们学过的this指针&#xff0c;就被后者所修饰&#xff0c;因此无法被修改。 const成员函数 ➡️为了保护函数里的成员&…

《Java极简设计模式》第05章:原型模式(Prototype)

作者&#xff1a;冰河 星球&#xff1a;http://m6z.cn/6aeFbs 博客&#xff1a;https://binghe.gitcode.host 文章汇总&#xff1a;https://binghe.gitcode.host/md/all/all.html 源码地址&#xff1a;https://github.com/binghe001/java-simple-design-patterns/tree/master/j…

【日常积累】Linux下sftp搭建

概述 SFTP是Secure File Transfer Protocol的缩写&#xff0c;是安全文件传送协议。可以为传输文件提供一种安全的加密方法。跟ftp几乎语法功能一样。 SFTP是SSH的一部分&#xff0c;是一种传输档案至Blogger伺服器的安全方式。它本身没有单独的守护进程&#xff0c;必须使用s…

Elasticsearch 8.X reindex 源码剖析及提速指南

1、reindex 源码在线地址 为方便大家验证&#xff0c;这里给出 reindex github 源码地址。 https://github.com/elastic/elasticsearch/blob/001fcfb931454d760dbccff9f4d1b8d113f8708c/server/src/main/java/org/elasticsearch/index/reindex/ReindexRequest.java reindex 常见…

开源软件的崛起:历史与未来

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

Lambda函数

一.概念 1.利用lambda表达式可以编写内嵌的匿名函数&#xff0c;用以替换独立函数或者函数对象 2.每当你定义一个lambda表达式后&#xff0c;编译器会自动生成一个匿名类&#xff08;这个类当前重载了&#xff08;&#xff09;运算符&#xff09;&#xff0c;我们称为闭包类型…

8.6 【C语言】返回指针值的函数

一个函数可以返回一个整型值、字符值、实型值等&#xff0c;也可以返回指针型的数据&#xff0c;即地址。 类型名 *类型名&#xff08;参数表列&#xff09; 例8.25 有a个学生&#xff0c;每个学生有b门课程的成绩。要求在用户输入学生序号以后&#xff0c;能输出该学生的全部…

Lazada商品详情接口 获取Lazada商品详情数据 Lazada商品价格接

一、引言 随着电子商务的迅速发展和普及&#xff0c;电商平台之间的竞争也日趋激烈。为了提供更好的用户体验和更高效的后端管理&#xff0c;Lazada作为东南亚最大的电商平台之一&#xff0c;开发了一种商品详情接口&#xff08;Product Detail API&#xff09;。该接口允许第…

数据可视化是什么?有什么工具?

一、什么是数据可视化&#xff1f; 数据可视化是一种通过图表、图形、地图和其他视觉元素将数据呈现给用户的方式。它是将复杂的数据转化为易于理解和解释的视觉形式的过程。数据可视化旨在帮助用户发现数据中的模式、趋势和关联&#xff0c;并从中获得洞察力。 数据可视化的…

根据源码,模拟实现 RabbitMQ - 转发规则实现(6)

目录 一、转发规则实现 1.1、需求分析 1.2、实现 Router 转发规则 1.2.1、bindingKey 和 routingKey 参数校验 1.2.2、消息匹配规则 1.2.3、主题交换机匹配规则 一、转发规则实现 1.1、需求分析 这里主要实现 routingKey 和 bindingKey 参数的校验&#xff0c;以及 Topic…

Python(.pyc)反编译:pycdc工具安装与使用

本文将介绍如何将python的.pyc文件反编译成源码&#xff0c;以便我们对源码的学习与改进。pycdc工具安装 下载地址&#xff1a; 1、Github地址&#xff1a;https://github.com/zrax/pycdc &#xff0c;下载后需要使用CMake进行编译。 2、已下载好及编译好的地址&#xff1a;ht…

ISIS路由协议

骨干区域与非骨干区域 凡是由级别2组建起来的邻居形成骨干区域&#xff1b;级别1就在非骨干区域&#xff0c;骨干区域有且只有一个&#xff0c;并且需要连续&#xff0c;ISIS在IP环境下目前不支持虚链路。 路由器级别 L1路由器只能建立L1的邻居&#xff1b;L2路由器只能建立L…

1.2 Kali Linux的网络配置

前言 最新文章请见此处&#xff0c;持续更新&#xff0c;敬请订阅&#xff01;https://blog.csdn.net/algorithmyyds/category_12418682.html 网络在如今的社会已是十分重要的媒介&#xff0c;如果没有网络&#xff0c;很多事情将难以办成。渗透测试也是一样——毕竟在攻击机…

Node opensslErrorStack 错误解决方法记录

从Git仓库中下载了一个老项目&#xff0c;使用npm install 安装后没有问题&#xff0c;当我使用npm run dev 的时候遇到了 OpenSSL 相关错误&#xff0c;例如 opensslErrorStack: [error:03000086:digital envelope routines::initialization error] 网上找了一下相关信息&am…

c# 数组反转

一个数组是{1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5&#xff0c;6}&#xff0c;把它变成{6&#xff0c;5&#xff0c;4&#xff0c;3&#xff0c;2&#xff0c;1} 1.创建一个和原数组长度类型一样的数组来接收反转的数据 private static void Main(string[] a…

学习设计模式之享元模式,但是宝可梦

前言 作者在准备秋招中&#xff0c;学习设计模式&#xff0c;做点小笔记&#xff0c;用宝可梦为场景举例&#xff0c;有错误欢迎指出。 享元模式 1 介绍 享元模式很好理解&#xff0c;它主要是为了减少创建对象的数量&#xff0c;属于结构型设计模式 目的&#xff1a;减少…

Python数据容器(列表list、元组tuple、字符串str、字典dict、集合set)详解

一、数据容器概念 相关介绍&#xff1a; 一种可以容纳多份数据的数据类型&#xff0c;容纳的每一份数据称之为一个元素。每一个元素&#xff0c;可以是任意类型的数据分为五类&#xff1a;列表[list]、元组(tuple)、字符串(str)、集合{set}、字典{dict} 相应区别&#xff1a…

Dubbo之PojoUtils源码分析

功能概述 PojoUtils是一个工具类&#xff0c;能够进行深度遍历&#xff0c;将简单类型与复杂类型的对象进行转换&#xff0c;在泛化调用时用到&#xff08;在泛化调用中&#xff0c;主要将Pojo对象与Map对象进行相互转换&#xff09; 功能分析 核心类PojoUtils分析 主要成员…

Jacoco XML 解析

1 XML解析器对比 1. DOM解析器&#xff1a; ○ 优点&#xff1a;易于使用&#xff0c;提供完整的文档树&#xff0c;可以方便地修改和遍历XML文档。 ○ 缺点&#xff1a;对大型文档消耗内存较多&#xff0c;加载整个文档可能会变慢。 ○ 适用场景&#xff1a;适合小型XML文档…

函数式编程-Stream流学习第二节-中间操作

1 Stream流概述 java8使用的是函数式编程模式,如同它的名字一样&#xff0c;它可以用来对集合或者数组进行链状流式操作&#xff0c;让我们更方便的对集合或者数组进行操作。 2 案例准备工作 我们首先创建2个类一个作家类&#xff0c;一个图书类 package com.stream.model;…