【网络编程】socket套接字

news2025/1/2 4:42:24

文章目录

  • 一、源IP和目的IP
  • 二、端口号port
  • 三、TCP/UDP协议
    • 3.1 网络字节流
  • 四、socket套接字
    • 4.1 socket常见接口
    • 4.2 sockaddr结构体
  • 五、总结

一、源IP和目的IP

如果我们的台式机或者笔记本没有IP地址就无法上网,而因为每台主机都有IP地址,所以注定了数据从一台主机传输到另一台主机一定有源IP和目的IP
所以在报头中就会包含源IP和目的IP。

而我们把数据从一台主机传递到另一台主机并不是目的,真正通信的其实是应用层上的软件。
在这里插入图片描述
而我们知道应用层可不止一个软件

那么我们现在就有了问题:
既然有了公网IP标识了一台唯一的主机,那么数据就可以由一台主机传递到另一台主机。但是有这么多的软件(进程),怎么保证软件A发送的被软件B接收呢?
换句话说:用什么来标识主机上的进程的唯一性呢?

二、端口号port

为了更好的表示一台主机上服务进程的唯一性,规定用端口号port标识服务进程、客户端进程的唯一性。

端口号:

1️⃣ 端口号是一个2字节16位的整数
2️⃣ 端口号用来标识一个进程,告诉操作系统要把数据交给哪一个进程
3️⃣ 一个端口号只能被一个进程占用(同一个主机)

由上面可以知道:
IP地址(标识唯一主机)+ 端口号(标识唯一进程)能够标识网络上的某一台主机的某一个进程(全网唯一进程)。

那么网络通信的本质就是进程间通信。
而我们之前说过进程间通信的本质是看到同一份资源现在这个资源就是网络
而通信的本质就是IO,因为我们上网的行为就两种情况:1.把数据发送出去 2.接收到数据。

这里再思考一个问题,我们标识一个进程有pid,那么为什么还需要端口号呢?

1️⃣ 首先pid是系统规定的,而port是网络规定的,这样就可以把系统和网络解耦
2️⃣ port标识服务器的唯一性不能做任何改变,要让客户端能找到服务器,就像110,120样不能被改变。而pid每次启动进程pid就会改变。
3️⃣ 不是所有的进程都需要提供网络服务或请求(不需要port),但每个进程都需要pid。

虽然一个端口号只能绑定一个进程,但是一个进程可以绑定多个端口号。

上面我们说了IP有源IP和目的IP,而这里的port也有源端口号和目的端口号。我们在发送数据的时候也要把自己的IP和端口号发送过去,因为数据还要被发送回来。所以发送数据的时候一定会多出一部分数据(以协议的形式呈现)。

有人可能会问那么第一次怎么知道给哪个IP和port发送,这个不用担心,因为服务器内部已经内置好了。

三、TCP/UDP协议

我们用的套接字接口一定会使用传输层协议,我们不会绕过传输层去调用下面的协议。
在这里插入图片描述

而传输层的协议分为TCP协议和UDP协议。

对于TCP协议有几个特点:

1️⃣ 传输层协议
2️⃣ 有连接(正式通信前要先建立连接)
3️⃣ 可靠传输(在内部帮我们做可靠传输工作)
4️⃣ 面向字节流

对于UDP协议有几个特点:

1️⃣ 传输层协议
2️⃣ 无连接
3️⃣ 不可靠传输
4️⃣ 面向数据报

可靠和不可靠传输:
不可靠传输:比如说发送数据时出现了丢包的情况、或者数据被重复传递了(传递了多份)、或者网络出现了问题等等造成的后果就叫做不可靠。

所以传输层就是用来解决可靠性的一个协议。

但是为什么UDP不可靠传输我们还要有这个协调呢?
这里要注意可不可靠是一个中性词。可靠是需要成本的,往往在维护和编码上都比较复杂;
而不可靠没有成本,使用起来也简单。
所以要分场景使用

3.1 网络字节流

我们知道多字节数据存储的时候会有大小端问题。
小端:低权值的数放入低地址。
大端:低权值的数放入高地址。

所以现在就出现了这么一种情况:可能一个大端机用大端的方式发送数据到一个小端机。
现在跨网络我们也不知道数据到底是大端和小端

所以就有了规定:
网络中的数据都是大端。

发送数据的主机如果是大端机就不用管,如果是小端机就把小端转成大端再发送。
接收数据同理。

那么如何定义网络数据流的地址呢?

发送主机把发送缓冲区的数据按内存的地址从低到高进行发送。
接收主机把接收缓冲区的数据按内存的地址从低到高进行接收。
也就是先发送的数据是低地址,后发送的数据是高地址。
TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节,不管这台主机是大端机还是小端机, 都会按照这个TCP/IP规定的网络字节序来发送/接收数据,如果当前发送主机是小端, 就需要先将数据转成大端; 否则就忽略, 直接发送即可。

而把数据转化成大端的工作不用我们自己来做,可以调用以下库函数做网络字节序和主机字节序的转换。

#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);

h表示host,n表示network,l表示32位长整数,s表示16位短整数。
主机是大端还是小端在函数内部会自己进行判断。
如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回。
如果主机是大端字节序,这些 函数不做转换,将参数原封不动地返回。

四、socket套接字

前面我们说过IP+端口号port标识了全网唯一的进程,我们IP+port就叫做套接字socket

4.1 socket常见接口

// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
int socket(int domain, int type, int protocol);
// 绑定端口号 (TCP/UDP, 服务器)
int bind(int socket, const struct sockaddr *address,
socklen_t address_len);
// 开始监听socket (TCP, 服务器)
int listen(int socket, int backlog);
// 接收请求 (TCP, 服务器)
int accept(int socket, struct sockaddr* address,
socklen_t* address_len);
// 建立连接 (TCP, 客户端)
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);

可以发现函数参数里面有个叫sockaddr的结构体类型,这是什么呢?

4.2 sockaddr结构体

其实套接字有不少种类型。
常见的有三种:

网络套接字
原始套接字
域间套接字

网络套接字主要运用于跨主机之间的通信,也能支持本地通信,而域间套接字只能在本地通信。而原始套接字可以跨过传输层(TCP/IP协议)访问底层的数据。

这些套接字应用场景完全不同,所以我们想用就得用三套不同的接口。
而为了方便,设计者只使用了一套接口,就可以通过不同的参数,解决所有的通信场景。

这里举两个具体的套接字类型:sockaddr_insockaddr_un

struct sockaddr_in {
    short int sin_family;           // 地址族,一般为AF_INET
    unsigned short int sin_port;    // 端口号,网络字节序
    struct in_addr sin_addr;        // IP地址
    unsigned char sin_zero[8];      // 用于填充,使sizeof(sockaddr_in)等于16
};

struct sockaddr_un {
    sa_family_t sun_family;       /* AF_UNIX */
    char sun_path[108];    /* 带有路径的文件名 */
};

在这里插入图片描述
可以看到sockaddr_insockaddr_un是两个不同的通信场景。区分它们就用16地址类型协议家族的标识符。 我们两个结构体都不用,用sockaddr

比方说我们想用网络通信,虽然参数是const struct sockaddr *addr,但实际传递进去的却是sockaddr_in结构体(注意要强制类型转换)。
在函数内部一视同仁,全部看成sockaddr类型,然后根据前两个字节判断到底是什么通信类型然后再强转回去。

我们可以把sockaddr看成基类,把sockaddr_insockaddr_un看成派生类,构成了多态体系。

五、总结

1️⃣ IP+port可以标志全网唯一进程。
2️⃣ 套接字是一种通信机制(通信的两方的一种约定),而套接字的表示形式:IP+port
3️⃣ TCP和UDP的主要区别就是可靠传输和不可靠传输,而可不可靠是中性词。
4️⃣ 网络字节序列简单粗暴的规定为大端。
5️⃣ sockaddr用统一的接口方式来解决网络通信的大部分问题。



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

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

相关文章

Prometheus Exporter开发

Prometheus Exporter开发 Exporter数据格式介绍 Exporter徒手开发 Exporter4种指标类型演示 Exporter自定义注册表 Exporter 基于Collector的模块开发 Exporter介绍 数据格式 通讯协议 HTTP协议服务端实现了gzip 数据格式 text/plain:文本协议 数据格式 prometheus…

MySQL性能监控全掌握,快来get关键指标及采集方法!

数据库中间件监控实战&#xff0c;MySQL中哪些指标比较关键以及如何采集这些指标了。帮助提早发现问题&#xff0c;提升数据库可用性。 1 整体思路 监控哪类指标&#xff1f; 如何采集数据&#xff1f; 第10讲监控方法论如何落地&#xff1f; 这些就可以在MySQL中应用起来。…

ChatGPT提示词工程(四):Inferring推断

目录 一、说明二、安装环境三、推断&#xff08;Inferring&#xff09;1. 推断情绪&#xff08;正面 / 负面&#xff09;2. 确定情绪的类型3. 识别愤怒4. 从客户评论中提取产品和公司名称5. 一次完成多项任务6. 推断主题7. 主题中是否包含给定的主题 一、说明 这是吴恩达 《Ch…

【栈】的实现

&#x1f58a;作者 : D. Star. &#x1f4d8;专栏 : 数据结构 &#x1f606;今日分享 : —>&#x1f4d6;区块链 &#xff1a; 小明向你借100块钱&#xff0c;说一周后还你&#xff0c;然后你拿个喇叭大喊一声&#xff1a;我是某某&#xff0c;小明向我借了100块&#xff0c…

Redis缓存(双写一致性问题)

Redis缓存&#xff08;双写一致性问题&#xff09; 1 什么是缓存?1.1 为什么要使用缓存1.2 如何使用缓存 2 添加缓存2.1 、缓存模型和思路2.2、代码如下 3 缓存更新策略3.1 、数据库缓存不一致解决方案&#xff1a;3.2 、数据库和缓存不一致采用什么方案 4 实现商铺和缓存与数…

【C生万物】 指针篇 (初级)

欢迎来到 Claffic 的博客 &#x1f49e;&#x1f49e;&#x1f49e; &#x1f449; 专栏&#xff1a;《C生万物 | 先来学C》&#x1f448; 前言&#xff1a; 面对C语言&#xff0c;很多童鞋都会高呼&#xff1a;指针难&#xff0c;指针难&#x…

【计算机专业漫谈】【计算机系统基础学习笔记】W2-1十进制数与二进制数,各进制数直接的转换

利用空档期时间学习一下计算机系统基础&#xff0c;以前对这些知识只停留在应试层面&#xff0c;今天终于能详细理解一下了。参考课程为南京大学袁春风老师的计算机系统基础MOOC&#xff0c;参考书籍也是袁老师的教材&#xff0c;这是我的听课自查资料整理后的笔记 W2-1十进制…

ChatGPT背后的技术:人类反馈强化学习RLHF

文章目录 前言Chat GPT是如何基于RLHF进行训练的RLHF 技术分解预训练语言模型训练奖励模型强化学习微调预训练模型 局限性参考 前言 随着OpenAI推出的Chat GPT火热出圈&#xff0c;Chat GPT背后的技术原理之一&#xff0c;人类反馈强化学习RLHF (Reinforcement Learning from …

Matplotlib 网格线

我们可以使用 pyplot 中的 grid() 方法来设置图表中的网格线。 grid() 方法语法格式如下&#xff1a; matplotlib.pyplot.grid(bNone, whichmajor, axisboth, ) 参数说明&#xff1a; b&#xff1a;可选&#xff0c;默认为 None&#xff0c;可以设置布尔值&#xff0c;true…

prometheus实战之二:使用常见指标

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 本篇概览 本文是《prometheus实战》系列的第二篇&#xff0c;在《prometheus实战之一&#xff1a;用ansible部署》一文咱们部署了prometheus服务&#xff0c…

防护服穿戴检测识别算法 yolov8

防护服穿戴检测识别系统基于yolov8网络模型图片数据识别训练&#xff0c;算法模型自动完成对现场人员是否按照要求穿戴行为实时分析。YOLOv8 算法的核心特性和改动可以归结为如下&#xff1a;提供了一个全新的 SOTA 模型&#xff0c;包括 P5 640 和 P6 1280 分辨率的目标检测网…

【开发工具】 我居然可以使用Office Tool Plus 安装上Office 真的是太不可思议了

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;web开发者、设计师、技术分享博主 &#x1f40b; 希望大家多多支持一下, 我们一起进步&#xff01;&#x1f604; &#x1f3c5; 如果文章对你有帮助的话&#xff0c;欢迎评论 &#x1f4ac;点赞&#x1…

【开发工具】 Office Tool Plus 居然也可以部署 Office 365 我的天 真的是太厉害了

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;web开发者、设计师、技术分享博主 &#x1f40b; 希望大家多多支持一下, 我们一起进步&#xff01;&#x1f604; &#x1f3c5; 如果文章对你有帮助的话&#xff0c;欢迎评论 &#x1f4ac;点赞&#x1…

人不成熟的五大特征-读后感

原文地址&#xff1a;人不成熟的五大特征-百度经验 1 立即要回报 1 所有简单的快的&#xff0c;别人也能做&#xff0c;这并不能使你超过别人。 2 做出别人做不出来的复杂成果&#xff0c;需要较长的时间和持续的学习&#xff0c;得到就得付出&#xff0c;时间&#xff0c;资源…

Windows10本地搭建网站教程 - 内网穿透发布公网访问

文章目录 概述1. 搭建一个静态Web站点2. 本地浏览测试站点是否正常3. 本地站点发布公网可访问3.1 安装cpolar内网穿透3.2 创建隧道映射公网地址3.3 获取公网URL地址 4. 公网远程访问内网web站点5. 配置固定二级子域名5.1 保留二级子域名5.2 配置二级子域名 6. 测试访问二级子域…

【Java笔试强训 30】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 一、选择题 二、编程题 &#x1f525;最难的问…

家乡特色推荐系统~java~mysql

摘 要 在Internet高速发展的今天&#xff0c;我们生活的各个领域都涉及到计算机的应用&#xff0c;其中包括家乡特色推荐的网络应用&#xff0c;在外国家乡特色推荐系统已经是很普遍的方式&#xff0c;不过国内的管理网站可能还处于起步阶段。家乡特色推荐系统采用java技术&…

常用半导体器件

&#xff08;1&#xff09;N 型半导体 在纯净的半导体硅或锗中掺入适量的五价磷元素&#xff0c;可形成带负电 的自由电子&#xff08;又称多数载流子&#xff09;参与导电。 &#xff08;2&#xff09;P 型半导体 在纯净的半导体硅或锗中掺入适量的三价硼元素&#xff0c;可形…

JavaEE初阶 - 文件/IO

一、认识文件 我们先来认识狭义上的文件(file)。针对硬盘这种持久化存储的I/O设备&#xff0c;当我们想要进行数据保存时&#xff0c;往往不是保存成一个整体&#xff0c;而是独立成一个个的单位进行保存&#xff0c;这个独立的单位就被抽象成文件的概念&#xff0c;就类似办公…

Docker持久化固定容器IP

基于Docker引擎创建Docker容器&#xff0c;在默认条件下创建容器是bridge桥接模式&#xff0c;启动容器IP地址是DHCP随机分配并且递增的&#xff0c;而且容器之间可以互相通信&#xff0c;网段也是固定的。 当Docker容器一旦关闭再次启动&#xff0c;就会导致容器的IP地址再次重…