当前位置: 首页 > news >正文

socket地址理解

socket介绍

套接字的基本概念

1. 套接字的定义:

  • 套接字(socket)是计算机网络中用于通信的端点,它抽象了不同主机上应用进程之间双向通信的机制。

2. 套接字的作用:

  • 套接字连接应用进程与网络协议栈,使得应用程序能够利用网络协议进行通信。
  • 它作为应用程序与网络协议栈的接口,通过操作系统提供的 API 进行数据交换。
套接字的工作机制

1. 双向通信:

  • 在网络通信中,套接字充当两个应用程序之间的通信连接点。
  • 一个应用程序可以将数据写入其所在主机的套接字,数据通过网络接口卡(NIC)和传输介质发送到目标主机的套接字,从而实现数据传输。

2. 组合与寻址:

  • 套接字由 IP 地址和端口号组成,形成唯一的通信端点。
  • 这种组合提供了一种机制,使数据包能够准确地传输到目标应用进程。

套接字在操作系统中的表示

1. 套接字作为文件:

  • 在 Linux 环境下,套接字是一种特殊的文件类型,被内核用伪文件(pseudo-file)表示。
  • 由于套接字被视为文件,因此可以使用文件描述符来引用和操作套接字。
  • 这种设计使得套接字的读写操作与普通文件的读写操作一致,统一了接口。

2. 区别于管道:

  • 虽然套接字与管道(pipe)类似,都用于进程间通信,但套接字主要用于网络进程间的数据传递,而管道主要用于本地进程间的通信。

套接字的类型

1. 常见的套接字类型:

  • 流式套接字(Stream Socket):提供面向连接的、可靠的数据传输服务,典型的协议是 TCP。
  • 数据报套接字(Datagram Socket):提供无连接的、不可靠的数据传输服务,典型的协议是 UDP。
总结

套接字是网络编程中的核心概念,提供了在不同主机上的应用进程之间进行通信的机制。它通过 IP 地址和端口号进行唯一标识,并在操作系统中作为特殊的文件类型进行管理,使得网络通信操作与文件操作一致,从而简化了编程接口。

socket 本身有“插座”的意思,在 Linux 环境下,用于表示进程间网络通信的特殊文件类型。本质为内核借助缓冲区形成的伪文件。既然是文件,那么理所当然的,我们可以使用文件描述符引用套接字。与管道类似的,Linux 系统将其封装成文件的目的是为了统一接口,使得读写套接字和读写文件的操作一致。区别是管道主要应用于本地进程间通信,而套接字多应用于网络进程间数据的传 递。

image-20240522062732723

// 套接字通信分两部分:

- 服务器端:被动接受连接,一般不会主动发起连接

- 客户端:主动向服务器发起连接

socket是一套通信的接口,Linux 和 Windows 都有,但是有一些细微的差别。

字节序

字节序(Endian)问题是计算机系统中关于数据表示的重要概念,主要涉及到数据的存储和通信方式。在不同的计算机体系结构中,字节序可能不同,这就要求在进行数据传输和通信时必须明确字节序,以确保数据正确地被解释和处理。

大端字节序(Big-Endian)

大端字节序,也称为“网络字节序”,因为它是多数网络协议采用的字节序,包括TCP/IP。在大端字节序中,一个多字节数值的最高字节(即最重要的字节)被存储在最低的内存地址,其次是次高字节,依此类推。例如,一个32位整数0x12345678在内存中的存储方式如下(地址由低到高):

  • 地址 x + 0: 0x12
  • 地址 x + 1: 0x34
  • 地址 x + 2: 0x56
  • 地址 x + 3: 0x78
小端字节序(Little-Endian)

记忆:小低低

小端字节序则恰好相反,一个多字节数值的最低字节(即最不重要的字节)被存储在最低的内存地址。它被很多现代桌面计算机体系(如x86架构)采用。例如,同样的32位整数0x12345678在小端字节序的计算机中的存储方式如下:

  • 地址 x + 0: 0x78
  • 地址 x + 1: 0x56
  • 地址 x + 2: 0x34
  • 地址 x + 3: 0x12
字节序的重要性

在网络通信中,字节序的不一致会导致数据被错误解释,进而造成通信错误。因此,为了数据能在不同的计算机系统间正确传输和接收,往往需要在发送和接收端之间进行字节序的转换。例如,在一个小端字节序的机器上发送数据到一个大端字节序的机器上时,发送者需要将数据从小端转换为大端字节序。

在进行网络编程,尤其是跨平台通信时,理解并正确处理字节序问题是非常关键的。Socket编程中经常用到的htonl()ntohl()等函数就是用于在主机字节序和网络字节序之间转换整数的字节序。

总结来说,字节序是一个基础而重要的概念,涉及到计算机体系、操作系统平台、网络通信等多个层面,正确处理字节序问题对保证数据交换的正确性和效率至关重要。

image-20240522070409611

image-20240522070418150

案例
/*  字节序:字节在内存中存储的顺序。小端字节序:数据的高位字节存储在内存的高位地址,低位字节存储在内存的低位地址大端字节序:数据的低位字节存储在内存的高位地址,高位字节存储在内存的低位地址
*/// 通过代码检测当前主机的字节序
#include <stdio.h>int main() {union {short value;    // 2字节char bytes[sizeof(short)];  // char[2]} test;test.value = 0x0102;if((test.bytes[0] == 1) && (test.bytes[1] == 2)) {printf("大端字节序\n");} else if((test.bytes[0] == 2) && (test.bytes[1] == 1)) {printf("小端字节序\n");} else {printf("未知\n");}return 0;
}
daic@daic:~/Linux/linuxwebserver/part04networkProgramming$ gcc byteorder.c 
daic@daic:~/Linux/linuxwebserver/part04networkProgramming$ ./a.out 
小端字节序

在进行网络编程时,处理字节序是保证跨平台数据通信正确性的一个重要方面。你已经很好地概括了如何利用大端字节序(即网络字节序)来实现数据的一致性和正确传输。下面我们详细解释这些概念和具体的函数使用:

字节序转换函数

网络字节序的重要性

**网络字节序是大端(Big-Endian)字节序,**这意味着数据的高位字节存储在低地址上。TCP/IP 协议族规定使用大端字节序是为了确保数据在不同计算架构的机器间传输时,每一台设备都能以相同的方式解释这些数据。这个标准化的处理方式避免了每个应用程序需要考虑目标机器字节序的复杂性。

h - host 主机,主机字节序
to - 转换成什么
n - network 网络字节序
s - short unsigned short
l - long unsigned int
#include <arpa/inet.h>
// 转换端口
uint16_t htons(uint16_t hostshort); // 主机字节序 - 网络字节序
uint16_t ntohs(uint16_t netshort); // 主机字节序 - 网络字节序
// 转IP
uint32_t htonl(uint32_t hostlong); // 主机字节序 - 网络字节序
uint32_t ntohl(uint32_t netlong); // 主机字节序 - 网络字节序
字节序转换函数

BSD Socket API 提供了一些函数来帮助程序员在主机字节序和网络字节序之间转换数据。主要的函数有:

  • htonl() (Host TO Network Long): 将一个长整型数从主机字节序转换到网络字节序。
  • htons() (Host TO Network Short): 将一个短整型数从主机字节序转换到网络字节序。
  • ntohl() (Network TO Host Long): 将一个长整型数从网络字节序转换到主机字节序。
  • ntohs() (Network TO Host Short): 将一个短整型数从网络字节序转换到主机字节序。
使用场景
  • 发送数据时: 在发送数据之前,数据需要从主机字节序转换为网络字节序,使用 htonl()htons()
  • 接收数据时: 在读取从网络接收的数据时,需要将数据从网络字节序转换回主机字节序,使用 ntohl()ntohs()
示例

假设您正在编写一个跨平台的网络应用,您需要发送一个整数和一个短整型数:

#include <stdio.h>
#include <netinet/in.h>int main() {int num = 0x12345678;short s_num = 0x1234;// 转换为网络字节序int net_num = htonl(num);short net_s_num = htons(s_num);// 发送 net_num 和 net_s_num ...// 接收数据// 假设接收到的数据存储在变量 net_num 和 net_s_num 中int host_num = ntohl(net_num);short host_s_num = ntohs(net_s_num);printf("Original: %x, Received: %x\n", num, host_num);printf("Original Short: %x, Received Short: %x\n", s_num, host_s_num);return 0;
}

这个例子展示了如何在发送和接收数据时处理字节序问题,确保数据在不同系统间正确地传输和解释。通过这种方式,无论数据是在小端还是大端机器上生成或接收的,都能正确处理,从而实现真正的跨平台兼容性。

案例
/*网络通信时,需要将主机字节序转换成网络字节序(大端),另外一段获取到数据以后根据情况将网络字节序转换成主机字节序。// 转换端口uint16_t htons(uint16_t hostshort);		// 主机字节序 - 网络字节序uint16_t ntohs(uint16_t netshort);		// 主机字节序 - 网络字节序// 转IPuint32_t htonl(uint32_t hostlong);		// 主机字节序 - 网络字节序uint32_t ntohl(uint32_t netlong);		// 主机字节序 - 网络字节序*/#include <stdio.h>
#include <arpa/inet.h>int main() {// htons 转换端口// typedef unsigned short int __uint16_t;uint16_t a = 0x0102;printf("a : %x\n", a);unsigned short b = htons(a);printf("b : %x\n", b);printf("=======================\n");// htonl  转换IPchar buf[4] = {192, 168, 1, 100};int num = *(int *)buf;int sum = htonl(num);unsigned char *p = (char *)&sum;printf("%d %d %d %d\n", *p, *(p+1), *(p+2), *(p+3));printf("=======================\n");// ntohlunsigned char buf1[4] = {1, 1, 168, 192};int num1 = *(int *)buf1;int sum1 = ntohl(num1);unsigned char *p1 = (unsigned char *)&sum1;printf("%d %d %d %d\n", *p1, *(p1+1), *(p1+2), *(p1+3));// ntohsreturn 0;
}
daic@daic:~/Linux/linuxwebserver/part04networkProgramming$ gcc bytetrans.c 
daic@daic:~/Linux/linuxwebserver/part04networkProgramming$ ./a.out 
a : 102
b : 201
=======================
100 1 168 192
=======================
192 168 1 1

socket地址

// socket地址其实是一个结构体,封装端口号和IP等信息。后面的socket相关的api中需要使用到这个
socket地址。
// 客户端 -> 服务器(IP, Port)
通用 socket 地址

socket 网络编程接口中表示 socket 地址的是结构体 sockaddr,其定义如下:

#include <bits/socket.h>
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
};
typedef unsigned short int sa_family_t;

sa_family 成员是地址族类型(sa_family_t)的变量。地址族类型通常与协议族类型对应。常见的协议族(protocol family,也称 domain)和对应的地址族入下所示:

image-20240522080913698

sa_data 成员用于存放 socket 地址值。但是,不同的协议族的地址值具有不同的含义和长度,如下所示:

image-20240522081113172

由上表可知,14 字节的 sa_data 根本无法容纳多数协议族的地址值。因此,Linux 定义了下面这个新的通用的 socket 地址结构体,这个结构体不仅提供了足够大的空间用于存放地址值,而且是内存对齐的。

#include <bits/socket.h>
struct sockaddr_storage
{
sa_family_t sa_family;
unsigned long int __ss_align;
char __ss_padding[ 128 - sizeof(__ss_align) ];
};
typedef unsigned short int sa_family_t;
专用 socket 地址

很多网络编程函数诞生早于 IPv4 协议,那时候都使用的是 struct sockaddr 结构体,为了向前兼容,现 在sockaddr 退化成了(void *)的作用,传递一个地址给函数,至于这个函数是 sockaddr_in 还是sockaddr_in6,由地址族确定,然后函数内部再强制类型转化为所需的地址类型。

image-20240522104145742

UNIX 本地域协议族使用如下专用的 socket 地址结构体:

#include <sys/un.h>
struct sockaddr_un
{
sa_family_t sin_family;
char sun_path[108];
};

TCP/IP 协议族有 sockaddr_in 和 sockaddr_in6 两个专用的 socket 地址结构体,它们分别用于 IPv4 和

IPv6:

#include <netinet/in.h>
struct sockaddr_in
{
sa_family_t sin_family; /* __SOCKADDR_COMMON(sin_) */
in_port_t sin_port; /* Port number. */
struct in_addr sin_addr; /* Internet address. */
/* Pad to size of `struct sockaddr'. */
unsigned char sin_zero[sizeof (struct sockaddr) - __SOCKADDR_COMMON_SIZE -
sizeof (in_port_t) - sizeof (struct in_addr)];
};struct in_addr
{
in_addr_t s_addr;
};struct sockaddr_in6
{
sa_family_t sin6_family;
in_port_t sin6_port; /* Transport layer port # */
uint32_t sin6_flowinfo; /* IPv6 flow information */
struct in6_addr sin6_addr; /* IPv6 address */
uint32_t sin6_scope_id; /* IPv6 scope-id */
};typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef uint16_t in_port_t;
typedef uint32_t in_addr_t;
#define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int))

所有专用 socket 地址(以及 sockaddr_storage)类型的变量在实际使用时都需要转化为通用 socket 地址类型 sockaddr(强制转化即可),因为所有 socket 编程接口使用的地址参数类型都是 sockaddr。

相关文章:

socket地址理解

socket介绍 套接字的基本概念 1. 套接字的定义&#xff1a; 套接字&#xff08;socket&#xff09;是计算机网络中用于通信的端点&#xff0c;它抽象了不同主机上应用进程之间双向通信的机制。 2. 套接字的作用&#xff1a; 套接字连接应用进程与网络协议栈&#xff0c;使…...

Gopeed的高级用法

Gopeed是一个开源全平台下载器&#xff0c;具体简介请参考&#xff1a; “狗屁下载器”&#xff1f;Gopeed - 开源全平台下载器 (免费轻量 / 比 Aria2 好用 / 远程下载) - 异次元软件世界 (iplaysoft.com) 这里主要介绍下自己摸索出来的 Gopeed 的高级做法。 有的网站添加的…...

OpenHarmony系统使用gdb调试init

前言 OpenAtom OpenHarmony&#xff08;简称“OpenHarmony”&#xff09;适配新的开发板时&#xff0c;启动流程init大概率会出现问题&#xff0c;其为内核直接拉起的第一个用户态进程&#xff0c;问题定位手段只能依赖代码走读和增加调试打印&#xff0c;初始化过程中系统崩溃…...

【SpringCloud】Spring Cloud基本介绍

目录 回顾架构分类单体架构分布式架构微服务架构什么是微服务优点缺点微服务的架构特征&#xff1a;微服务架构面临的挑战技术挑战微服架构的设计原则微服务概念提供者(Provider)消费者(Consumer)RPC和Restful集群分布式 总结 服务拆分和远程调用服务拆分原则服务拆分示例 思考…...

全域运营是本地生活服务的新模式吗?

最近&#xff0c;本地生活赛道又出现了一个新的说法&#xff0c;即全域运营是本地生活的下半场。事实上&#xff0c;这一论断并非空穴来风&#xff0c;而是有真凭实据。 作为多家互联网大厂重点布局的业务板块&#xff0c;本地生活的火爆程度早已有目共睹。根据多家互联网大厂…...

机器视觉-硬件

机器视觉-硬件 镜头焦距凸透镜焦点不止一个相机镜头由多个镜片组成对焦和变焦 镜头光圈光圈的位置光圈系数F 镜头的景深景深在光路中的几何意义 远心镜头远心镜头的种类远心镜头特性应用场景 镜头的分辨率镜头反差镜头的MTF曲线镜头的靶面尺寸镜头的几何相差相机镜头接口螺纹接…...

机器学习实验 --- 逻辑回归

第1关&#xff1a;逻辑回归核心思想 任务描述 本关任务&#xff1a;根据本节课所学知识完成本关所设置的编程题 #encodingutf8 import numpy as npdef sigmoid(t):完成sigmoid函数计算:param t: 负无穷到正无穷的实数:return: 转换后的概率值:可以考虑使用np.exp()函数#*****…...

浅谈C++函数

目录 一、函数的概念二、调用函数的两个前提三、函数传参的三种形式四、函数返回类型 一、函数的概念 函数是C程序的基本模块&#xff0c;通常一个C程序由一个或多个函数组成。函数可以完成用户指定的任务&#xff0c;一般分为库函数和用户自定义的函数。函数由函数头和函数体…...

6.小程序页面布局 - 账单明细

文章目录 1. 6.小程序页面布局 - 账单明细1.1. 竞品1.2. 布局分析1.3. 布局demo1.4. 页面实现-头部1.5. 账单明细1.5.1. 账单明细-竞品分析1.5.2. 账单明细-实现1.5.2.1. 账单明细-实现-mock数据1.5.2.2. 每日收支数据的聚合整理1.5.2.3. 页面scroll-view 1.6. TODO 1. 6.小程序…...

记录ES7.X更新数据的低级错误

背景&#xff1a;新项目复用之前同事遗留下的方法 问题&#xff1a;ES跨索引更新数据错误 排查&#xff1a;复用同事的方法有问题&#xff0c;他直接使用ES别名更新数据导致&#xff0c;只有一个索引时无问题&#xff0c;当多个索引使用同一别名时会出现异常 解决&#xff1…...

【简单介绍下链表基础知识】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…...

leetcode 2915.和为目标值的最长子序列的长度

思路&#xff1a;01背包 这个背包问题很经典了&#xff0c;但是这里涉及到一个问题&#xff0c;就是我们转化问题的时候发现&#xff0c;这个背包需要正好装满才行。这里我们把长度作为价值&#xff0c;也就是说每一个数的价值都是1。 我们需要把dp初始化为全部为负数&#x…...

欧拉函数、快速幂、扩展欧几里得算法、中国剩余定理和高斯消元

欧拉函数 给定 n 个正整数 ai&#xff0c;请你求出每个数的欧拉函数。 欧拉函数的定义1∼N 中与 N 互质的数的个数被称为欧拉函数&#xff0c;记为 ϕ(N)。 若在算数基本定理中&#xff0c;Np1a11p2a2…pmm&#xff0c;则&#xff1a;ϕ(N) Np1−1/p1p2−1/p2…pm−1/pm 输…...

自定义原生小程序顶部及获取胶囊信息

需求&#xff1a;我需要将某个文字或者按钮放置在小程序顶部位置 思路&#xff1a;根据获取到的顶部信息来定义我需要放的这个元素样式 * 这里我是定义某个指定页面 json&#xff1a;给指定页面的json中添加自定义设置 "navigationStyle": "custom" JS&am…...

yolov8推理由avi改为mp4

修改\ultralytics-main\ultralytics\engine\predictor.py&#xff0c;即可 # Ultralytics YOLO &#x1f680;, AGPL-3.0 license """ Run prediction on images, videos, directories, globs, YouTube, webcam, streams, etc.Usage - sources:$ yolo modepred…...

Vue3设置缓存:storage.ts

在vue文件使用&#xff1a; import { Local,Session } from //utils/storage; // Local if (!Local.get(字段名)) Local.set(字段名, 字段的值);// Session Session.getToken()storage.ts文件&#xff1a; import Cookies from js-cookie;/*** window.localStorage 浏览器永…...

超市信息管理系统(java+swing+jdbc+msyql)

...

如何用AI工具提升日常工作效率,帮我们提速增效减负

昨天&#xff0c;coze海外版支持了GPT4o&#xff0c; 立马体验了下&#xff0c;速度杠杠的。 https://www.coze.com 支持chatGP和gemini模型&#xff0c;需要科学上网。国内 https://www.coze.cn支持语雀、KIMI模型。 这里回到正题&#xff0c; 如何用AI工具提升日常工作效率…...

C++: 优先级队列的模拟实现和deque

目录 一、优先级队列 1.1优先级队列 priority_queue介绍 1.2优先级队列的使用 1.3priority_queue的模拟实现 二、deque 2.1deque介绍 2.2deque的优缺点 2.3为什么选择deque作为stack和queue的底层默认容器 一、优先级队列 1.1优先级队列 priority_queue介绍 1.11 优先级队…...

C++ socket epoll IO多路复用

IO多路复用通常用于处理单进程高并发&#xff0c;在Linux中&#xff0c;一切皆文件&#xff0c;一个socket连接会对应一个文件描述符&#xff0c;在监听多个文件描述符的状态应用中epoll相对于select和poll效率更高 epoll本质是系统在内核维护了一颗红黑树&#xff0c;监听的文…...

Linux 文件类型,目录与路径,文件与目录管理

文件类型 后面的字符表示文件类型标志 普通文件&#xff1a;-&#xff08;纯文本文件&#xff0c;二进制文件&#xff0c;数据格式文件&#xff09; 如文本文件、图片、程序文件等。 目录文件&#xff1a;d&#xff08;directory&#xff09; 用来存放其他文件或子目录。 设备…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

JVM虚拟机:内存结构、垃圾回收、性能优化

1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...