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

【Linux网络编程】套接字编程

目录

一、端口号 (port)

二、认识TCP/Udp协议

1)连接性解释

2)可靠性解释

3)面向数据报/字节流解释

三、网络字节序列

四、struct sockaddr类型介绍

五、TCP 通信API

1)socket()解释

2) bind()解释

2.1 setsockopt()函数

3)listen( )解释

4)accept( )解释

5)connect( )解释

6)tcp读写

7)Udp通信API


一、端口号 (port)

1)port、套接字概念

      端口号是一个 2 字节 16位 的整数
      网络通信的本质不同主机上的两个进程进行间通信,并且两进程会看到同一块资源——网络。并且我们用ip是用于表示互联网中不同主机的地址;端口号(port) 这是用于标识一台主机上的不同进程。所以 ip + port 既可以用于标识互联网中的唯一进程,我们也将 ip + port 称为套接字!!

2)端口号 vs 进程id
      端口号用于标识同一台主机上进程的唯一性,但进程id作用同样如此。那为啥在网络中不复用进程id知识,而是引入端口号呢?

      1、其一是为了让网络模块和系统模块进行接藕,减低两者间的耦合度!
      2、其二是并不是所有的进程都有通信的需求。而port专用于网络通信!

3)端口号和进程关系
      一个进程可以绑定多个端口号,但一个端口号不能被多个进程绑定!

二、认识TCP/Udp协议

我们先对TCP和UDP有一个大概的认识,在后面再详细讲解它的协议内容

TCP协议:

  • 传输层协议
  • 有连接
  • 可靠传输
  • 面向字节流

UDP协议:

  • 传输层协议
  • 没有连接
  • 不可靠传输
  • 面向数据报

1)连接性解释

      TCP在通信前需要先建立连接,也就是大名鼎鼎的3次握手,2次挥手;而UDP通信什么都不用提前做。我们可以将 TCP 通信比喻成打电话时,我们在通信前需要先获得对方同意,对方同意接你电话;将 UDP 想象为寄快递,我只需要知道对方地址即可!

2)可靠性解释

 tcp是可靠,Udp不可靠。那生活中我们采用tcp就可以了,为啥需要Udp?

      原因在于 tcp 的可靠性是有代价的(数据丢包,超时重传、数据粘包等问题需要处理),而 udp 认为只要将即数据从传输层发给网络层就认为数据发生成功了,所以 tcp 通信比 udp慢。并且可靠、不可靠描述的是两种协议的特点,并没有谁好谁坏。

      在当前网络环境中,数据丢包的概率极小。
      针对不同的场景,可以选择不同的通信方式。如果对数据可靠性要求高的场景,我们可以采用tcp,比如支付过程。反之采用 udp 协议,在满足需求的前提下,大大提高通信速度。比如直播,偶尔出现数据丢包,对我们影响不大就可以采用udp协议!

3)面向数据报/字节流解释

      首先,无论是面向字节流,还是面向数据报,都是在传输层的行为特征

      TCP -> 面向字节流是指数据向流水一样,是没有明显边界的,TCP 协议会将这些数据视为一连串无结构的​​字节流​​。它可能会根据网络情况将多次写入的数据合并成一个大的报文发送出去,也可能将一次写入的大量数据拆分成多个包发送。


      UDP -> 面向数据报是指报文之间是有边界的,即每次系统调用发送的数据,都会被 UDP 协议封装成一个独立的、完整的的数据包(数据报)。这个数据报在传输过程中​​不会被合并或拆分​

      它意味着 UDP 每次接收和发送的都是一个完整的报文单元。这个完整的报文单元(UDP 数据报)会作为整体,经历之后所有网络层的封装和解封装过程。


三、网络字节序列

      在内存中的多字节数据相对于内存地址有大端和小端之分,两台进行网络通信的主机,可能发方采用大端,收方采用小端,此时就会出现发方根据大端的规则去发送数据,而收方是按照小端的规则去解释数据的,这样就会导致收方将数据解释出来的意思并不是发方的本意。

      因此,网络规定:

  • 发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出。

  • 接收主机把从网络上接到的字节依次保存在接受缓冲区中,也是按照内存地址从低到高的顺序保存。

  • 因此,网络数据流的地址应该这样规定**:先发出的数据是低地址,后发出的数据是高地址

  • TCP/IP 协议规定,网络数据流应该采用大端字节序,即低地址高权值位。

  • 不管这台主机是大端机还是小端机,都会按照这个 TCP/IP 规定的 网络字节序 来发送、接收数据。

  • 如果当前发送主机是小端,就需要先将数据转换成大端;否则就忽略,直接发送即可。

      为了使网络程序具有可移植性,使同样的 C 代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做 主机字节序网络字节序 的转换。

      host表示主机,network表示网络。所以前两个是将主机字节序转为网络字节序

      后两个函数时将网络字节序转为主机字节序


四、struct sockaddr类型介绍

      sockt API 是一层抽象的网络编程接口,适用于各种底层网络协议,如 IPv4IPv6,以及 UNIX Domain Socket。然而各种网络协议的地址格式并不一样。

      网络通信时,套接字编程有很多类型,主要有如下3种:

  1. 域间套接字Unix socket:主要用于本主机内部通信。域间套接字通过套接字文件来进行通信,进程可以通过打开这个文件来进行读写操作,从而实现通信。
  2. 网络socket:通过 ip + port来进行网络通信。
  3. 原始socket:原始套接字绕过传输层,直接通过网络层进行通信。主要用于编写一些网络工具。

因为套接字编程有三种,所以一般的想法是,设计出三套不同的套接字编程接口,但是这里为了简化,实际上只设计了一套接字编程接口。既然只设计了一套接口,那就要求不管是哪种套接字编程,都只能调用这一种接口,那就要求参数必须要一样。

      struct sockaddr 就起到这样的作用,它将三种套接字编程的参数类型进行了统一。从下图可以看到,struct sockaddr_in 就是网络套接字的类型,struct sockaddr_un 就是域间套接字的类型,它们的前两字节都存的是套接字类型,所有的套接字编程接口,在内部会去检查类型,然后去执行不同的套接字编程代码。

五、TCP 通信API

      服务器指服务端使用,客户端指客户端使用

1)socket()解释

// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
int socket(int domain, int type, int protocol);

 socket( )打开一个网络通讯端口,如果成功的话,就像open()一样返回一个文件描述符sockfd。应用程序可以像读写文件一样用read/write在网络上收发数据。如果socket( )调用出错则返回-1。


domain(协议家族):即socket()函数采用的网络协议种类,在网络通信中一般选择 AF_INET
type(套接字类型):对于tcp而言,面向字节流,选择 SOCK_STREAM
protocol(协议):通常前面两个参数就明确的通信协议种类,所以一般填 0

2) bind()解释

// 绑定端口号 (TCP/UDP, 服务器) 
int bind(int socket, const struct sockaddr *address,

 bind 函数用于将一个套接字(socket)与特定的 IP地址 和 端口号 关联起来。

(将参数sockfd 和 myaddr 绑定在一起, 使 sockfd 这个用于网络通讯的文件描述符能够监听myaddr 所描述的地址和端口号)

  1、对于 服务端 ip和port 是固定的,但我们一般只绑定 port,而 ip 选择任意地址(即IP地址都可以接受)。

  原因在于一台机器上可能存在多张网卡,即一台主机从多个ip(网卡)读取数据,这些数据都应该交给上层指定端口(port)

  2、但对于 客户端 而言,虽然也需要绑定 ip+port,但不需要显示绑定。

  原因在于客户端程序很多,如果直接由用户显示绑定,可能会导致某些时刻端口号冲突,导致一些程序无法正常启动!所以客户端在首次发送信息时,操作系统会自动绑定。

      简洁 : 服务端不绑定IP,通常绑定0.0.0.0,这意味着接受任意IP。客服端不绑定端口号

      服务端IP绑定通常为,客户端不绑定端口号,让操作系统替我们去决定。

      bind 调用时,如果短时间内重复调用会失败,这和tcp断开连接时会进入TIME_WAIT状态有关。我们只需要通过地址复用即可,具体做法如下:

      int opt = 1; setsockopt(_listensockfd, SOL_SOCKET, SO_REUSEADDR| SO_REUSEPORT, &opt, sizeof(opt)); // 地址复用

2.1 setsockopt()函数
int setsockopt(int sockfd, int level, int option_name, const void *option_value, socklen_t option_len);
  • socockfd:要设置选项的套接字描述符。
  • level:指定了选项所在的协议层级。套接字层选SOL_SOCKET
  • option_name:设置的选项的名称。主要有两选项:SO_REUSEADDR允许地址和端口的复用;SO_REUSEPORT 与 SO_REUSEADDR 类似,但提供了更细粒度的控制。
  • option_value需要设置的选项值。
  • option_len:option_value指针指向的变量长度。

3)listen( )解释

// 开始监听socket (TCP, 服务器)
int listen(int socket, int backlog);

      tcp在通信前需要先建立连接,但 服务端 如何得知 客户端 发起了请求开始建立连接呢?所以我们需要通过 listen( ) 函数将套接字设置为监听状态!!

      listen( ) 声明 sockfd 处于监听状态, 并且最多允许有backlog个客户端处于连接等待状态, 如果接收到更多的连接请求就忽略。

      listen()成功返回0,失败返回 -1 ;

      sockfd 上面提到过,就是socket( )函数创建的套接字文件描述符的缩写,是一个整数

4)accept( )解释

// 接收请求 (TCP, 服务器)
int accept(int socket, struct sockaddr* address, socklen_t* address_len);

      三次握手完成后,服务器调用accept( )接受连接,并返回一个新的文件描述符!

      如果服务器调用accept( )时还没有客户端的连接请求,就阻塞等待直到有客户端连接上来。   

      address是一个传出参数,accept( )返回时传出客户端的地址和端口号;

      如果给address 参数传NULL,表示不关心客户端的地址。

如何理解返回一个新的文件描述符:

      通过listen()将套接字设置为监听状态,我们可以把监听套接字理解为饭店外进行拉客的工作人员!他的工作只是将客人拉到字节饭店即可,并不真正提高服务;而是重新叫一名服务员进行招待后,出去重新拉客。
      所以监听套接字就好比拉客的工作人员,他只是用于监听等待客户端发起连接。  

      而返回的新的文件描述符才是真正和客户端进行交互的。

      后续客户端和服务端进行网络通信,都是通过新的文件描述符来进行!!

5)connect( )解释

// 建立连接 (TCP, 客户端)
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);// 绑定端口号 (TCP/UDP, 服务器) 
int bind(int socket, const struct sockaddr *address, socklen_t address_len);

      客户端需要调用connect( )连接服务器;

      connect 和 bind 的参数形式一致, 区别在于 bind 的参数是本地的IP地址, 而 connect 的参数是对方的IP地址!!
      connect( )成功返回0,出错返回-1。

6)tcp读写

 tcp的 客户端 和 服务端 通信和文件一样,通过read、write进行!

7)Udp通信API

 UDp只需要将建 socket 文件文件描述符(本质是创建文件细节,将网卡文件打开),然后绑定ip+port 即可通信。

 UDP通信消息收发通过recvfrom、sendto完成!

http://www.dtcms.com/a/593169.html

相关文章:

  • 网站怎么做弹出表单网站竞价 英文
  • 电子电气架构 --- 当前技术水平
  • OS 特性之PendSV 异常
  • 跆拳道东莞网站建设触屏版网站开发
  • 在电脑端企业微信打开内置浏览器并调试
  • Seata原理与简单示例
  • LeetCode 420 - 强密码检验器
  • 优化学校网站建设方案下载官方网站app
  • Visual Basic 创建状态栏
  • 网站建设的人才怎么称呼wordpress多语言模板
  • LeetCode 分类刷题:876. 链表的中间结点
  • LeetCode 分类刷题:143. 重排链表
  • 分布式专题——51 ES 深度分页问题及其解决方案详解
  • 2025.11.10 力扣每日一题
  • 麻城网站开发同一网站相同form id
  • dede网站制作wordpress长微博工具
  • 专业定制铸铁T型槽地轨,提供稳定的制造、实验基准线
  • PyCharm如何像其他idea软件跨行选择文本
  • 【场景题】线上接口响应慢,应该如何排查问题?
  • Product Hunt 每日热榜 | 2025-11-10
  • 【智能体(Agent)技术深度解析】从架构到实现细节,核心是实现“感知环境→处理信息→决策行动→影响环境”的闭环
  • 网站的登陆注册页面怎么做做水果网站弄个什么名字
  • Advisor与@Aspect
  • Java基础——集合进阶6
  • 网站建设湛江分类信息网站如何做排名
  • 二十七、通信接口
  • 个人网站备案条件个人怎么做网页
  • SQL 相关子查询:性能杀手及其优化方法
  • 一文掌握UI自动化测试
  • 金融保险银行营销AI数字化转型培训讲师培训老师唐兴通讲金融银保团队险年金险市场销售