网络编程-套接字相关基础知识


1.1. Socket简介

套接字(socket)是一种通信机制,凭借这种机制, 客户端<->服务器 模型的通信方式既可以在本地设备上进行,也可以跨网络进行。

Socket英文原意是“孔”或者“插座”的意思,在网络编程中,通常将其称之为“套接字”,当前网络中的主流程序设计都是使用Socket进行编程的,因为它简单易用,它还是一个标准(BSD Socket),能在不同平台很方便移植,比如你的一个应用程序是基于Socket编程的,那么它可以移植到任何实现BSD Socket标准的平台,比如LwIP,它兼容BSD Socket;又比如Windows,它也实现了一套基于Socket的套接字接口,更甚至在国产操作系统中,如RT-Thread,它也实现了BSD Socket标准的Socket接口。

在Socket中,它使用一个套接字来记录网络的一个连接,套接字是一个整数,就像我们操作文件一样,利用一个文件描述符,可以对它打开、读、写、关闭等操作,类似的,在网络中,我们也可以对Socket套接字进行这样子的操作,比如开启一个网络的连接、读取连接主机发送来的数据、向连接的主机发送数据、终止连接等操作。

Linux系统中的套接字相关的函数,注意要包含网络编程中常用的头文件:

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

1.2. socket()

函数原型:

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

socket()函数用于创建一个socket描述符(socket descriptor),它唯一标识一个socket,这个socket描述字跟文件描述字一样,后续的操作都有用到它,把它作为参数,通过它来进行一些读写操作。

创建socket的时候,也可以指定不同的参数创建不同的socket描述符,socket函数的三个参数分别为:
1. domain:参数domain表示该套接字使用的协议族
在Linux系统中支持多种协议族,对于TCP/IP协议来说,选择AF_INET就足以,当然如果你的IP协议的版本支持IPv6,那么可以选择AF_INET6,可选的协议族具体见:

AF_UNIX, AF_LOCAL: 本地通信
AF_INET : IPv4
AF_INET6 : IPv6

AF_IPX : IPX - Novell 协议
AF_NETLINK : 内核用户界面设备
AF_X25 : ITU-T X.25 / ISO-8208 协议
AF_AX25 : 业余无线电 AX.25 协议
AF_ATMPVC : 访问原始ATM PVC
AF_APPLETALK : AppleTalk
AF_PACKET : 底层数据包接口
AF_ALG : 内核加密API的AF_ALG接口

2. type:参数type指定了套接字使用的服务类型
可能的类型有以下几种:

SOCK_STREAM:提供可靠的(即能保证数据正确传送到对方)面向连接的Socket服务,多用于资料(如文件)传输,如TCP协议
SOCK_DGRAM:是提供无保障的面向消息的Socket 服务,主要用于在网络上发广播信息,如UDP协议,提供无连接不可靠的数据报交付服务。

SOCK_SEQPACKET:为固定最大长度的数据报提供有序的,可靠的,基于双向连接的数据传输路径。
SOCK_RAW:表示原始套接字,它允许应用程序访问网络层的原始数据包,这个套接字用得比较少,暂时不用理会它。
SOCK_RDM:提供不保证排序的可靠数据报层。

3. protocol:参数protocol指定了套接字使用的协议
在IPv4中,只有TCP协议提供SOCK_STREAM这种可靠的服务,只有UDP协议提供SOCK_DGRAM 服务,对于这两种协议,protocol的值均为0,因为当protocol为0时,会自动选择type类型对应的默认协议。

当创建套接字成功的时候,该函数返回一个int类型的值,也就是socket描述符,该值大于等于0;而如果创建套接字失败时则返回-1

1.3. bind()

函数原型:

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

在套接口中,一个套接字只是用户程序与内核交互信息的枢纽,它自身没有太多的信息,也没有网络协议地址和端口号等信息,在进行网络通信的时候,必须把一个套接字与一个IP地址或端口号相关联,这个过程就是绑定的过程。

bind()函数用于将一个 IP 地址或端口号与一个套接字进行绑定,许多时候内核会帮我们自动绑定一个IP地址与端口号,然而有时用户可能需要自己来完成这个绑定的过程,以满足实际应用的需要,最典型的情况是一个服务器进程需要绑定一个众所周知的地址和端口以等待客户来连接,作为服务器端,这一步绑定的操作是必要的,而作为客户端,则不是必要的,因为内核会帮我们自动选择合适的IP地址与端口号。

    ps:bind()函数并不是总是需要调用的,只有用户进程想与一个具体的地址或端口相关联的时候才需要调用这个函数。如果用户进程没有这个需要,那么程序可以依赖内核的自动的选址机制来完成自动地址选择。

参数:

    sockfd:sockfd是由socket()函数返回的套接字描述符。my_addr:my_addr是一个指向套接字地址结构的指针。addrlen:addrlen指定了以addr所指向的地址结构体的字节长度。

若bind()函数绑定成功则返回0,若出错则为-1。

sockaddr 结构内容如下:

sockaddr结构:

struct sockaddr {sa_family_t     sa_family;char            sa_data[14];
}

咋一看这个结构体,好像没啥信息要我们填写的,确实也是这样子,我们需要填写的IP地址与端口号等信息,都在sa_data连续的14字节信息里面,但这个结构对用户操作不友好,一般我们在使用的时候都会使用sockaddr_in结构,sockaddr_in和sockaddr是并列的结构(占用的空间是一样的),指向sockaddr_in的结构体的指针也可以指向sockadd的结构体,并代替它,而且sockaddr_in结构对用户将更加友好,在使用的时候进行类型转换就可以了。

sockaddr_in结构:

struct sockaddr_in {short int sin_family;               /* 协议族 */unsigned short int sin_port;        /* 端口号 */struct in_addr sin_addr;            /* IP地址 */unsigned char sin_zero[8];          /* sin_zero是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节 */
};

这个结构体的第一个字段是与sockaddr结构体是一致的,而剩下的字段就是sa_data连续的14字节信息里面的内容,只不过从新定义了成员变量而已,sin_port字段是我们需要填写的端口号信息,sin_addr字段是我们需要填写的IP地址信息,剩下sin_zero 区域的8字节保留未用。

举个简单的使用实例:

struct sockaddr_in server;bzero(&server, sizeof(server));// assign IP, PORT
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(6666);// binding newly created socket to given IP and verification
bind(sockfd, (struct sockaddr*)&server, sizeof(server));

参考资料:

1.【野火】《i.MX Linux开发实战指南》

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

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

相关文章

Jenkins安装部署

目录 一、CI/CD介绍 二、持续集成与持续交付 持续集成&#xff08;CI&#xff09; 持续交付&#xff08;CD&#xff09; 持续集成的组成要素 持续集成的好处 持续集成的流程 三、Gitlab简介与特点 四、Gitlab CI/CD工作原理 五、Gitlab的部署与安装 安装依赖环境 G…

docker-compose部署及使用

Docker Compose是一个用于定义和运行多个Docker容器的工具。它使用YAML文件来配置应用程序的服务、网络和卷等方面&#xff0c;使得在单个主机上进行部署更加简单。通过定义一个Compose文件&#xff0c;你可以一次性启动、停止和管理整个应用程序的多个容器。 Compose文件包含了…

【每日一题】[信息与未来 2023] 幸运数字题解(枚举 模拟)

标签&#xff1a;数位拆分、枚举、模拟题意&#xff1a;给定区间 [ a , b ] [a,b] [a,b]&#xff0c;求出区间内满足奇数位和等于偶数位和的数字个数题解&#xff1a;遍历区间内每个数字&#xff0c;统计其奇数位和与偶数位和&#xff0c;如果相等&#xff0c;计数器加一&#…

Stability AI与VAST推出TripoSR:快速3D建模新时代,0.5秒生成3D模型

前言 在人工智能领域&#xff0c;3D内容生成技术正迅速成为创新的前沿。最近&#xff0c;Stability AI与华人团队VAST联合推出的TripoSR模型&#xff0c;标志着3D建模进入了一个新的快速时代。此次合作不仅展示了技术的飞跃发展&#xff0c;也为开发者和创意工作者提供了前所未…

CSS3动画有哪些?

文章目录 一、是什么二、实现方式transition 实现渐变动画transform 转变动画animation 实现自定义动画 三、总结参考文献 一、是什么 CSS动画&#xff08;CSS Animations&#xff09;是为层叠样式表建议的允许可扩展标记语言&#xff08;XML&#xff09;元素使用CSS的动画的模…

使用ScottPlot库在.NET WinForms中快速实现大型数据集的交互式显示

前言 在.NET应用开发中数据集的交互式显示是一个非常常见的功能&#xff0c;如需要创建折线图、柱状图、饼图、散点图等不同类型的图表将数据呈现出来&#xff0c;帮助人们更好地理解数据、发现规律&#xff0c;并支持决策和沟通。本文我们将一起来学习一下如何使用ScottPlot库…

[剪藏] - 由哇哈哈和农夫山泉所想到的

哇哈哈和农夫山泉的缠斗最近冒出来一个有趣的点&#xff1a;营销大于内容的胜利。 具体来说是这样的&#xff1a;农夫山泉很多年前做广告&#xff0c;说纯净水没有矿物质&#xff0c;长期喝是不利于人体健康的。农夫还做了个营销的对比实验&#xff0c;大概是用矿泉水养水仙花&…

ASFF自适应空间特征融合

paper&#xff1a;Learning Spatial Fusion for Single-Shot Object Detection official implementation&#xff1a;https://github.com/GOATmessi7/ASFF 背景 金字塔特征表示pyramid feature representation是解决目标检测中尺度变化挑战的常用方法。特征金字塔的一个主要…

刷题日记——反转公约数、循环位移(厦门大学机试)

题目 分析 将输入的数字看作字符串&#xff0c;然后将字符串转成真实值计算两个真实值&#xff0c;然后从1开始遍历公约数&#xff0c;每次发现一个更大的公约数就替换&#xff0c;直到找不到公约数 代码 #include <cstdio> #include <map> #include <string…

Spring Boot整合canal实现数据一致性解决方案解析-部署+实战

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java全栈-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 目录 1.前言 2.canal部署安装 3.Spring Boot整合canal 3.1数据库与缓存一致性问题…

内存操作函数

memcpy mem--memory--内存 指向计算机内存 cpy-copy-拷贝 也就是内存拷贝 针对内存的函数 void* memcpy(void * destination,const void * source,size_t num) 把source的空间 复制到 destination的部分 长度是num 如果source 和 dest 的部分有重叠,会复制的结果是未定义的(建…

memcpy函数及其模拟实现

一、 函数原型 void *memcpy(void *destin, void *source, size_t n);二、参数 destin-- 指向用于存储复制内容的目标数组&#xff0c;类型强制转换为 void* 指针。 source-- 指向要复制的数据源&#xff0c;类型强制转换为 void* 指针。 n-- 要被复制的字节数。 三、返回…