您的位置:首页 > 教育 > 培训 > 域名备案查询网址_扬中做网站_google play下载安装_seo设置是什么

域名备案查询网址_扬中做网站_google play下载安装_seo设置是什么

2025/3/19 14:40:39 来源:https://blog.csdn.net/WYF_111501/article/details/146350867  浏览:    关键词:域名备案查询网址_扬中做网站_google play下载安装_seo设置是什么
域名备案查询网址_扬中做网站_google play下载安装_seo设置是什么

一、套接字

1.1什么是套接字

套接字文件,原本就是一个和管道文件类似,用来实现进程间通信的一个文件

既然有了管道文件,当时为什么还要开发套接字文件,去实现进程的通信

因为管道文件是半双工模式的

套接字文件是全双工模式的

但是后来,有了OSI 7层模型以及TCP协议 4层模型之后

套接字文件就进化出了新的功能:

套接字文件中允许存放 ip 和 port 以实现数据的跨主机传输

原先只能实现进程间通信的套接字,就有了一个新的名字:域套接字

1.2 如何创建一个套接字文件:socket

函数原型:int socket(int domain, int type, int protocol);
功能描述:创建一个套接字文件,参数不同,功能类型就会不同
参数描述:参数 domain:网络介质,常用的有以下几种AF_UNIX,AF_LOCAL : 本地通信协议,其实就是给域套接字用的AF_INET:ipv4 地址协议AF_INET6:ipv6 地址协议最常用的就是: AF_INET参数 type:套接字类型,有以下2个常用类型SOCK_STREAM:提供一种有序的、可靠的、全双工的、基于连接的字节流套接字 这个描述一看就知道,tcp协议用的就是这种套接字SOCK_DGRAM:提供一种数据报文形式的,非连接的,不可靠的,发送的数据有最大长度限制的套接字这个描述一看就知道,udp协议使用的是这种套接字参数 protocol: 一般直接写0表示:网络通信协议会根据套接字的类型自动选取如果套接字类型为 SOCK_STREAM,protocol 为0,则自动选用tcp协议如果套接字类型为 SOCK_DGRAM,protocol 为0,则自动选用udp协议
返回值:成功创建套接字,返回套接字的描述符,失败返回-1套接字描述符和文件描述一回事儿,遵循最小未使用原则

1.3 如何向套接字文件中写入ip 和 port

套接字写入ip和port其实就是明确一下ip和port到底是多少

之前讲过,服务器和客户端都需要明确ip和port

也就是说,服务器套接字和客户端套接字,都需要将ip和port写入套接字里面

1.3.1 先要准备一个地址信息结构体:struct sockaddr_in

该结构体结构如下:
struct sockaddr_in{unsigned short sin_family; // 这是一个标记位,固定写 AF_INETunsigned short sin_port; // 端口号struct in_addr sin_addr;// 一个结构体,结构如下struct in_addr{unsigned int s_addr; // 用来存放ip地址的变量        } unsigned char zero[8]; // 没有实际意义,完全为了字节对齐填充大小
}实例:准备将 "192.168.1.1" 和 8888 端口写入结构体中,为未来写入套接字中做准备struct sockaddr_in addr = {0};addr.sin_family = AF_INET;addr.sin_port = htons(8888); // 因为本地字节序和网络字节序不一定一致,所以端口号在进入网络之前,一定要转换成大端字节序addr.sin_addr.s_addr = inet_addr("192.168.1.1");

1.3.2 将准备好的存有ip和port的结构体写入套接字中

函数原型:int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
功能描述:将写有ip和port地址信息结构体,写入套接中
参数描述:参数 sockfd:准备写入ip和port的套接字参数 addr:写有ip和port的结构体地址,该结构体如下struct sockaddr {unsigned short sa_family;  // 固定写 AF_INETchar        sa_data[14]; // 这个14个字节的内存里面,就是用来存放 ip 和 port的}如果使用这个结构体去存放ip和port的话,代码如下参数 addrlen:就是第二个参数 addr 的实际占用长度
返回值:成功返回0,失败返回-1。bind函数非常容易报错,只要绑定的端口号已经被用了,就会报错这个 struct sockaddr 这个结构体我们成为通用地址结构体
事实上有2个结构体会通过我们所介绍的地址上的0101直接赋值的形式转换成 struct sockaddr 这个结构体
struct sockaddr_in
struct sockaddr_un调用形式struct sockaddr_in addr = {0};addr.sin_family = AF_INET;addr.sin_port = htons(8888); // 因为本地字节序和网络字节序不一定一致,所以端口号在进入网络之前,一定要转换成大端字节序addr.sin_addr.s_addr = inet_addr("192.168.1.1");if(bind(server,(struct sockaddr*)&addr,sizeof(addr)) == -1){perror("bind");    }

1.4 如何使用套接字文件传输数据

1.4.1 直接使用 read 或者 write 函数

文件IO里面的read 和 write 怎么用,套接字的read和write就怎么用

不再介绍

1.4.2 recv 和 send

这2个函数专门给套接字使用的,描述符用不了

函数原型:ssize_t send(int sockfd, const void *buf, size_t len, int flags);
功能描述:通过套接字,将数据发送到网络中
参数描述:前3个参数 sockfd、buf、len :功能和write一模一样参数 flags:这个参数也是send 和 write 的区别所在flags 可以设定 send 是一个阻塞型 IO 还是非阻塞型 IO0:阻塞型IOMSG_DONTWAIT:非阻塞型IOsend什么时候阻塞:发送数据目标地点,如果满了,则send会阻塞,直到目标地点产生新的空间为止、所以从我们的角度来看:send 和write 唯一的区别在于send 自带设置阻塞和非阻塞的参数write 不自带这个功能,默认阻塞函数原型:ssize_t recv(int sockfd, void *buf, size_t len, int flags);
功能描述:通过套接字,从网络中读取数据
参数描述:前3个参数 sockfd、buf、len :功能和read一模一样参数 flags:这个参数也是send 和 write 的区别所在flags 可以设定 send 是一个阻塞型 IO 还是非阻塞型 IO0:阻塞型IOMSG_DONTWAIT:非阻塞型IO    所以从我们的角度来看:recv 和 read 唯一区别在于recv 自带设置阻塞和非阻塞的参数read 不自带,默认阻塞

1.5 如何将任意一个阻塞型IO函数,设置成非阻塞的

函数原型:int fcntl(int fd, int cmd, ... /* arg */ );
功能描述:该函数有多个功能,到底执行哪个功能由 cmd 的值决定
参数描述:参数 cmd :F_GETFL:获取 fd 描述符的 flagF_SETFL:设置 fd 描述符的 flag当cmd选择F_SETFL的时候,需要传入第3个参数,第三个参数功能为 想要设置的具体的flag的值到底什么是flag:其实就是open函数第2个参数 flag,也就是文件描述符属性属性有:可读,可写,追加,清空,创建,非阻塞 等等等等以scanf为例:通过fcntl函数将标准输入流修改成非阻塞型IOscanf 用的是 stdin 标准输入流,阻塞型IO一旦将标准输入流修改成非阻塞型IO之后,scanf就不阻塞了

二、创建服务器

2.1 服务器的搭建

2.1.1 创建服务器套接字:socket

2.1.2 提前准备ip和port:struct sockaddr_in addr

2.1.3 为服务器套接字绑定ip和port :bind

2.1.4 创建一个监听列表:listen

所有连接服务器的客户端,都会被服务器加入到监听列表中去

函数原型:int listen(int sockfd, int backlog);
功能描述:创建监听列表并监听客户端连接,如果有客户端连接,则将该客户端加入监听列表中
参数描述:参数 sockfd:哪个描述符需要监听并创建监听列表,一般就是服务器的描述符参数 backlog:监听列表的大小

2.1.5 从监听列表中,接受客户端的连接:accept

函数原型:int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能描述:接受客户端的连接,并且获取该客户端的ip和port
参数描述:参数 sockfd:哪个描述符接受客户端的连接,一般就是服务器参数 addr:一个地址信息结构体的地址,该结构体中将会接受并存放新链接的客户端的ip和port参数 addrlen:第二个参数的实际长度,但是注意这里是个指针返回值:成功接受客户端的连接之后,会返回该客户端的套接字客户端套接字非常有用,服务器与特定的客户端进行通信的时候,必须使用该客户端套接字调用形式:struct sockaddr_in client_addr = {0};int len = sizeof(client_addr);int client = accept(server,(struct sockaddr*)&client_addr,&len);当然,我们也可以仅接受客户端的连接,不需要知道客户端的ip和portint client = accept(server,NULL,NULL);注意:accept 函数是一个阻塞型函数也就是说,一旦调用accept函数就会立刻阻塞,直到有客户端连接为止

2.1.6 服务器代码

三、创建客户端

3.1 客户端的搭建

3.1 创建客户端套接字 :socket

3.2 为客户端准备 ip 和 port :struct sockaddr_in addr

3.3 连接服务器:connect

函数原型:int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
功能描述:根据提供的ip和port连接到指定服务器
参数描述:参数 sockfd:客户端套接字参数 addr:存有ip和port的一个通用地址信息结构体参数 addrlen:第2个参数的实际长度
返回值:成功连接返回0,失败返回-1,因为存在失败的可能,所以记得判空调用形式struct sockaddr_in addr = {0};addr.sin_family = AF_INET;addr.sin_port = htons(8888); // 因为本地字节序和网络字节序不一定一致,所以端口号在进入网络之前,一定要转换成大端字节序addr.sin_addr.s_addr = inet_addr("192.168.1.1");if(connect(server,(struct sockaddr*)&addr,sizeof(addr)) == -1){perror("bind");    }

3.4 客户端断开连接

客户端一旦与服务器断开链接之后

服务器那边,通过客户端套接字读取客户端发送数据的read或者recv函数,就会从阻塞变成非阻塞

变成非阻塞之后,如果没有读取到数据,则会返回0

所以我们可以根据read或者recv的返回值来判断客户端是否断开连接

3.5 客户端代码

四、TCP中的粘包现象

tcp协议为了提高发送的效率,会将短时间连续发送的小数据,当做一组数据统一发送

原理是:

tcp协议本身存在一个1500字节的缓存区,tcp协议每次write发送数据的时候,总是会发送1500个字节

如果发送了n组数据,这n组数据的时间间隔很短,并且数据总大小没有超过1500个字节

那么TCP协议就会将这n组数据全都放到同一个1500字节的缓存区中去,统一发送

4.1 协议包

规定好一组数据的固定大小,以及一组数据里面每个数据占据多少个字节

然后服务器和客户端,全都遵循同样的规定实现数据的收发

这样的规定如果我们把它打包写成具体的代码,打包出来的成果我们就称为协议包

4.1.1 使用协议包的服务器

4.1.2 使用协议包的客户端

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com