【网络编程】socket套接字|sockaddr|sockaddr_in|通信过程

news2024/9/20 20:56:28

目录

​编辑

源IP地址和目的IP地址

Socket

网络字节序

socket编程接口

 sockaddr结构

sockaddr

sockaddr_in(IPv4)

 sockaddr_in(IPv6)

完整的套接字(socket)通信过程

创建socket套接字 

bind绑定套接字

 listen建立监听

 accept接受连接

connect建立连接 

sendto发送数据

接收数据

close关闭套接字


源IP地址和目的IP地址

在网络中,IP地址标识了唯一一台主机,这表明只要我们知道了某个主机的IP地址,就可以向该主机发送数据;但是目标主机收到了数据后,不知道数据要具体发送给哪个进程。

为了解决这个问题,网络通信中引入了端口号的概念。端口号是一个16位的整数,它允许我们在同一台主机上区分不同的网络服务或应用程序。拿着IP地址和端口号就可以将数据发送给目标主机的具体某个进程;

网络通信本质还是进程间通信,只不过这两个进程可能不在一台主机上。

Socket

在进行网络通信时,客户端就相当于插头,服务端就相当于一个插座,但服务端上可能会有多个不同的服务进程(多个插孔),因此当我们在访问服务时需要指明服务进程的端口号(对应规格的插孔),才能享受对应服务进程的服务;

在网络中,两个进程想要互相通信,要有四个熟悉:源主机的IP+Port(端口号),目标主机的IP+Port(端口号)IP+Port的组合就称为套接字Socket

网络字节序

数据在内存中存储有大小端之分,而磁盘文件中的多字节数据相对于文件中的偏移量地址也有大小端之分,网络数据流也有大小端之分;

这样就引出了一个问题:如果通信的进程是在一台主机上还没啥问题(存储读取方式相同),如果是跨主机通信,一方是大端存储,一方是小端存储,假设不做处理发送给对方,不同的存储和读取方式肯定会引起乱码问题

为了避免问题:需要将数据发送前转成网络字节序。而TCP/IP协议规定网络数据流应采用大端字节序(低地址高地址),所以如果当前发送主机方是小端,需要先将数据转成大端

  • htonl函数的作用是将 32 位的长整数从主机字节序转换为网络字节序,例如将 IP 地址转换后准备发送
  • htons函数的作用是将 16 位的短整数从主机字节序转换为网络字节序,例如将 端口号 地址转换后准备发送
  • ntohl函数的作用是将 32 位的长整数从网络字节序转换为主机字节序,例如将 接收到的 IP 地址转换后使用
  • ntohs函数的作用是将 16 位的短整数从网络字节序转换为主机字节序,例如将接收到的端口号转换后使用

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结构

sockaddr结构体之外还有两个结构体:sockaddr_in和sockaddr_un

  • sockaddr_in结构体是用于跨网络通信,其中sockaddr_in的in是inet,"inet" 是Internet Protocol(IP)的简写
  • sockaddr_un结构体是用于本地通信,其中sockaddr_un的un是unix

sockaddr 是一个通用的套接字地址结构,在不同的网络协议中被用来表示地址信息。这个结构通常用作更具体结构(如 sockaddr_in 用于IPv4, sockaddr_in6 用于IPv6)的基础。

 

sockaddr
struct sockaddr {
    sa_family_t sa_family;  // 地址族(Address family)
    char sa_data[14];       // 套接字地址数据(Socket address data)
};
sockaddr_in(IPv4)
struct sockaddr_in {
    sa_family_t sin_family;   // 地址族(AF_INET)
    in_port_t sin_port;       // 端口号(Port number),网络字节序
    struct in_addr sin_addr;  // IPv4地址
    char sin_zero[8];         // 填充字节,使结构体大小与 `sockaddr` 一致
};
 sockaddr_in(IPv6)
struct sockaddr_in6 {
    sa_family_t      sin6_family;  // 必须设置为 AF_INET6
    in_port_t        sin6_port;    // 端口号,网络字节序
    uint32_t         sin6_flowinfo; // 流量控制信息
    struct in6_addr  sin6_addr;    // IPv6 地址
    uint32_t         sin6_scope_id; // 范围ID
};

struct in6_addr {
    unsigned char   s6_addr[16];  // 128位IPv6地址
};

完整的套接字(socket)通信过程

  1. 创建套接字:使用socket()函数来创建一个新的套接字。此函数需要三个参数:地址族(如AF_INET对应IPv4)、套接字类型(如SOCK_STREAM 表示TCP流套接字)和协议(一般设置为0,让系统选择默认协议)。
  2. 绑定地址:服务器端需要将套接字绑定到一个本地地址上,以便客户端可以连接到它。使用 bind() 函数来完成这个操作。首先定义一个 sockaddr_in 结构体,并填充相应的信息(IP地址和端口号),然后调用 bind()。
  3. 监听连接:对于服务器来说,下一步是监听传入的连接请求。使用listen() 函数,指定要监听的套接字和队列的最大长度。
  4. 接受连接:当有客户端尝试连接时,服务器通过 accept() 函数接受连接。这会创建一个新的套接字用于与客户端通信。
  5. 发送/接收数据:一旦连接建立,双方就可以通过 send() 和 recv() 函数或它们的变体(如 write() 和 read())交换数据了。
  6. 关闭连接:通信完成后,应该关闭套接字,释放资源。使用 close() 函数来关闭套接字。

创建socket套接字 

#include <sys/types.h>
#include <sys/socket.h>

// 创建一个IPv4的TCP套接字
int socket(int domain, int type, int protocol);
  • domain:地址簇,常见的有AF_INET(IPv4),和AF_INET6(IPv6)
  • type:套接字类型,常见的有SOCK_STREAM(TCP),SOCK_DGRAM(UDP)
  • protocol:协议,通常为0(自动选择),也可以指定协议,如IPPROTO_TCP 或 IPPROTO_UDP。
  • 成功时返回一个套接字描述符,失败时返回-1,并设置error

 调用socket这个函数得到一个文件描述符,在操作系统的内核中,它对应于一个数据结构,存储了该套接字的各种状态信息和资源,例如IP地址、端口号、通信协议、缓冲区等。

bind绑定套接字

bind函数将套接字绑定到一个IP地址和端口号。

#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • sockfd:套接字描述符
  • addr:指向ockaddr结构体的指针,该结构体对象包含了要绑定的地址信息,对于IPv4,使用sockaddr_in 结构体;对于IPv6,使用 sockaddr_in6 结构体。
  • addr_len:addr指向结构体对象的大小,通常使用sizeof获取
  • 成功时返回0,失败时返回-1并设置errno

 listen建立监听

#include <sys/types.h>
#include <sys/socket.h>
int listen(int sockfd, int backlog);
  • sockfd:套接字描述符
  • backlog挂起连接的最大队列长度,即最多有多少个连接可以等待被接受
  • 成功时返回0,失败时返回-1并设置errno

 accept接受连接

#include <sys/types.h>
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  • sockfd监听套接字描述符,即listen获取的套接字描述符
  • addr:指向sockaddr结构体对象的指针,用于存储客户端地址信息
  • addrlen:指向addr指向结构体对象的大小
  • 成功时返回新的套接字描述符,失败时返回-1并设置errno

connect建立连接 

#include <sys/types.h>
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • sockfd:套接字描述符
  • addr:指向sockaddr结构体对象的指针,用于存储服务器地址信息
  • addrlen:sockaddr 结构体的大小。
  • 成功时返回0,失败时返回-1并设置errno

sendto发送数据

#include <sys/types.h>
#include <sys/socket.h>
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
 const struct sockaddr *dest_addr, socklen_t addrlen);
  • sockfd: 套接字描述符,通过 socket 函数创建
  • buf: 指向要发送的数据缓冲区
  • len: 要发送的数据的长度
  • flags: 发送标志,通常为0
  • dest_add: 指向 sockaddr 结构体的指针,包含目标地址和端口号
  • addrlen: sockaddr 结构体的大小
  • 成功时返回发送的字节数,失败时返回-1,并设置 errno 以指示错误

接收数据

#include <sys/types.h>
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, 
struct sockaddr *src_addr, socklen_t *addrlen);
  • sockfd: 套接字描述符,通过 socket 函数创建。
  • buf: 指向存储接收数据的缓冲区。
  • len: 缓冲区的长度,即可以接收的最大字节数。
  • flags: 接收标志,通常为0。
  • src_addr: 指向 sockaddr 结构体的指针,用于存储发送方的地址信息。
  • addrlen: 指向 socklen_t 变量的指针,表示 sockaddr 结构体的大小。调用函数时需要设置为 sockaddr 结构体的大小,函数返回时设置为实际地址的长度。

close关闭套接字

#include<unistd.h>
int close(int fd);

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

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

相关文章

错题集锦之C语言

直接寻址和立即寻址 算法的又穷性是指算法程序的运行时间是有限的 未经赋值的全局变量值不确定 集成测试是为了发现概要设计的错误 自然连接要求两个关系中进行比较的是相同的属性&#xff0c;并且进行等值连接&#xff0c;在结果中还要把重复的属性列去掉 赋值运算符 赋值…

CAFE: Catastrophic Data Leakage in Vertical Federated Learning(纵向联邦学习)

NeurIPS 2021 发表单位&#xff1a;美国伦斯勒理工学院、IBM研究院、国立阳明交通大学 GitHub&#xff1a;https://github.com/DeRafael/CAFE 摘要&#xff1a; 梯度共享机制&#xff08;批处理&#xff09;会泄露私有数据—>提出数据泄露攻击CAFE—>提出缓解CAFE对策 在…

云计算课程作业1

作业1 Xmanager连接 rhel连接 作业2 首先确认你的虚拟机设置的是NAT 1-3 然后打开这篇blog&#xff0c;并完成第一步和第二步 因为我们是NAT&#xff0c;所以不需要连接网桥&#xff0c;即跳过第三步&#xff0c;但是这里ping一下测试网络连接 2- 如果到这里你发现提示yum…

2024 Oracle CloudWorld的信息量实在太大了

2024年9月9日&#xff0c;为期4天的2024甲骨文全球云大会在美国拉斯维加斯盛大开幕。今年的主题聚焦于&#xff0c;通过将最新的AI技术融入其产品和服务&#xff0c;以构建和使用应用、云技术、数据库、开发人员工具和人工智能服务&#xff0c;帮助各个行业解决复杂的业务挑战。…

【数据结构与算法 | 灵神题单 | 二叉搜索树篇】力扣99, 1305, 230, 897

1. 力扣99&#xff1a;恢复二叉搜索树 1.1 题目&#xff1a; 给你二叉搜索树的根节点 root &#xff0c;该树中的 恰好 两个节点的值被错误地交换。请在不改变其结构的情况下&#xff0c;恢复这棵树 。 示例 1&#xff1a; 输入&#xff1a;root [1,3,null,null,2] 输出&…

天润融通创新功能,将无效会话转化为企业新商机

“您好&#xff0c;请问有什么可以帮您&#xff1f;” “......” 一个新的咨询会话进来&#xff0c;但客户却并不说话&#xff0c;这种情况客服人员肯定不会陌生&#xff0c;它一般被称为“无效会话”。 如今“无效会话”越来越多&#xff0c;已经成为困扰无数企业的难题。…

最清晰 | 自学前端之js

怎么在vscode中运行网页代码 1、在vscode中安装插件“ open PHP/HTML/JS ” 2、在代码区域,右键点击” open PHP/HTML/JS in browser " 一、js概念 1、是什么: (1)运行在客户端(浏览器) (2)一种编程语言(脚本语言) (3)实现人机交互 2、做什么: (1)网页…

react 创建react项目

使用react的环境&#xff1a; 下载nodejs,然后全局安装create-react-app 1、检查是否安装&#xff1a; create-react-app --version 2、全局安装create-react-app npm install create-react-app -g 3、创建react项目 注意&#xff1a;项目第一次安装&#xff0c;可能会直…

ADB 安装教程:如何在 Windows、macOS 和 Linux 上安装 Android Debug Bridge

目录 一、ADB 介绍 二、Windows 系统安装 ADB 1. 下载 ADB 2. 解压文件 3. 验证 ADB 安装 4. 配置环境变量 5. 验证全局 ADB 使用 三、macOS 系统安装 ADB 1. 下载 ADB 2. 解压文件 3. 配置环境变量 4. 验证 ADB 安装 四、Linux 系统安装 ADB 1. 使用包管理器安装…

Pandas和matplotlib实现同期天气温度对比

目录 1、下载近两年的天气Excel数据 2、pandas加载Excel 3、将时间作为索引 4、按日计算最值、均值 5、选取近两年同期温度数据 6、同期温度曲线对比,共享y轴 1、下载近两年的天气Excel数据 一个免费的天气数据下载网址:METAR北京(机场)历史天气 (rp5.ru) 选择”北京天…

20240921 每日AI必读资讯

AI、悟空、西湖文创集盒……2024云栖大会有超多硬核科技&#xff01; - 9月19日&#xff0c;一年一度的阿里云栖大会拉开帷幕 - 阿里现任掌舵者吴泳铭、CTO周靖人携手大模型领域当红炸子鸡月之暗面CEO杨植麟、小鹏汽车CEO何小鹏等一众明星企业创始人给业界带来了一场久违的国…

《 LiteFlow 规则引擎(1) - 入门篇》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

【RabbitMQ】应用

RabbitMQ 应用 1. 七种⼯作模式介绍1.1 Simple(简单模式)1.2 Work Queue(⼯作队列)1.3 Publish/Subscribe(发布/订阅)概念介绍Publish/Subscribe模式 1.4 Routing(路由模式)1.5 Topics(通配符模式)1.6 RPC(RPC通信)1.7 Publisher Confirms(发布确认) 2. ⼯作模式的使⽤案例2.1 …

Java【代码 18】处理Word文档里的Excel表格数据(源码分享)

处理Word文档里的Excel表格数据 1.原始数据2.处理程序2.1 识别替换表格表头2.2 处理多余的换行符2.3 处理后的结果 3.总结 1.原始数据 Word 文档里的 Excel 表格数据&#xff0c;以下仅为示例数据&#xff1a; 读取后的字符串数据为&#xff1a; "姓名\r\n身份证号\r\n手…

【计网】从零开始使用TCP进行socket编程 ---服务端业务模拟Xshell

最糟糕的情况&#xff0c; 不是你出了错&#xff0c; 而是你没有面对出错的勇气。 从零开始使用TCP进行socket编程 1 通信过程的多版本实现1.1 多进程版本1.2 多线程版本 2 服务端业务模拟Xshell2.1 整体框架设计2.2 Command类设计 1 通信过程的多版本实现 在前一篇的文章…

鸿蒙手势交互(三:组合手势)

三、组合手势 由多种单一手势组合而成&#xff0c;通过在GestureGroup中使用不同的GestureMode来声明该组合手势的类型&#xff0c;支持顺序识别、并行识别和互斥识别三种类型。 GestureGroup(mode:GestureMode, gesture:GestureType[]) //- mode&#xff1a;为GestureMode枚…

美元降息,对普通人有哪些影响?

美元降息&#xff0c;对普通人有哪些影响&#xff1f; 美元降息了。很多朋友都说我又不炒股&#xff0c;我手里又没有美金&#xff0c;美元跟我有啥关系啊&#xff1f;那我们就来聊聊美元降息&#xff0c;对我们国内经济到底有哪些影响&#xff1f;你再来看看跟你有没有关系&a…

计算机毕业设计 美发管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

MySQL高阶1890-2020年最后一次登录

目录 题目 准备数据 分析数据 题目 编写解决方案以获取在 2020 年登录过的所有用户的本年度 最后一次 登录时间。结果集 不 包含 2020 年没有登录过的用户。 返回的结果集可以按 任意顺序 排列。 准备数据 Create table If Not Exists Logins (user_id int, time_stamp …

数据库-约束与多表查询

1.约束 例子&#xff1a; 外键约束 例子&#xff1a; 2.多表查询 多表关系 概述 内连接 外连接 自连接 联合查询 子查询 介绍 标量子查询 仅有一个值 列子查询 行子查询 表子查询 练习