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

目录

​编辑

源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_INET6in_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.xdnf.cn/news/1540673.html

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

相关文章

OpenCV系列教程二:基本图像增强(数值运算)、滤波器(去噪、边缘检测)

文章目录 一、基本图像增强&#xff08;数值运算&#xff09;1.1 加法 &#xff08;cv2.add&#xff09;1.1.1 图像与标量相加&#xff08;调节亮度&#xff09;1.1.2 图像与图像相加&#xff08;两个图像shape要相同&#xff09;1.1.3 图像的加权加法&#xff08;渐变切换&…

身份证识别接口的应用场景和作用

引言 在信息化与数字化高速发展的今天&#xff0c;身份证作为个人身份的重要证明文件&#xff0c;在各行各业的应用越来越广泛。传统的身份证信息录入和审核过程通常需要人工操作&#xff0c;不仅效率低下&#xff0c;而且容易出现错误。为了解决这些问题&#xff0c;身份证识别…

C++入门基础知识八

1.介绍new与delete 1.malloc和free是函数&#xff0c;new和delete是操作符 2.malloc申请的空间不会初始化&#xff0c;new可以初始化 3.malloc申请空间失败时&#xff0c;返回的是NULL&#xff0c;因此必须判空&#xff0c;new不需要&#xff0c;但是new需要捕获异常 4.申请…

Kyutai 开源对话模型 Moshi;李飞飞空间智能公司已筹集超过 2.3 亿美元丨 RTE 开发者日报

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。 我们的社区编辑团队会整理分享 RTE&#xff08;Real-Time Engagement&#xff09; 领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、…

OpenAI GPT o1技术报告阅读(3)-英文阅读及理解

✨继续阅读报告&#xff1a;使用大模型来学习推理(Reason) 原文链接&#xff1a;https://openai.com/index/learning-to-reason-with-llms/ 这次我们继续看一个英文阅读理解的案例。 原问题&#xff1a; The following passage is the draft of an excerpt from a contempora…

Web开发:ABP框架3——入门级别的接口增删改查实现原理

一、上节回顾 运用了ABP框架&#xff0c;使用了EFcore进行增删改查 二、程序的入口 代码解说&#xff1a; public class Program // 定义程序主类 {public async static Task<int> Main(string[] args) // 主方法&#xff0c;返回状态码{// 配置Serilog日志Log.Logger…

手机换新,怎么把旧iPhone手机数据传输至新iPhone16手机

随着苹果公司推出了备受期待的iPhone 16。这款最新型号的iPhone不仅在设计上进行了革新&#xff0c;更在性能和功能上带来了前所未有的突破。对于那些准备从旧iPhone升级到iPhone 16的用户来说&#xff0c;最关心的问题之一就是如何把旧手机的资料转移到新手机中了。如果你不知…

Java从入门到精通学习框架(二)

在这个阶段&#xff0c;重点是掌握 Java 的高级特性&#xff0c;理解和应用常见的数据结构、Java 的并发编程模型&#xff0c;以及深入理解 Java 的内存管理机制等。通过这一阶段的学习&#xff0c;你将能够编写更加复杂和高效的程序&#xff0c;并为后续的框架学习打下坚实基础…

深度学习-图像处理篇1.1-1.2神经网络

1.1卷积神经网络基础 卷积层 对彩色RGB图像进行卷积 1.卷积核的通道数与输入特征层的通道数相同 2.卷积输出的特征矩阵通道数与卷积核个数相同 池化层 池化中一般池化核大小和步长大小一样 思考 加上偏移量bias该如何计算? 卷积计算时加上偏移量即可 加上激活函数该如何计…

Python画笔案例-055 绘制七彩浪花

1、绘制七彩浪花 通过 python 的turtle 库绘制 七彩浪花&#xff0c;如下图&#xff1a; 2、实现代码 绘制七彩浪花&#xff0c;以下为实现代码&#xff1a; """七彩浪花.py """ import turtlecs [red,orange,yellow,green,cyan,blue,magenta]…

E2VPT: An Effective and Efficient Approach for Visual Prompt Tuning

论文汇总 存在的问题 1.以前的提示微调方法那样只关注修改输入&#xff0c;而应该明确地研究在微调过程中改进自注意机制的潜力&#xff0c;并探索参数效率的极限。 2.探索参数效率的极值来减少可调参数的数量? 解决办法 提示嵌入进行transformer中 提示剪枝 Token-wise …

OpenCV_距离变换的图像分割和Watershed算法详解

在学习watershed算法的时候&#xff0c;书写代码总会出现一些错误&#xff1a; 上述代码运行报错&#xff0c;显示OpenCV(4.10.0) Error: Assertion failed (src.type() CV_8UC3 && dst.type() CV_32SC1) in cv::watershed 查找资料&#xff1a;目前已解决 这个错…

CentOS7搭建Hadoop3集群教程

一、集群环境说明 1、用VMware安装3台Centos7虚拟机 2、虚拟机配置&#xff1a;2C&#xff0c;2G内存&#xff0c;50G存储 3、集群架构设计 从表格中&#xff0c;可以看出&#xff0c;Hadoop集群&#xff0c;主要有2个模块服务&#xff0c;一个是HDFS服务&#xff0c;一个是YAR…

wordpress更换域名后用户图片头像不显示

&#x1f3c6;本文收录于《全栈Bug调优(实战版)》专栏&#xff0c;主要记录项目实战过程中所遇到的Bug或因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&am…

【Python报错已解决】AttributeError: ‘DataFrame‘ object has no attribute ‘append‘

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

基于深度学习的文本情感原因提取研究综述——论文阅读

前言 既然要学习情感分析&#xff0c;那么肯定还要了解情感原因对抽取的发展历程&#xff0c;所以我又搜了一篇研究综述&#xff0c;虽然是2023年发表的&#xff0c;但是里面提及到的历程仅停留到2022年。这篇综述发布在TASLP期刊&#xff0c;是音频、声学、语言信号处理的顶级…

【论文解读系列】用于自监督点云表示的生成变分对比学习

Generative Variational-Contrastive Learning for Self-Supervised Point Cloud Representation | IEEE Transactions on Pattern Analysis and Machine Intelligence (acm.org) 作者&#xff1a;Bohua Wang; Zhiqiang Tian; Aixue Ye; Feng Wen; Shaoyi Du; Yue Gao 摘要 三…

Coggle数据科学 | 科大讯飞AI大赛:玉米雄穗识别挑战赛

本文来源公众号“Coggle数据科学”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;科大讯飞AI大赛&#xff1a;玉米雄穗识别挑战赛 赛题名称&#xff1a;玉米雄穗识别挑战赛 赛题类型&#xff1a;计算机视觉、物体检测 赛题任务&…

LeetCode_sql_day30(1264.页面推荐)

描述 1264.页面推荐 朋友关系列表&#xff1a; Friendship ------------------------ | Column Name | Type | ------------------------ | user1_id | int | | user2_id | int | ------------------------ (user1_id, user2_id) 是这张表具有唯一值的…

HT326 免电感滤波2x20W D类立体声音频功放

特点 输出功率(BTL模式) 2x20W (VDD14.5V,RL4Ω,THDN1%) 单电源系统: 4.5V-18V; 超过90%效率&#xff0c;无需散热器 扩频功能&#xff0c;免电感滤波 模拟差分/单端输入可选 增益:32dB 保护功能:过压/过流/过热/欠压异常&#xff0c;直流检测 和短路保护 无铅无卤封装&#x…