当前位置: 首页 > news >正文

网络编程(套接字)

目录

一、套接字

1、套接字的作用

2、关于TCP和UDP协议

1. TCP协议

2. UDP协议

3. 两者的区别

2、套接字函数

1)函数 socket(创建套接字同文件描述符)

2)准备套接字用结构体

1. 套接字的结构体

2. 客户端的套接字:

3. 服务器的套接字:

3)bind(以结构体向套接字中写入 ip、port)

4)send / write(通过套接字发送数据)

5)recv / read(通过套接字接收数据)

6)fcntl(变更函数状态:阻塞/非阻塞)


一、套接字

套接字在最初只是一种IPC通讯手段,在TCP协议出现,TCP协议使用套接字进行通信,因此我们常说的套接字都是应用于网络通信,而早期只用于进程间通讯的则称为域套接字

1、套接字的作用

专门用于网络间通信的一种文件形式

该文件,包含了要交换的数据和通信双方的 ip地址和 port端口号

ip地址和 port端口号需要我们自己添加到套接字中,并且不同的协议需要使用不同类型的套接字

2、关于TCP和UDP协议

TCP协议和UDP协议的套接字就是不同类型的

1. TCP协议

TCP协议是一个可靠的,连续的,基于字节流的协议,TCP具有流量控制功能,顺序控制功能,应答重发功能,以确保在网络不拥堵的时候,所有的数据都可以正确的发送

2. UDP协议

UDP协议由于非连续性,且没有有效的应答手段,所以不可靠,很容易丢包

向前纠错技术(后来各大厂商对UDP协议的更进,添加了校验的方法)

udp协议在发送数据的时候,会选择在发送 n 个数据的时候,匹配发送 m 个校验包

比如说发送 3个数据的时候,匹配发送1个校验包

最简单的校验包 = 1#数据报 + 2#数据报 + 3#数据报

比如说:发送了 1 ,2,3 这3个数据,此时,再发送一个校验包,校验包的值是 4

很明显,在丢包率为 25% 的时候,3个包配一个校验包,就能完全避免丢包

因为4个包里面丢一个,丢了校验包完全无所谓

丢的是任意一个数据包,可以通过校验包和其他数据包,恢复出丢失的数据是多少

依此类推:如果网络波动变大,我们就需要配更多的校验包,以保证丢包率减低,恢复率提高

3. 两者的区别

TCP协议稳定性高,传输速度慢,UDP协议稳定性差,传输速度快

2、套接字函数

1)函数 socket(创建套接字同文件描述符)

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
功能:创建不同类型的套接字用文件描述符
参数 domain:套接字所依赖的网络介质如果是 ipv4 就填入 AF_INET如果是 ipv6 就填入 AF_INET6如果是 域套接字 就填入 AF_LOCAL / AF_UNIX
参数 type:选择套接字的类型SCOK_STREAM:字节流套接字传输数据,连续,可靠,双向,数据量大SOCL_DGRAM:数据包套接字传输数据,不连续,不可靠,有长度要求,双向
参数 protocol:选择套接字所依赖的通信协议0:自动匹配,会根据参数 type 和参数 protocol 自动选择合适的通信协议
返回值:返回创建套接字文件描述符一般来说:AF_INET + SOCK_STREAM + 0 ,最终创建的是 TCP 协议的套接字AF_INET + SOCK_DGRAM  + 0 ,最终创建的是 UDP 协议的套接字 

        字节流的优点:允许发送无穷大的数据,会在内核中对数据做分割处理,但是由于连续发送,数据依然粘连在一起

        字节流的缺点:由于数据是粘连的,因此接收端需要花费大量的时间处理数据

        数据包的优点:数据不会粘连,发送几次数据就是几个数据包

        数据包的缺点:发送的数据大小有上限,过大的数据需要手动分批次发送,还有丢包的风险

2)准备套接字用结构体

1. 套接字的结构体
struct sockaddr_in {__kernel_sa_family_t  sin_family; /* 依赖的网络介质       */__be16        sin_port;           /* port端口号           */struct in_addr    sin_addr;       /* ip地址               */
};

        127.0.0.1 是一个本地回环地址,不会经过网卡,专门用来在无网络的情况下做本地测试,
抓包工具无法抓到这个 ip地址 的数据

2. 客户端的套接字:

写入 ip地址 的目的 是为了通过 ip地址,找到该客户端想要连接的服务器

写入 port端口号 的目的 是为了通过端口号,知道数据需要发送到服务器的哪个进程  

3. 服务器的套接字:

写入 ip地址 的目的 是过滤掉不想接收的客户端,选择想要连接的客户端

写入 port端口号 的目的 是为了让服务器知道要去哪个进程读取接收到的数据

3)bind(以结构体向套接字中写入 ip、port)

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
功能:往套接字中写入 ip地址 和 port端口号 (该操作被称为为套接字命名)
参数 sockfd:填写 套接字用文件描述法
参数 addr:通用套接字结构体指针,需要提前准备 struct sockaddr_in 类型的结构体
参数 addrlen:参数 addr 的字节长度

4)send / write(通过套接字发送数据)

#include <sys/types.h>
#include <sys/socket.h>
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
功能:通过套接字,向套接字中指向的ip地址发送数据
参数 sockfd:填入 socket创建的套接字文件描述符
参数 buf:填入 要发送的数据的地址
参数 len:填入 要发送的字节的长度
参数 flag:设置函数的状态 阻塞 / 非阻塞0    :默认阻塞,发送数据给目标,目标的接收区满了,就会发送阻塞MSG_DONTWAIT:非阻塞,发送数据给目标,接收区满了,丢弃新发送的数据
=======================================================================
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
用法基本一致,IO篇也有详细介绍

5)recv / read(通过套接字接收数据)

#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
功能:通过套接字,读取套接字中ip地址所发送的数据
参数 sockfd:由socket创建的套接字文件描述符
参数 buf:将读取到的数据存入buf所指向的连续地址(所指向的数组)
参数 len:所读取数据的字节长度
参数 flags:设置函数的状态 阻塞 / 非阻塞0    :默认阻塞,没有接收到数据就阻塞MSG_DONTWAIT:非阻塞,没有读取到数据直接返回 0 
返回值:阻塞模式:返回接收到数据的字节数,若套接字损坏 返回 -1若服务器与客户端连接断开,则有阻塞函数变为非阻塞函数,并返回 0非阻塞模式:返回接收到数据的字节数,若服务器与客户端断开,返回 -1未接收到参数,则返回 0
=====================================================================
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
用法基本一致,IO篇也有详细介绍

6)fcntl(变更函数状态:阻塞/非阻塞)

#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
功能:设置指定文件描述符的状态,也就是flags属性
参数 cmd:设置函数的功能 设置 flags 或 读取 flagsF_SETFL:设置 fd 文件的 flags 属性F_GETFL:获取 fd 文件的 flags 属性
不定参 ···:此处只有第一个数据是有效的仅当 cmd == F_SETFL 时,需要传一个不定参作为 flags
返回值:当 cmd == F_SETFL 时,成功返回 0 ,失败返回 -1当 cmd == F_GETFL 时,返回 flags ,失败返回 -1

使用时要注意不要变更原有的状态,因此尽可能追加flags值(若有需要替换原先的值,也可以换)

使用流程:
1、先获取 fd 原有的 flags 属性
2、对获取到的 flags 属性追加
3、将追加好的 flags 属性,设置为 fd 的 flags 属性

以标准输入流为例

http://www.xdnf.cn/news/1124191.html

相关文章:

  • HTML应用指南:利用GET请求获取河南省胖东来超市门店位置信息
  • win10安装Elasticsearch
  • iOS高级开发工程师面试——RunTime
  • 深度解读virtio:Linux IO虚拟化核心机制
  • 一种用于医学图像分割的使用了多尺寸注意力Transformer的混合模型: HyTransMA
  • 记录自己在将python文件变成可访问库文件是碰到的问题
  • Linux的相关学习
  • JavaScript进阶篇——第一章 作用域与垃圾回收机制
  • 2025 R3CTF
  • 日语学习-日语知识点小记-构建基础-JLPT-N3阶段(4):语法+单词+復習+发音
  • JS基础知识(上)
  • 设计模式(行为型)-迭代器模式
  • H2 与高斯数据库兼容性解决方案:虚拟表与类型处理
  • 前端开发中的常见问题及解决方案
  • 群晖Nas - Docker(ContainerManager)上安装SVN Server和库权限设置问题
  • HarmonyOS从入门到精通:动画设计与实现之九 - 实用动画案例详解(下)
  • Redis作缓存时存在的问题及其解决方案
  • mysql 与redis缓存一致性,延时双删 和先更新数据库,再删除缓存,哪个方案好
  • 《Librosa :一个专为音频信号处理和音乐分析设计的Python库》
  • Pythonic:Python 语言习惯和哲学的代码风格
  • Kubernetes 高级调度01
  • STM32F1_Hal库学习UART
  • 破局与重构:文心大模型开源的产业变革密码
  • Java-ThreadLocal
  • java基础(day07)
  • 打开xmind文件出现黑色
  • 【LeetCode 热题 100】94. 二叉树的中序遍历——DFS
  • 13.计算 Python 字符串的字节大小
  • SpringMVC2
  • 鸿蒙开发NDK之---- 如何将ArkTs的类型转化成C++对应的类型(基础类型,包含部分代码解释)