【Linux网络与网络编程】02.初识Socket编程

1. 数据传输的目的

前一篇文章中我们讲解了网络传输的流程,那么网络传输的目的是什么呢?难道我们只是将数据从一台主机传输到另一台主机吗?

当然不是的!因为数据是给人用的。比如:聊天是人在聊天,下载是人在下载,浏览网页是人在浏览? 但是人是怎么看到聊天信息的呢?怎么执行下载任务呢?怎么浏览网页信息呢?是通过启动的 qq,迅雷,浏览器。 而启动的 qq,迅雷,浏览器都是进程。换句话说,进程是人在系统中的代表,只要把数据给进程就相当于人就拿到了数据。 所以数据传输到主机是手段,将数据传达给主机的进程才是目的。 但是系统中,同时会存在非常多的进程,当数据到达目标主机之后,怎么转发给目标进程?这就要在网络的背景下,在系统中标识主机的唯一性。

2. 认识端口号

端口号(port)是传输层协议的内容。

端口号是一个 2 字节 16 位的整数,用来标识一个进程,告诉操作系统,当前的这个数据要交给哪一个进程来处理。IP 地址 + 端口号能够标识网络上的某一台主机的某一个进程。因此一个端口号只能被一个进程占用,但是一个进程可以绑定多个端口号。

 我们有这样的问题:那为什么不使用PID来标识进程的唯一性呢?而是使用端口号来标识?

这是为了避免网络与系统的耦合度过高,参考LWP和线程的关系。 

端口号范围划分:

0 - 1023: 知名端口号,HTTP、 FTP、SSH 等这些广为使用的应用层协议,他们的端口号都是固定的。

1024 - 65535: 操作系统动态分配的端口号,客户端程序的端口号就是由操作系统从这个范围分配的。

3. 认识Socket编程

现在我们知道,IP 地址用来标识互联网中唯一的一台主机,port 用来标识该主机上唯一的一个网络进程,那么IP+Port 就能表示互联网中唯一的一个进程。在通信的时候,本质是两个互联网进程代表人来进行通信,{srcIp, srcPort,dstIp,dstPort} 这样的 4 元组就能标识互联网中唯二的两个进程。所以网络通信的本质就是进程间通信我们把 ip+port 叫做套接字 socket。

4. 传输层的典型代表

如果我们了解了系统,也了解了网络协议栈,我们就会清楚,传输层是属于内核的,那么我们要通过网络协议栈进行通信,必定调用的是传输层提供的系统调用来进行的网络通信。

下图是对TCP协议和UDP协议的简略介绍: 

5. 网络字节序

我们已经知道,内存中的多字节数据相对于内存地址有大端和小端之分,磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分,网络数据流同样有大端小端之分。那么如何定义网络数据流的地址呢?

发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出,接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存。因此,网络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是高地址

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

为使网络程序具有可移植性,使同样的 C 代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换。

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

 6. Socket编程接口

// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
int socket(int domain, int type, int protocol);
//参数:
//    domain:需要指定域/协议簇
//    type:类型
//    protocol:协议,一般置0即可
//返回值:
//    成功返回socket文件描述符,失败则返回-1// 绑定端口号 (TCP/UDP, 服务器)
int bind(int socket, const struct sockaddr *address,socklen_t address_len);
//参数:
//    socket:需要绑定的socket文件描述符
//    address:绑定的结构
//    address_len:绑定结构的大小

Socket API是一层抽象的网络编程接口,适用于各种底层网络协议,如 IPv4、IPv6。以及后面要讲的 UNIX Domain Socket。然而,各种网络协议的地址格式并不相同。

 

IPv4 和 IPv6 的地址格式定义在 netinet/in.h 中,IPv4 地址用 sockaddr_in 结构体表示,包括 16 位地址类型,16 位端口号和32 位 IP 地址。IPv4、IPv6 地址类型分别定义为常数 AF_INET、AF_INET6。这样,只要取得某种 sockaddr 结构体的首地址,不需要知道具体是哪种类型的 sockaddr 结构体,就可以根据地址类型字段确定结构体中的内容。socket API 可以都用 struct sockaddr * 类型表示,在使用的时候需要强制转化成 sockaddr_in。这样的好处是程序的通用性可以接收 IPv4、IPv6以及 UNIX Domain Socket 各种类型的 sockaddr 结构体指针做为参数。

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

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

相关文章

电脑连不上手机热点会出现的小bug

一、问题展示 注意: 不要打开 隐藏热点 否则他就会在电脑上 找不到自己的热点 二、解决办法 把隐藏热点打开即可

CUDA专题3:为什么GPU能改变计算?深度剖析架构、CUDA®与可扩展编程

1. 简介 1.1. 使用 GPU 的优势 图形处理器(GPU)在相近的成本和功耗范围内,能够提供比中央处理器(CPU)更高的指令吞吐量和内存带宽。许多应用程序利用这些优势,在 GPU 上的运行速度远超 CPU(参见《GPU 应用》)。其他计算设备(如 FPGA)虽然能效也很高,但其编程灵活性…

Linux输入系统应用编程

什么是输入系统 Linux 输入系统是处理用户输入设备(如键盘、鼠标、触摸屏、游戏手柄等)的软件架构。在应用编程层面&#xff0c;它提供了与这些输入设备交互的接口。 主要组成部分 输入设备驱动层&#xff1a;直接与硬件交互的驱动程序 输入核心层&#xff1a;内核中的输入子…

StarRocks BE宕机排查

StarRocks BE宕机排查 排查是否OOM dmesg -T|grep -i oom #排查是否oom原因&#xff1a; 2.X版本OOM原因 BE 的配置文件 (be.conf) 中 mem_limit 配置不合理&#xff0c;需要配置mem_limit(机器总内存-其他服务占用内存-1~2g(系统预留)) 比如机器内存40G&#xff0c;上面有…

逻辑回归(Logistic Regression)模型的概率预测函数

以二分类问题为例&#xff0c;常见的损失函数有 负对数似然损失(neg log-likelihood loss)&#xff0c;交叉熵损失(cross entropy loss)&#xff0c;deviance loss指数损失(exponential loss)。 前三者虽然名字不同&#xff0c;但却具有相同的表达形式。此外&#xff0c;neg …

函数式组件中的渲染函数 JSX

在 Vue.js 和 React 等现代前端框架中&#xff0c;函数式组件已成为一种非常流行的设计模式。函数式组件是一种没有内部状态和生命周期方法的组件&#xff0c;其主要功能是接受 props 并渲染 UI。随着这些框架的演进&#xff0c;渲染函数和 JSX&#xff08;JavaScript XML&…

Android 动态设置默认Launcher(默认应用 电话-短信-浏览器-主屏幕应用))

Android 动态设置默认Launcher(默认应用 电话-短信-浏览器-主屏幕应用&#xff09;) 文章目录 场景需求参考资料思路期待效果 实现方案源码流程分析和思路实现DefaultAppActivityHandheldDefaultAppFragmentHandheldDefaultAppPreferenceFragmentDefaultAppChildFragmentDefaul…

Qt下载模板到本地文件内容丢失问题

上源码 关键点已标注在源码中 A, B… // 保存的文件路径后缀QString dateTime Myapp::getCurrentTimeDescYMDHms().replace(" ", "").replace("-", "").replace(":", "");// 临时文件名称QString newFileName Q…

【数学建模】动态规划算法(Dynamic Programming,简称DP)详解与应用

动态规划算法详解与应用 文章目录 动态规划算法详解与应用引言动态规划的基本概念动态规划的设计步骤经典动态规划问题1. 斐波那契数列2. 背包问题3. 最长公共子序列(LCS) 动态规划的优化技巧动态规划的应用领域总结 引言 动态规划(Dynamic Programming&#xff0c;简称DP)是一…

蓝桥杯备考------>双指针(滑动窗口)

来看哈我们这道例题 我们第一种想法应该就是暴力求解&#xff0c;枚举每个子数组 当我们枚举第一个数的时候&#xff0c;我们要从第一个数开始挨个枚举每个结尾 如图&#xff0c;以第一个数开头的最长不重复数我们就枚举完了 然后我们让两个指针全部到第二个数 再枚举第二个…

python实现股票数据可视化

最近在做一个涉及到股票数据清洗及预测的项目&#xff0c;项目中需要用到可视化股票数据这一功能&#xff0c;这里我与大家分享一下股票数据可视化的一些基本方法。 股票数据获取 目前&#xff0c;我已知的使用python来获取股票数据方式有以下三种: 爬虫获取&#xff0c;实现…

【15】Selenium 爬取实战

一、selenium适用场景 二、爬取目标 三、爬取列表页 &#xff08;1&#xff09;初始化 &#xff08;2&#xff09;加载列表页 &#xff08;3&#xff09;解析列表页 &#xff08;4&#xff09;main 四、爬取详情页 &#xff08;1&#xff09;加载详情页 &#xff08;2…

如何封装一个上传文件组件

#今天用el-upload感到很多不方便&#xff0c;遂决定自己封装一个。注&#xff1a;本文不提供表面的按钮样式和文件上传成功后的样式&#xff0c;需要自己创建。本文仅介绍逻辑函数# 1&#xff0c;准备几个表面用来指引上传的元素 2&#xff0c;创造统一的隐藏文件上传输入框&…

【计网】数据包

期末复习自用的&#xff0c;处理得比较草率&#xff0c;复习的同学或者想看基础的同学可以看看&#xff0c;大佬的话可以不用浪费时间在我的水文上了 1.数据包的定义&#xff1a; 数据包是网络通信中的基本单元&#xff0c;它包含了通过网络传输的所有必要信息。数据包的结构…

HTTP抓包Websocket抓包(Fiddler)

近期时常要和各个厂商的java云平台打交道&#xff1a;登录、上传、下载等&#xff0c;程序的日志虽必不可少&#xff0c;但前期调试阶段&#xff0c;免不了遇到问题&#xff0c;这时有一个称手的抓包工具就显得尤为重要了。 Fiddler Everywhere是一款跨平台的网络调试工具&…

Git和GitCode使用(从Git安装到上传项目一条龙)

第一步 菜鸟教程-Git教程 点击上方链接&#xff0c;完成Git的安装&#xff0c;并了解Git 工作流程&#xff0c;知道Git 工作区、暂存区和版本库的区别 第二步 GitCode官方帮助文档-SSH 公钥管理 点击上方链接&#xff0c;完成SSH公钥设置 第三步&#xff08;GitCode的官方引…

基于 WebAssembly 的 Game of Life 交互实现

一、前言 在前期的实现中&#xff0c;我们使用 Rust 编写核心逻辑&#xff0c;并通过 WebAssembly 将其引入到 Web 环境中&#xff0c;再利用 JavaScript 进行渲染。接下来&#xff0c;我们将在这一基础上增加用户交互功能&#xff0c;使模拟过程不仅能够自动演化&#xff0c;…

【keil】单步调试

一、步骤 1、打开stc-isp软件 2.打开keil仿真设置&#xff0c;选择对应的单片机型号 3.点击将所选目标单片机设置为仿真芯片&#xff0c;点击下载&#xff0c;按一下单片机打下载按钮 4.此时已经将仿真程序下载到单片机 5.此时点击options,找到debug选择STC Montor 51 Driv…

c++弱指针实现原理

在 C 中&#xff0c;弱指针&#xff08;std::weak_ptr&#xff09;是一种特殊的智能指针&#xff0c;其核心目标是‌解决 std::shared_ptr 的循环引用问题‌&#xff0c;同时不增加对象的引用计数。它的实现原理基于与 std::shared_ptr 共享的 ‌控制块&#xff08;Control Blo…

【ManiSkill】环境success条件和reward函数学习笔记

1. “PickCube-v1” info["success"]&#xff1a;用于指示任务是否成功完成 布尔型张量&#xff0c;在环境的evaluate()方法中计算并返回&#xff1a; "success": is_obj_placed & is_robot_static这确保了机器人不仅能将物体准确放置在目标位置&am…