SOCKET编程(3):相关结构体与函数

相关结构体与函数

sockaddr、sockaddr_in结构体

sockaddr和sockaddr_in详解

struct sockaddr共16字节,协议族(family)占2字节,IP地址和端口号在sa_data字符数组中

/* Structure describing a generic socket address.  */
struct sockaddr
{__SOCKADDR_COMMON(sa_); /* Common data: address family and length.  */char sa_data[14];       /* Address data.  */
};#define	__SOCKADDR_COMMON(sa_prefix) \sa_family_t sa_prefix##family

struct sockaddr_in更细致地划分了协议族、端口号和IP地址,其中IP地址定义了新的结构体struct in_addr该结构体中宏定义了uint32_t类型的变量,sin_zero字符数组存在的意义是为了使struct sockaddr_instruct sockaddr 大小相等,便于进行强制类型转换(与bind()等函数的参数有关)

/* Structure describing an Internet socket address.  */
struct sockaddr_in
{__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)];
};/* Internet address.  */
typedef uint32_t in_addr_t;
struct in_addr
{in_addr_t s_addr;
};

总结

  1. 二者长度一样,都是16个字节,即占用的内存大小是一致的,因此可以互相转化。二者是并列结构,指向sockaddr_in结构的指针也可以指向sockaddr
  2. sockaddr常用于bind、connect、recvfrom、sendto等函数的参数,指明地址信息,是一种通用的套接字地址
  3. sockaddr_in 是internet环境下套接字的地址形式
  4. 在网络编程中我们会对sockaddr_in结构体进行操作,使用sockaddr_in来建立所需的信息,最后使用类型转化
  5. 一般先把sockaddr_in变量赋值后,强制类型转换后传入用sockaddr做参数的函数:sockaddr_in用于socket定义和赋值;sockaddr用于函数参数

socket()函数

socket函数用于创建一个新的socket,也就是向系统申清一个socket资源

socket函数用户客户端和服务端

int socket(int domain, int type, int protocol);

domain:协议域,又称协议族(family)。常用的协议族有AF INET、AF INET6、AF LOCAL(或称AF UNIX,Unix域Socket)、AF ROUTE等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址

type:指定socket类型。常用的socket类型有SOCK_STREAM、SOCK_DGRAM、SOCK RAW、SOCK_PACKET、SOCK_SEQPACKET等。流式socket(SOCK_STREAM)是一种面向连接的socket,针对于面向连接的TCP服务应用。数据报式socket(SOCK_DGRAM)是一种无连接的socket,对应于无连接的UDP服务应用

protocol:指定协议。常用协议有IPPROTO_TCP、IPPROTO_UDP、IPPROTO_STCP、IPPROTO_TIPC等,分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议

💡 第一个参数只能填AF INET,第二个参数只能填SOCK STREAM,第三个参数只填0

除非系统资料耗尽,socket函数一般不会返回失败

返回值:成功则返回一个socket,失败返回-1,错误原因存于errno中

💡 “资源耗尽”即Linux对打开文件数的限制,见2022-06-10笔记

// 第1步:创建服务端的socket
int listenfd;
for (int i = 0; i < 2000; ++i)
{if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){perror("socket");return -1;}cout << "sock id:" << listenfd << endl;
}
sock id:1012
sock id:1013
sock id:1014
sock id:1015
sock id:1016
sock id:1017
sock id:1018
sock id:1019
sock id:1020
sock id:1021
sock id:1022
sock id:1023
socket: Too many open files

inet_addr() 和inet_ntoa()函数

使用socket进行通信的时候,我们需要指定三个元素:通信域(地址族)、IP地址、端口号,这三个元素由SOCKADDR_IN结构体定义

为了简化编程一般将IP地址设置为INADDR_ANY,如果需要使用特定的IP地址则需要使用inet_addr()** 和**inet_ntoa()函数

inet_addr()inet_ntoa()完成字符串和in_addr结构体的互换

inet_addr()函数参数cp代表点分十进制的IP地址,如1.2.3.4,返回值为in_addr_t 类型

/* Convert Internet host address from numbers-and-dots notation in CPinto binary data in network byte order.  */
extern in_addr_t inet_addr (const char *__cp) __THROW;

inet_ntoa() 函数输入为in_addr结构体而输出为字符串

/* Convert Internet number in IN to ASCII representation.  The return valueis a pointer to an internal array containing the string.  */
extern char *inet_ntoa (struct in_addr __in) __THROW;

hostent结构体

hostent实例详解

/* Description of data base entry for a single host.  */
struct hostent
{char *h_name;			/* Official name of host.  */char **h_aliases;		/* Alias list.  */int h_addrtype;		/* Host address type.  */int h_length;			/* Length of address.  */char **h_addr_list;		/* List of addresses from name server.  */
#ifdef __USE_MISC
# define	h_addr	h_addr_list[0] /* Address, for backward compatibility.*/
#endif
};
struct hostent{char *h_name;         //正式主机名char **h_aliases;     //主机别名int h_addrtype;       //主机IP地址类型:IPV4-AF_INETint h_length;		      //主机IP地址字节长度,对于IPv4是四字节,即32位char **h_addr_list;	  //主机的IP地址列表};#define h_addr h_addr_list[0]   //保存的是IP地址
  • h_name:官方域名(Official domain name)。官方域名代表某一主页,但实际上一些著名公司的域名并未用官方域名注册
  • h_aliases:别名,可以通过多个域名访问同一主机。同一 IP 地址可以绑定多个域名,因此除了当前域名还可以指定其他域名
  • h_addrtype:gethostbyname() 不仅支持 IPv4,还支持 IPv6,可以通过此成员获取IP地址的地址族(地址类型)信息,IPv4 对应 AF_INET,IPv6 对应 AF_INET6
  • h_length:保存IP地址长度。IPv4 的长度为 4 个字节,IPv6 的长度为 16 个字节
  • h_addr_list:这是最重要的成员。通过该成员以整数形式保存域名对应的 IP 地址。对于用户较多的服务器,可能会分配多个 IP 地址给同一域名,利用多个服务器进行均衡负载

在这里插入图片描述

在实际的应用中,一台服务器往往有好几个IP地址,而域名只有一个,这样设计的好处是,可以使系统分布设计,提升服务器的稳定性和抗灾难能力

一般对服务器的访问,则是先经过DNS(Domain Name System)服务器,DNS通过均衡设计,返回合适的IP与客户端进行交互,避免客户端只连接一个IP,导致网络拥堵

gethostbyname()函数

gethostbyname()函数:通过域名获取IP地址

gethostbyname()函数详解

客户端中直接使用IP地址会有很大的弊端,一旦IP地址变化(IP地址会经常变动),客户端软件就会出现错误
而使用域名会方便很多,注册后的域名只要每年续费就永远属于自己的,更换IP地址时修改域名解析即可,不会影响软件的正常使用

域名仅仅是 IP 地址的一个助记符,目的是方便记忆,通过域名并不能找到目标计算机,通信之前必须要将域名转换成 IP 地址

gethostbyname() 函数可以完成这种转换

/* Return entry from host data base for host with NAME.This function is a possible cancellation point and therefore notmarked with __THROW.  */
extern struct hostent *gethostbyname (const char *__name);

bind()函数

服务端用于将把用于通信的地址和端口绑定到socket上

int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

sockfd:需要绑定的socket

addr:存放了服务端用于通信的地址和端口

addrlen:表示addr结构体的大小

返回值:成功则返回0,失败返回-1,错误原因存于errno中

如果绑定的地址错误,或端口已被占用,bind函数一定会报错,否则一般不会返回错误

💡 注意第二个参数为sockaddr结构体指针

在这里插入图片描述

listen()函数

listen函数使用主动连接套接口变为被连接套接口,使得一个进程可以接受其它进程的请求,从而成为一个服务器进程

在TCP服务器编程中listen函数把进程变为一个服务器,并指定相应的套接字变为被动连接

/* Prepare to accept connections on socket FD.N connection requests will be queued before further requests are refused.Returns 0 on success, -1 for errors.  */
extern int listen (int __fd, int __n) __THROW;

_fd:服务端的socket,标识绑定的,未连接的套接字的描述符

-n:挂起的连接队列的最大长度

  • 比如有100个用户链接请求,但是系统一次只能处理20个,那么剩下的80个不能不理人家,所以系统就创建个队列记录这些暂时不能处理,一会儿处理的连接请求,依先后顺序处理,那这个队列到底多大?就是这个参数设置,比如2,那么就允许两个新链接排队。这个不能无限大,那内存就不够了
  • 可以手动设置这个参数,但是别太大
  • 我们一般填写这个参数为SOMAXCONN ,让系统自动选择最合适的个数

connect()函数

#include <sys/types.h> 					
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);参数:
第一个参数:int sockdf:socket文件描述符
第二个参数: const struct sockaddr *addr:传入参数,指定服务器端地址信息,含IP地址和端口号
第三个参数:socklen_t addrlen:传入参数,传入sizeof(addr)大小
返回值:成功: 0失败:-1,设置errno

当客户端调用 connect()函数之后,发生一下情况之一才会返回(完成函数调用)

  • 服务器端接收连接请求
  • 发生断网的异常情况而终端连接请求

需要注意的是,所谓的“接收连接”并不意味着服务器调用 accept()函数,其实是服务器端把连接请求信息记录到等待队列,因此 connect()函数返回后并不进行数据交换,而是要等服务器端 accept 之后才能进行数据交换(read、write)

客户端端需要调用connect()连接服务器,connect和bind的参数形式一致,区别在于bind的参数是自己的地址,而connect的参数是对方的地址

accept()函数

socket的accept函数解析

socket中accept()函数的理解

/* Await a connection on socket FD.When a connection arrives, open a new socket to communicate with it,set *ADDR (which is *ADDR_LEN bytes long) to the address of the connectingpeer and *ADDR_LEN to the address's actual length, and return thenew socket's descriptor, or -1 for errors.This function is a cancellation point and therefore not marked with__THROW.  */
extern int accept (int __fd, __SOCKADDR_ARG __addr,socklen_t *__restrict __addr_len);

在这里插入图片描述

send()函数

send函数用于把数据通过socket发送给对端

不论是客户端还是服务端,应用程序都用send函数来向TCP连接的另一端发送数据

ssize_t send(int sockfd, const void *buf, size_t len, int flags);
  • sockfd为已建立好连接的socket
  • buf为需要发送的数据的内存地址,可以是C语言基本数据类型变量的地址,也可以数组、结构体、字符串,内存中有什么就发送什么
  • len需要发送的数据的长度,为buf中有效数据的长度
  • flags填0,其他数值意义不大
  • 函数返回已发送的字符数,出错时返回-1,错误信息errno被标记
  • 注意,就算是网络断开,或socket已被对端关闭,send函数不会立即报错,要过几秒才会报错
  • 如果send函数返回的错误(<=0),表示通信链路已不可用

recv()函数

recv函数用于接收对端通过socket发送过来的数据

不论是客户端还是服务端,应用程序都用recv函数接收来自TCP连接的另一端发送过来数据

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

参数信息同send()函数

函数返回已接收的字符数,出错时返回-1,失败时不会设置errno的值

  • 如果socket的对端没有发送数据,recv函数就会等待
  • 如果对端发送了数据,函数返回接收到的字符数
  • 出错时返回-1,如果socket被对端关闭,返回值为0
  • 如果recv函数返回的错误(<=0),表示通信通道已不可用

💡 数据收发时的数据量会受到发送缓冲区和接收缓冲区大小的限制
数据收发时要注意字节序的问题(不同主机字节序的问题)

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

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

相关文章

抓大鹅教程电脑端秒通关……

大家好&#xff0c;我是小黄。 最近抓大鹅小程序游戏很火&#xff0c;抓大鹅小游戏是由青岛蓝飞互娱科技股份有限公司开发并推出的一款休闲益智类三消游戏。在游戏中&#xff0c;玩家需要在特定的“购物篮子”背景下&#xff0c;找到三个相同的物品并将其消除。游戏的玩法简单…

社工库信息查询

此网站需要注册账号&#xff0c;新用户注册送3点券&#xff0c;每日签到可获得1.5点券。也可通过充值来查 我这里有方法可以利用缺陷来无限获取点券查人

程序员的归宿。。

大家好&#xff0c;我是瑶琴呀。 相信每个进入职场的人都考虑过自己的职业生涯规划&#xff0c;在不同的年龄段可能面临不同挑战&#xff0c;这点对于 35 的人应该更为感同身受。 对于程序员来说&#xff0c;大部分人的职业道路主要是下面三种&#xff1a;第一条&#xff0c;…

【Delphi 爬虫库 6】使用正则表达式提取猫眼电影排行榜top100

正则表达式库的简单介绍 正则表达式易于使用&#xff0c;功能强大&#xff0c;可用于复杂的搜索和替换以及基于模板的文本检查。这对于输入形式的用户输入验证特别有用-验证电子邮件地址等。您还可以从网页或文档中提取电话号码&#xff0c;邮政编码等&#xff0c;在日志文件中…

人生是旷野,不是轨道

最近看到一句话&#xff0c;很喜欢&#xff0c;分享一下。"人生是旷野&#xff0c;不是轨道"。人生不是固定的方程式&#xff0c;也没有唯一答案&#xff0c;没有谁生来就应该是什么样。别太被太多世俗观念束缚住手脚&#xff0c;每个人都有权利自由生长&#xff0c;…

用友畅捷通T+ keyEdit sql注入漏洞

产品介绍 畅捷通 T 是一款灵动&#xff0c;智慧&#xff0c;时尚的基于互联网时代开发的管理软件&#xff0c;主要针对中小型工贸与商贸企业&#xff0c;尤其适合有异地多组织机构&#xff08;多工厂&#xff0c;多仓库&#xff0c;多办事处&#xff0c;多经销商&#xff09;的…

朋友圈刷屏的粘土风格照片,你体验过了吗?

Remini 的粘土风格真的丑萌丑萌的&#xff01; 从去年“妙鸭相机”的走红&#xff0c;到今年Remini的刷屏&#xff0c;其实可以看出大众对于图片趣玩的兴趣非常大&#xff01; 一张普通的照片经过工具的处理&#xff0c;一下子变成新风格&#xff0c;让人眼前一亮。如果你也对…

GPT-SoVits:语音克隆,语音融合

首发网站 https://tianfeng.space 前言 零样本文本到语音&#xff08;TTS&#xff09;&#xff1a; 输入 5 秒的声音样本&#xff0c;即刻体验文本到语音转换。少样本 TTS&#xff1a; 仅需 1 分钟的训练数据即可微调模型&#xff0c;提升声音相似度和真实感。跨语言支持&…

信息收集方法合集 第1期

前言 在工作中&#xff0c;经常被问到某个文件怎么下载&#xff0c;原文来自哪里。索性把我知道的所有信息收集方法全部整理一遍&#xff0c;希望对大家有用&#xff0c;如果有帮助到你&#xff0c;非常荣幸&#xff0c;我会坚持分享我的学习、工作经验。 信息种类&#xff1…

云启未来:“云计算与网络运维精英交流群”与“独家资料”等你来探索“

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 公众号&#xff1a;网络豆云计算学堂 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a; 网络豆的主页​​​​​ &#x1f680; 云计算与运维精英交流群诚邀您的加入…

搭建Docker私服镜像仓库Harbor

1、概述 Harbor是由VMware公司开源的企业级的Docker Registry管理项目&#xff0c;它包括权限管理(RBAC)、LDAP、日志审核、管理界面、自我注册、镜像复制和中文支持等功能。 Harbor 的所有组件都在 Dcoker 中部署&#xff0c;所以 Harbor 可使用 Docker Compose 快速部署。 …

PermissionError: [Errno 13] Permission denied: ‘xx.xlsx‘的解决办法

我在转换文件的时候遇到这个报错&#xff0c;原因是文件名与已有文件名重复了 解决办法很简单&#xff0c;如下图把" " 里的名字换成不重复的&#xff0c;再次允许代码&#xff0c;会恢复正常

ue引擎游戏开发笔记(37)——实现敌人接收攻击伤害,并作出反应

1.需求分析&#xff1a; 现在已经显示造成实际伤害&#xff0c;但敌人对实际伤害并未产生反馈&#xff0c;例如还击&#xff0c;或者死亡倒地等等&#xff0c;实现敌人对于受击的反馈。 2.操作实现&#xff1a; 1.思路&#xff1a;在动画蓝图中添加死亡动画&#xff0c;并通过…

【姿态解算与滤波算法】

姿态解算 一、主线 姿态表示方式&#xff1a;矩阵表示&#xff0c;轴角表示&#xff0c;欧拉角表示&#xff0c;四元数表示。 惯性测量单元IMU&#xff08;Inertial Measurement Unit&#xff09;&#xff1a;MPU6050芯片&#xff0c;包含陀螺仪和加速度计&#xff0c;分别测…

winhex工具,将文件转换为16进制数据放入代码。

今天介绍winhex工具&#xff0c;可以将任何内容读取读取为16进制数据。下面看下效果。 下载链接&#xff1a; WinHex: Hex Editor & Disk Editor, Computer Forensics & Data Recovery Software 一、WinHex打开文件 我们要打开的文件&#xff1a; 打开后&#xff1a; 我…

服务器远程桌面局域网连接不上的解决方法

在企业网络环境中&#xff0c;服务器远程桌面局域网连接不上是一个常见且棘手的问题。这种问题可能导致工作效率下降&#xff0c;甚至影响业务运营。因此&#xff0c;我们需要采取专业的方法来解决这一问题。 服务器远程桌面局域网连接不上的解决方法&#xff1a; 1、确保服务器…

解锁网站SEO优势,百度站长工具助您一臂之力(百度站长平台还提供了哪些工具供seo人员使用?)

在当今数字化时代&#xff0c;网站已经成为企业宣传、产品销售、信息发布的主要渠道之一。有着再好的网站&#xff0c;如果在百度等搜索引擎中无法被用户搜索到&#xff0c;那就等于白搭。因此&#xff0c;网站的SEO优化显得尤为重要。而作为国内最大的搜索引擎&#xff0c;百度…

LoRa模块学习

什么是LoRa调制 LoRa&#xff08;Long Range&#xff0c;远距离&#xff09;是一种调制技术&#xff0c;与同类技术相比&#xff0c;提供更长的通信距离。调制是基于扩频技术&#xff0c;线性调制扩频&#xff08;CSS&#xff09;的一个变种&#xff0c;具有前向纠错&#xff…

安装SQL Server详细教程_sql server安装教程

一&#xff0c;SQL Server数据库安装 1.首先&#xff0c;下载安装程序 &#xff08;1&#xff09;从网盘下载安装exe 点击此处直接下载 &#xff08;2&#xff09;从官网下载安装exe文件 在官网选择Developer进行下载 2.开始安装 双击安装程序&#xff0c;开始安装 这里直…

搭建vue3组件库(四): 样式库搭建

文章目录 1. 样式目录文件架构2. SCSS 样式变量2.1 设置颜色 SCSS 变量2.2 设置多种类型主题2.3 生成全局类型主题 SCSS 变量2.4 分组生成 SCSS 变量 1. 样式目录文件架构 packages/theme-chalk 目录结构&#xff1a; ├── packages │ ├── theme-chalk │ │ ├─…