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

linux系统中网络编程的实现

目录

一、网络编程基本介绍

OSI参考模型及TCP/IP参考模型

1、OSI参考模型(Open Systems Interconnection Model)

📊 OSI七层结构:

🧭 功能总结:

2、TCP/IP参考模型

📊 TCP/IP四层结构:

3、OSI与TCP/IP模型的对比

4、层次关系图示 🧩

TCP协议

1、TCP概述

✅ TCP的主要特征

2、TCP的可靠性机制

1️⃣ 序列号(Sequence Number)

2️⃣ 确认应答与重传机制(ACK + Retransmission)

3️⃣ 滑动窗口(Sliding Window)

3、TCP连接的建立——三次握手(Three-Way Handshake)

🔁 三次握手过程:

⚙️ 三次握手示意图:

4、TCP首部格式(TCP报文段结构)

5、TCP的总结与应用场景

UDP协议

1、UDP概述

✅ UDP的主要特征

2、UDP的通信方式

通信模式:

3、UDP的工作原理

4、UDP报文格式(UDP首部结构)

5、UDP的优缺点

6、UDP的典型应用场景

7、TCP vs UDP 对比总结

协议的选择

1、基本概念回顾

2、TCP 与 UDP 的三大核心区别

1️⃣ 数据可靠性要求

2️⃣ 应用的实时性

3️⃣ 网络可靠性与环境适应性

3、其他常见区别(补充对比)

4、总结口诀 🧠

5、典型应用举例对比

二、网络编程相关概念

IP地址

1、IP地址的基本概念

✅ 网络通信的基本原理:

2、IPv4地址的表示方式

1️⃣ IPv4地址结构

2️⃣ IP地址的组成

3、IP地址的分类(传统分类法)

4、特殊IP地址

🔸 1️⃣ 回环地址(Loopback Address)

🔸 2️⃣ 私有地址(Private IP)

🔸 3️⃣ 广播地址(Broadcast Address)

5、子网掩码(Subnet Mask)

🧩 子网掩码的作用:

🔢 子网掩码的表示规则:

6、DNS与IP的关系

7、重点总结表

8、总结口诀 🧠 

IPV4和IPV6

1、基本概念

2、IPv4 的特点

3、IPv6 的诞生与特点

IPv6 的主要特征:

4、IPv4 与 IPv6 的详细对比

5、IPv6 的优势总结

6、IPv4 与 IPv6 地址表示示例

7、IPv6 的过渡与兼容

8、总结口诀 🧠

端口号

1、端口号的基本定义

2、端口号的作用

3、端口号的范围与分类

4、常见的系统端口号(0~1023)

5、用户自定义端口(>1024)

6、端口号与通信示意

7、端口号的使用规则与注意事项

8、总结口诀 🧠

9、常见举例总结表

socket

1、什么是 Socket(套接字)

✅ Socket 的本质

2、Socket 的作用

3、Socket 通信方式分类

4、① 流式 Socket(Stream Socket)

🌍 对应协议:TCP

✅ 特点:

📄 示例结构(TCP Socket):

5、② 数据报 Socket(Datagram Socket)

🌍 对应协议:UDP

✅ 特点:

📄 示例结构(UDP Socket):

6、Socket 通信模型示意图

7、Socket 通信流程对比总结

8、总结口诀 🧠

linux网络相关的命令

1、系统网络连接前提

2、网络连通性测试命令

3、防火墙管理命令(Ubuntu)

4、常用网络状态查看命令

5、练习案例(虚拟机互联)

6、注意事项

7、总结口诀 🧠

三、TCP网络编程

相关API函数的介绍

socket() ------ 建立网络通信的通道

1.头文件

2.函数原型

3.函数参数

4.返回值

5.函数功能

6.示例代码

bind() ------ 绑定函数

1.头文件

2.函数原型

3.函数参数

4.返回值

5.函数功能

6.常见错误与解决办法

7.示例代码

listen() ------ 监听函数

1.头文件

2.函数原型

3.函数参数

4.返回值、

5.函数功能

6.示例代码

accept() ------ 接收客户端连接请求 

1.头文件

2.函数原型

3.函数参数

4.返回值

5.函数功能

6.示例代码

recv() ------ 接收函数

1.头文件

2.函数原型

3.函数参数

4.返回值

5.函数功能

6.示例代码

send() ------ 发送函数

1.头文件

2.函数原型

3.函数参数

4.返回值

5.函数功能

6.示例代码

connect() ------ 连接函数

1.头文件

2.函数原型

3.函数参数

4.返回值

5.函数功能

6.示例代码

TCP实例:

题目:TCP 网络通信程序设计(基于 socket 的 C/S 模型)

要求:

主要步骤:

使用方法:

补充:ip地址的选择

代码:

四、UDP网络编程

UDP框架

⭐ UDP 的特点:

UDP 服务器端流程

UDP 客户端流程

UDP相关函数

sendto() ------ 发送信息

1.头文件

2.函数原型

3.函数参数

4.返回值

5.函数功能

6.示例代码

recvfrom() ------ 接收信息

1.头文件

2.函数原型

3.函数参数

4.返回值

5.函数功能

6.示例代码

UDP实例


一、网络编程基本介绍

OSI参考模型及TCP/IP参考模型

1、OSI参考模型(Open Systems Interconnection Model)

OSI参考模型 是由 ISO(国际标准化组织) 提出的开放式系统互连模型,用于指导网络通信体系结构的设计。它将网络通信过程划分为 七个层次

📊 OSI七层结构:
层次名称功能常见设备/协议
第7层应用层(Application)为用户提供网络服务接口HTTP、FTP、SMTP、DNS
第6层表示层(Presentation)数据格式转换、加密、压缩JPEG、MP3、SSL
第5层会话层(Session)建立、管理和终止会话RPC、NetBIOS
第4层传输层(Transport)端到端的数据传输、差错控制TCP、UDP
第3层网络层(Network)路由选择与逻辑寻址IP、ICMP、IPX
第2层数据链路层(Data Link)成帧、差错检测、物理寻址MAC、PPP、以太网交换机
第1层物理层(Physical)比特流传输、定义物理介质网线、集线器、光纤
🧭 功能总结:
  • 上三层(应用层、表示层、会话层):面向用户的服务。

  • 下四层(传输层、网络层、数据链路层、物理层):面向数据传输的服务。


2、TCP/IP参考模型

TCP/IP参考模型 是互联网采用的事实标准模型,由 美国国防部(DoD) 提出,也称 DoD模型
它比OSI模型更实际、更简单,仅分为 四层

📊 TCP/IP四层结构:
层次名称对应OSI层功能常见协议
第4层应用层应用层 + 表示层 + 会话层提供用户服务HTTP、FTP、SMTP、DNS
第3层传输层传输层端到端通信TCP、UDP
第2层网络层(网际层)网络层IP寻址与路由IP、ICMP、ARP
第1层网络接口层(链路层)数据链路层 + 物理层物理传输Ethernet、PPP、Wi-Fi

🌐 TCP/IP协议族各层作用(重点整理)

TCP/IP协议族由四层组成,每一层都有明确的功能分工与对应协议。


1️⃣ 网络接口层(Network Interface Layer)

作用:

  • 负责在 物理网络上传输数据,实现主机与物理介质之间的通信。

  • 将上层传下来的 IP数据报 封装成 帧(Frame),并转换为 比特流(0和1) 在物理介质上传输。

  • 接收方则执行相反操作:比特流 → 帧 → 数据报。

关键功能:

  • 成帧、差错检测(如CRC校验)

  • 确定数据在局域网内的传输方式(MAC寻址)

  • 控制物理传输介质(网线、光纤、Wi-Fi等)

常见协议/设备:
Ethernet(以太网)、Wi-Fi(802.11)、PPP、ARP、RARP、交换机、网卡等。

🧠 记忆提示:

“帧”在这一层产生——负责数据帧的发送与接收


2️⃣ 网络层(Internet Layer)

作用:

  • 负责将数据帧封装成IP数据报(Packet)

  • 负责在不同网络之间**选择最佳路径(路由)**进行转发。

  • 实现**逻辑寻址(IP地址)**与网络间互连。

关键功能:

  • 路由选择与转发

  • 分片与重组(Packet Fragmentation/Reassembly)

  • IP寻址与逻辑网络划分(子网)

  • 差错检测与控制(ICMP)

常见协议:
IP(Internet Protocol)、ICMP、IGMP、ARP、RARP等。

🧠 记忆提示:

网络层决定“怎么走、走哪条路”,即路由选择与IP封装


3️⃣ 传输层(Transport Layer)

作用:

  • 负责端到端通信(主机之间的进程通信)。

  • 建立、维持和终止通信会话。

  • 提供可靠传输(TCP)非可靠传输(UDP)

  • 确定通信方式:面向连接 or 无连接。

关键功能:

  • 分段与重组(Segment)

  • 端口号寻址(区分不同进程)

  • 差错检测与重传控制(TCP)

  • 流量控制与拥塞控制(TCP)

常见协议:
TCP(Transmission Control Protocol)、UDP(User Datagram Protocol)

🧠 记忆提示:

“端到端通信靠传输层,端口号识别靠它来。”


4️⃣ 应用层(Application Layer)

作用:

  • 面向用户,为各种网络应用提供服务接口

  • 通过端口号区分不同应用进程,实现进程间通信。

  • 用户通过这一层使用网络(浏览网页、收发邮件、聊天等)。

关键功能:

  • 提供特定网络服务(文件传输、邮件、网页访问等)

  • 定义数据格式与交换方式

  • 处理应用程序之间的通信

常见协议:
HTTP(网页)、FTP(文件传输)、SMTP/POP3(邮件)、DNS(域名解析)、Telnet、SSH 等。

🧠 记忆提示:

“用户能看到的都是应用层的功劳。”
例如:QQ、微信、浏览器等都运行在应用层,通过端口号区分不同进程。

🌐 TCP/IP 协议族主要协议及注解


1️⃣ 网络接口层(Network Interface Layer)协议

🧩 ARP(Address Resolution Protocol,地址解析协议)

作用:
用于在同一局域网中,通过 IP地址 → 物理地址(MAC) 的转换。
即:主机知道对方IP地址,但不知道其MAC地址时,通过ARP请求获取。

举例:

  • A主机要给B主机发数据包,只知道B的IP。

  • A发送ARP广播请求:“谁是192.168.1.2?”

  • B回复:“我是192.168.1.2,我的MAC是00-1C-B3-xx-xx-xx。”

  • A将此映射关系缓存到ARP表中(ARP Cache)。

关键词: IP到MAC的映射。
应用场景: 局域网通信、交换机转发。


2️⃣ 网络层(Internet Layer)协议

🌍 IP(Internet Protocol,网际协议)

作用:
实现主机间的数据传输与逻辑寻址(IP地址),并负责路由选择
它定义了数据包的基本格式、寻址方式与分片机制。

特点:

  • 无连接(每个数据报独立传输)

  • 不可靠(不保证顺序与完整性)

  • 提供最基础的“尽力而为”传输服务

关键任务:
寻址(IP地址分配)、路由(选择路径)。

常见版本: IPv4、IPv6


🚦 MPLS(Multi-Protocol Label Switching,多协议标签交换)

作用:
一种高速网络传输机制,结合了“电路交换的快速”和“分组交换的灵活”的优点。
通过为每个数据包分配一个简短的标签(Label),实现快速转发而非复杂的路由查表。

特点:

  • 高效转发,减少路由器负载

  • 支持多种网络协议(故称“多协议”)

  • 应用于骨干网、VPN、QoS保障等场景

发展状态:
仍在持续发展中,是**下一代网络(NGN)**的重要基础技术。

🧠 记忆提示:

MPLS 是“网络高速公路”的交通标签系统。


3️⃣ 传输层(Transport Layer)协议

🔒 TCP(Transmission Control Protocol,传输控制协议)

作用:
为应用层提供 可靠的、面向连接的 数据传输服务。
在通信前需建立连接(三次握手),传输过程中进行确认、重传与流量控制。

特点:

  • 面向连接(Connection-Oriented)

  • 可靠传输(有确认应答、超时重传)

  • 数据有序到达(序列号控制)

  • 适合传输大批量、可靠性要求高的数据

应用场景:
网页浏览(HTTP/HTTPS)、文件传输(FTP)、电子邮件(SMTP)等。

🧠 记忆提示:

“慢而稳”——TCP 可靠但开销大。


UDP(User Datagram Protocol,用户数据报协议)

作用:
提供无连接、不可靠的通信服务。
它不建立连接,也不确认是否成功接收,因此速度快、效率高。

特点:

  • 无连接(Connectionless)

  • 不保证数据到达(无确认机制)

  • 数据开销小、实时性高

适用场景:
视频会议、语音通话、网络直播、在线游戏等。

🧠 记忆提示:

“快而轻”——UDP 快但不保证到达。


3、OSI与TCP/IP模型的对比

对比项OSI模型TCP/IP模型
层数7层4层
提出机构ISO美国国防部(DoD)
是否理论化理论模型实际模型
应用范围教学、研究实际互联网架构
层间对应应用层/表示层/会话层 → 应用层;传输层 → 传输层;网络层 → 网际层;数据链路+物理层 → 网络接口层

4、层次关系图示 🧩

TCP协议

1、TCP概述

TCP(Transmission Control Protocol,传输控制协议)
面向连接的、可靠的、全双工 的传输层协议。
它在通信的两端建立“虚拟连接”,保证数据能够正确、有序、完整地到达目标主机。


✅ TCP的主要特征
特征说明
面向连接通信前必须建立连接(三次握手),通信后释放连接(四次挥手)。
可靠传输通过确认应答、重传、序列号等机制保证数据不丢失、不重复。
全双工通信双方可同时发送与接收数据。
面向字节流数据在TCP中被看作连续的字节流,而非独立的报文。

2、TCP的可靠性机制

TCP通过以下几种机制保证 端到端通信的可靠性:

1️⃣ 序列号(Sequence Number)
  • 每个TCP报文段都会附带一个 序列号(Sequence Number)

  • 序列号标识了该报文段中第一个字节的编号

  • 接收方依据序列号判断数据的顺序,保证数据 按序组装

🧠 例:
发送方分三次发送数据序号 1–100、101–200、201–300;
接收方收到后按序重新组装成完整数据流。


2️⃣ 确认应答与重传机制(ACK + Retransmission)
  • 接收方每成功接收一个报文段,会发送 ACK确认报文

  • 若发送方在规定时间内未收到ACK,就会 自动重传 该数据包。

  • 这确保了数据不会因为网络故障而丢失。

🧠 例:

A → B 发送 Seq=100;
若 B 未返回 ACK=101,则 A 超时重发该包。


3️⃣ 滑动窗口(Sliding Window)
  • 用于流量控制,防止发送方发送过快导致接收方缓存溢出。

  • 发送方根据接收方通告的“窗口大小”来控制发送速率。

  • 窗口可以动态调整,使传输效率更高。

🧠 例:

若接收方窗口大小 = 5000 字节,则发送方最多可连续发送 5000 字节数据而不必等待确认。


3、TCP连接的建立——三次握手(Three-Way Handshake)

为了建立一个可靠的连接,TCP 使用 三次握手(Three-Way Handshake) 来同步双方的通信状态。


🔁 三次握手过程:
次数发送方(A)接收方(B)说明
第一次握手A → B:发送连接请求(SYN=1, Seq=x)告诉B要建立连接,并发送序列号x
第二次握手B → A:确认连接(SYN=1, ACK=1, Seq=y, Ack=x+1)A收到确认B同意建立连接,同时发送自己的序列号y
第三次握手A → B:发送确认(ACK=1, Seq=x+1, Ack=y+1)B收到确认A确认连接成功,双方建立通信通道

🧠 目的:

  • 双方确认彼此的 接收与发送能力正常

  • 保证双方序列号与确认号 同步


⚙️ 三次握手示意图:
 

🔸 建立后双方即可开始数据传输(全双工)。


4、TCP首部格式(TCP报文段结构)

每个TCP报文段都包含一个固定的 20字节首部(可变部分可增加选项)。

字段长度作用
源端口号(Source Port)16位标识发送进程
目的端口号(Destination Port)16位标识接收进程
序列号(Sequence Number)32位数据流中第一个字节的编号
确认号(Acknowledgment Number)32位下一个期望接收的字节序号
首部长度(Header Length)4位TCP首部占多少个32位字(即4字节)
标志位(Flags)6~9位控制连接状态(如SYN, ACK, FIN等)
窗口大小(Window Size)16位指明接收方可接收的数据量
校验和(Checksum)16位检测数据传输中的错误
紧急指针(Urgent Pointer)16位指示紧急数据的位置
选项(Options)可变长如MSS、窗口扩大因子、时间戳等

🧠 重点记忆字段:
端口号、序列号、确认号、校验和、滑动窗口。


5、TCP的总结与应用场景

项目内容
协议类型面向连接、可靠传输
传输方向全双工
主要机制序列号、确认应答、重传、滑动窗口
优点可靠性高、顺序传输
缺点开销较大、延迟略高
典型应用HTTP/HTTPS、FTP、SMTP、Telnet、SSH 等

UDP协议

1、UDP概述

UDP(User Datagram Protocol,用户数据报协议)
是一种 无连接的、非可靠的、面向数据报的传输层协议
它与TCP同属于传输层协议,但比TCP更简单、更高效。


✅ UDP的主要特征
特征说明
无连接(Connectionless)通信前无需建立连接,发送数据后也无需确认。
不可靠传输不保证数据一定到达、也不保证顺序正确。
面向报文保持应用层数据报的边界,一次发送一次接收。
传输效率高无需握手、无重传机制,开销小、速度快。
一对多通信同一个UDP应用程序可以同时与多个主机通信。

🧠 记忆口诀:

“无连接、少控制、速度快、不可靠” —— 就是UDP。


2、UDP的通信方式

UDP 不像 TCP 那样建立“连接”,它是 直接将数据报(Datagram)发往目标地址和端口

通信模式:
模式说明举例
一对一(单播)一个客户端与一个服务器通信DNS 查询、TFTP
一对多(广播)一个主机向同一局域网内所有主机发送数据DHCP(IP地址分配)
多对多(组播)一组主机同时接收数据IPTV、网络直播

3、UDP的工作原理

UDP 的工作过程非常简单,主要分为两个步骤:

1️⃣ 发送方:
将应用层的数据加上 UDP首部(包含端口号和校验信息) → 交给IP层封装成数据报 → 发送出去。

2️⃣ 接收方:
IP层接收UDP数据报 → 根据端口号交给相应的应用进程。

🧠 说明:
UDP没有连接的概念,因此:

  • 没有三次握手;

  • 没有确认与重传机制;

  • 没有流量控制;

  • 但能实现快速的“尽力而为”传输。


4、UDP报文格式(UDP首部结构)

UDP 报文首部固定为 8字节(64位),结构非常简单。

字段长度说明
源端口号(Source Port)16位标识发送进程
目的端口号(Destination Port)16位标识接收进程
长度(Length)16位整个UDP报文(首部+数据)的长度
校验和(Checksum)16位检测数据在传输中是否出错

📦 UDP报文结构示意图:

🧠 记忆提示:

UDP首部 = 4个字段 × 16位 = 8字节,非常简洁!


5、UDP的优缺点

优点缺点
结构简单、传输速度快不保证可靠性
不需建立连接,节省开销无顺序控制、易丢包
支持一对多通信无流量控制、无重传机制
实时性强(延迟低)数据可能重复或丢失

6、UDP的典型应用场景

UDP 常用于 对实时性要求高、可靠性要求低 的网络应用:

应用场景协议示例特点
视频会议、语音通话RTP、VoIP实时性强,允许少量丢包
网络直播、在线游戏自定义UDP协议速度优先
局域网广播/组播DHCP、SNMP快速分发信息
DNS域名解析DNS请求小、响应快

🧠 例子:

网络视频会议时,如果偶尔丢一帧画面并不会影响整体交流,
因此采用UDP更合适。


7、TCP vs UDP 对比总结

比较项TCPUDP
是否连接面向连接(三次握手)无连接
传输可靠性可靠(有确认、重传、顺序控制)不可靠(尽力而为)
传输方式字节流数据报
传输速度较慢较快
报头大小20字节(以上)8字节
通信方式一对一一对多
典型应用HTTP、FTP、SMTPDNS、视频通话、广播

🧭 一句话总结:

TCP:可靠、慢、有保证
UDP:快速、轻、实时优先

协议的选择

1、基本概念回顾

协议中文名称类型特点
TCP传输控制协议(Transmission Control Protocol)面向连接提供可靠、有序、双向的字节流传输
UDP用户数据报协议(User Datagram Protocol)无连接提供快速、不可靠的报文传输

2、TCP 与 UDP 的三大核心区别


1️⃣ 数据可靠性要求
  • TCP:可靠传输协议

    • 通过 序列号、确认应答(ACK)、超时重传、滑动窗口 等机制,确保数据准确到达、不重复、不丢失

    • 适合对数据正确性要求高的场景。

    📘 举例:

    • 登录验证(用户名、密码)

    • 文件传输(FTP)

    • 邮件发送(SMTP)

🧠 记忆提示:

“数据要准确,选 TCP。”


  • UDP:不可靠传输协议

    • 不提供确认与重传机制,可能出现数据丢失或乱序。

    • 适用于实时性强但对数据准确性要求不高的场景。

    📘 举例:

    • 视频会议

    • 网络语音(VoIP)

    • 实时游戏通信

🧠 记忆提示:

“允许偶尔丢包,选 UDP。”


2️⃣ 应用的实时性
  • TCP:延迟高,实时性较差

    • 在通信前要经过“三次握手”,结束时还有“四次挥手”。

    • 在传输中每个报文都需确认、重传,造成延时大

    • 不适合实时通信(例如语音、直播)。

    📘 举例:

    • 发送消息要确认送达 → 延时明显。


  • UDP:实时性强

    • 无需建立连接,数据直接发送。

    • 没有重传确认机制,延迟低。

    • 适用于对延迟敏感的实时通信场合

    📘 举例:

    • 在线会议、网络直播、网络游戏等。

🧠 记忆提示:

“速度第一,选 UDP;可靠优先,选 TCP。”


3️⃣ 网络可靠性与环境适应性
  • TCP:适合网络不稳定的环境

    • 内置错误检测与重传机制,可在丢包、乱序环境下保持数据可靠。

    • 当网络质量差时仍能保证传输正确性。

    📘 举例:

    • 长距离或跨网段数据传输(如下载、远程控制)


  • UDP:适合网络稳定的环境

    • 无纠错机制,若网络丢包严重则数据可能丢失。

    • 但在良好的网络条件下,UDP更轻量高效,能加快传输速度。

    📘 举例:

    • 局域网游戏、局域网媒体分发

🧠 记忆提示:

“网络差用 TCP,网络好用 UDP。”


3、其他常见区别(补充对比)

对比项目TCPUDP
是否面向连接是(三次握手)
可靠性高(有确认、重传、校验)低(尽力而为)
传输方式字节流(连续数据流)数据报(独立报文)
报头大小20字节以上(复杂)8字节(简单)
传输效率较低(开销大)较高(无握手)
顺序保证有序到达可能乱序
流量控制有滑动窗口控制无流量控制
实时性延迟较高延迟极低
典型应用HTTP、FTP、SMTP、SSHDNS、视频、语音、直播

4、总结口诀 🧠

TCP:重可靠,轻速度 —— 适合重要数据传输
UDP:重速度,轻可靠 —— 适合实时性通信


5、典型应用举例对比

场景推荐协议原因
文件下载 / 登录验证TCP要求数据完整、准确
视频会议 / 网络语音UDP要求实时、延迟低
网页浏览(HTTP)TCP需完整加载内容
网络直播UDP丢少量包不影响播放
邮件发送TCP需保证可靠送达

二、网络编程相关概念

IP地址

1、IP地址的基本概念

IP地址(Internet Protocol Address)
是网络中每台主机或设备的唯一标识符,用于实现网络设备之间的通信。

📘 通俗理解:
IP地址就像“网络中的门牌号”,
计算机之间要通信,必须知道对方的 IP 地址。


✅ 网络通信的基本原理:
  1. 通过 IP 地址 —— 定位到目标设备(主机)。

  2. 通过 端口号(Port) —— 定位到设备上的具体进程或应用程序。

🧠 举例:

访问网页 → 实际上是访问目标服务器的 IP 地址 + 端口号(80 或 443)。


2、IPv4地址的表示方式

1️⃣ IPv4地址结构
  • IPv4 地址长度: 32 位(二进制位),即 4 字节。

  • 表示方法: 采用 点分十进制表示法(Dotted Decimal Notation)

    • 每 8 位(二进制)转换成一个十进制数,中间用“.”分隔。

📘 示例:

十进制表示:192.168.1.1
二进制表示:11000000.10101000.00000001.00000001


2️⃣ IP地址的组成
部分说明
网络号(Network ID)标识网络所属的网段(类似于街区)
主机号(Host ID)标识该网络中的具体主机(类似于门牌号)

同一网络内的主机:

  • 网络号相同

  • 主机号必须唯一


3、IP地址的分类(传统分类法)

IPv4地址被分为 A、B、C、D、E 五类
其中,A、B、C类地址最常用于主机和网络通信。

类别地址范围(十进制)网络号位数主机号位数默认子网掩码用途
A类1.0.0.0 ~ 126.255.255.2558位24位255.0.0.0超大型网络
B类128.0.0.0 ~ 191.255.255.25516位16位255.255.0.0中型网络
C类192.0.0.0 ~ 223.255.255.25524位8位255.255.255.0小型网络
D类224.0.0.0 ~ 239.255.255.255---多播(组播)
E类240.0.0.0 ~ 255.255.255.255---保留实验用途

📘 注意:

  • 127.0.0.0/8 (即127开头的地址)保留为 回环地址

  • 最常见的局域网是 C类地址(如 192.168.x.x)。


4、特殊IP地址

🔸 1️⃣ 回环地址(Loopback Address)
  • 范围:127.0.0.0 ~ 127.255.255.255

  • 常用:127.0.0.1

  • 作用:用于 本机测试本地进程间通信

🧠 特点:

使用回环地址发送的数据不会经过网络,而是直接返回本机。


🔸 2️⃣ 私有地址(Private IP)

用于 局域网内部通信,不能在互联网上直接使用。
(若要访问互联网,需要通过 NAT 转换成公有地址。)

类别地址范围
A类10.0.0.0 ~ 10.255.255.255
B类172.16.0.0 ~ 172.31.255.255
C类192.168.0.0 ~ 192.168.255.255

📘 举例:

家用路由器默认分配的内网地址通常为 192.168.1.x


🔸 3️⃣ 广播地址(Broadcast Address)
  • 表示网络中所有主机的地址。

  • 主机号全部为 1

🧠 举例:

子网 192.168.1.0/24 → 广播地址为 192.168.1.255


5、子网掩码(Subnet Mask)

🧩 子网掩码的作用:
  • 用于从 IP 地址中提取网络号

  • 通过 与运算(AND) 得到网络地址。

📘 例:

IP地址:192.168.1.15
子网掩码:255.255.255.0
二进制与运算结果:192.168.1.0 (即网络地址)


🔢 子网掩码的表示规则:
  • 子网掩码长度:32位

  • 由一串 连续的1(表示网络号)和 连续的0(表示主机号)组成。

网络类别默认掩码网络位主机位
A类255.0.0.08位24位
B类255.255.0.016位16位
C类255.255.255.024位8位

📘 CIDR写法(无分类表示法):

192.168.1.1/24 ← “/24”表示网络位长度(即子网掩码255.255.255.0)


6、DNS与IP的关系

DNS(Domain Name System)
用于将人类容易记忆的“域名”转换为对应的“IP地址”。

🧠 例:

输入网址:www.baidu.com
↓
DNS解析 → 220.181.38.148(服务器IP地址)
↓
浏览器连接到对应的IP服务器

📘 作用:

DNS让用户通过“名字”访问网站,而不是直接记复杂的数字IP。


7、重点总结表

概念说明示例
IP地址网络中设备的唯一标识192.168.1.10
子网掩码区分网络号与主机号255.255.255.0
网关地址出口路由器的IP192.168.1.1
私有IP局域网使用地址192.168.x.x
公有IP互联网使用地址8.8.8.8
回环地址本机通信测试127.0.0.1
广播地址发送给同网段所有主机192.168.1.255

8、总结口诀 🧠 

📘 “IP标设备,掩码定网段;
回环测自己,广播找全班;
私有局域网,公有上外端。”

IPV4和IPV6

1、基本概念

协议全称中文名称位数
IPv4Internet Protocol version 4互联网协议第4版32 位
IPv6Internet Protocol version 6互联网协议第6版128 位

2、IPv4 的特点

  • 使用 32位地址(即 4 个字节)。

  • 理论上可提供 约43亿个地址(2³² ≈ 4.29×10⁹)

  • 由于地址分配不均及保留部分地址,真正可供使用的约 5亿个左右

  • 采用 点分十进制 表示。

📘 示例:

IPv4 地址:192.168.1.1

🧠 缺陷:

随着互联网设备(电脑、手机、物联网设备)数量爆炸增长,IPv4 地址早已不够用。


3、IPv6 的诞生与特点

为了解决 IPv4 地址枯竭的问题,诞生了 IPv6(Internet Protocol version 6)

IPv6 的主要特征:
  • 地址长度:128位(16字节)

    • 理论上可提供:

      👉 2¹²⁸ ≈ 3.4×10³⁸ 个地址

      相当于每平方米可分配约 1000 个地址

  • 地址表示方式:

    • 使用 十六进制表示,每 16 位为一组,共 8组,中间用冒号“::”分隔。

    • 例如:

      2001:0db8:85a3:0000:0000:8a2e:0370:7334
    • 可以省略连续的“0000”:

      2001:db8:85a3::8a2e:370:7334
  • 自动配置功能(无需DHCP)

    • 支持 无状态地址自动配置(SLAAC),主机可自动获取IP地址。

  • 更高的安全性

    • 内置IPSec加密,在协议层支持端到端的数据安全。

  • 改进的报文结构

    • 简化了IPv4的头部格式,提高路由转发效率。

  • 支持组播、多播

    • 更高效的网络通信机制,适用于视频会议、流媒体、物联网等应用。


4、IPv4 与 IPv6 的详细对比

对比项目IPv4IPv6
地址长度32 位128 位
地址数量约 43 亿约 3.4 × 10³⁸
地址表示方式点分十进制(如192.168.1.1)冒号分隔的十六进制(如2001:db8::1)
地址类型单播、广播、多播单播、多播、任播(无广播)
子网划分使用子网掩码使用前缀长度(/64、/48等)
配置方式手动或DHCP分配自动配置(SLAAC)
安全性依赖外部协议(如IPSec可选)内置IPSec支持
路由效率报头复杂、路由表大报头简化、转发速度快
网络层协议ARP、ICMPv4不使用ARP,改为ICMPv6
地址空间耗尽
NAT(网络地址转换)需要不需要
兼容性广泛使用中正在逐步推广

5、IPv6 的优势总结

优势说明
🌍 地址空间巨大彻底解决地址枯竭问题
传输效率高报文头更简洁,路由转发更快
🔒 安全性强原生支持IPSec加密与身份认证
🤖 自动配置设备可自行生成地址,无需人工配置
📡 更好的多媒体支持支持组播,适合视频会议与物联网
🌐 消除NAT限制实现真正的端到端通信

6、IPv4 与 IPv6 地址表示示例

类型IPv4 示例IPv6 示例
家庭内网192.168.1.10fd00::1234:abcd
公网地址8.8.8.8(Google DNS)2001:4860:4860::8888(Google IPv6 DNS)
回环地址127.0.0.1::1
默认路由0.0.0.0::/0

7、IPv6 的过渡与兼容

由于 IPv4 仍被广泛使用,目前网络正处于 IPv4 与 IPv6 共存阶段
常见的过渡技术包括:

技术名称作用
双栈(Dual Stack)同时运行 IPv4 与 IPv6
隧道(Tunneling)将IPv6数据封装在IPv4网络中传输
转换(Translation)IPv4 与 IPv6 地址间的相互转换(如 NAT64)

8、总结口诀 🧠

IPv4 位少快枯竭,
IPv6 位长天地阔;
十六进制冒号连,
自动加密更方便。

端口号

1、端口号的基本定义

端口号(Port Number) 是传输层协议(TCP、UDP)中用来标识主机上不同应用进程的数字编号。

📘 简单理解:

IP地址 → 定位到具体的设备
端口号 → 定位到设备上的具体程序或服务

🧠 举例:

访问一台服务器时,

  • IP地址:找到服务器

  • 端口号:找到具体的服务(如网页、文件传输等)


2、端口号的作用

作用:

在网络通信中,通过端口号来区分不同的进程或服务,确保数据准确地交付给正确的应用程序。

🧩 TCP/IP通信模型中:

  • IP地址负责“找到哪台计算机

  • 端口号负责“找到哪一个程序


3、端口号的范围与分类

端口号为 16位无符号整数,范围为:

🔢 0 ~ 65535

根据使用情况,端口号分为以下三类:

分类范围说明
系统端口(知名端口)0 ~ 1023系统或特定应用程序使用(固定分配)
注册端口(用户常用)1024 ~ 49151用户进程或注册服务使用,可分配但需登记
动态/私有端口49152 ~ 65535临时通信时由系统动态分配(客户端常用)

4、常见的系统端口号(0~1023)

服务名称协议端口号作用说明
HTTPTCP80网页访问服务
HTTPSTCP443加密网页访问(安全HTTP)
FTPTCP21文件传输协议控制连接
SSHTCP22安全远程登录
TELNETTCP23远程终端连接
SMTPTCP25邮件发送服务
POP3TCP110邮件接收服务
DNSUDP/TCP53域名解析服务
SNMPUDP161网络管理协议
NTPUDP123网络时间同步协议

5、用户自定义端口(>1024)

  • 用户或应用程序可以自定义使用 1024 以上的端口。

  • 一般用于:

    • 数据库服务(如 MySQL:3306)

    • 游戏服务器

    • 局域网通信

    • 临时客户端连接(如网页浏览器)

📘 示例:

服务协议端口号说明
MySQLTCP3306数据库服务
SQL ServerTCP1433微软数据库服务
RedisTCP6379内存数据库
TomcatTCP8080Web服务(开发常用)

6、端口号与通信示意

一个完整的网络通信需要四个要素(即 套接字 Socket):

要素示例说明
源IP地址192.168.1.10客户端主机
源端口号50123客户端程序临时分配
目的IP地址172.16.0.5服务器主机
目的端口号80Web服务端口

🧠 理解:

浏览器访问网页时:
浏览器(客户端)用随机端口访问服务器(80端口),
服务器收到请求后,根据端口号知道应由“HTTP服务”处理该请求。


7、端口号的使用规则与注意事项

  • 同一台主机中,端口号不能重复使用。

    • 同一协议(TCP或UDP)下的端口唯一。

  • 不同协议的端口号可以相同。

    • 例如:TCP 80 与 UDP 80 可以同时存在。

  • 系统端口需管理员权限才能使用(0~1023)。

  • 防火墙可通过端口号限制访问。

    • 例如:关闭80端口可阻止网页访问。


8、总结口诀 🧠

IP 定位主机,端口定位程序;
0到1023系统留,用户用大号自定义。


9、常见举例总结表

协议/服务使用端口传输层协议备注
HTTP80TCP网页访问
HTTPS443TCP加密网页
FTP21TCP文件传输
SSH22TCP安全远程登录
DNS53UDP/TCP域名解析
DHCP67/68UDP自动分配IP
SMTP25TCP邮件发送
POP3110TCP邮件接收
MySQL3306TCP数据库
Tomcat8080TCPWeb应用开发

socket

1、什么是 Socket(套接字)

Socket(套接字) 是网络通信中最重要的一种编程接口。
它是对网络通信的抽象封装,是 应用层与传输层之间的桥梁

📘 通俗理解:

Socket 就像一根“网络插头”,
程序通过插上这个插头(socket),就能在网络上收发数据。


✅ Socket 的本质
  • 是一种 特殊的 I/O 接口

  • 在 Linux 中,一切皆文件,因此 Socket 也有一个 文件描述符(file descriptor)

  • 程序通过 读写 Socket 文件描述符 来进行网络通信,就像操作普通文件一样。


2、Socket 的作用

  • 实现 进程间通信(IPC:Inter-Process Communication)。

  • 可用于:

    • 本地通信(同一主机上的不同进程)

    • 网络通信(不同主机之间)

📘 总结一句话:

Socket 是实现“主机 ↔ 主机”或“进程 ↔ 进程”通信的桥梁。


3、Socket 通信方式分类

在 Linux 网络编程中,常见的 Socket 类型主要有两种:

类型名称对应协议特点应用场景
流式套接字(SOCK_STREAM)流方式 SocketTCP面向连接、可靠传输、数据有序文件传输、网页通信
数据报套接字(SOCK_DGRAM)数据报方式 SocketUDP无连接、不可靠传输、数据无序视频会议、语音通话

4、① 流式 Socket(Stream Socket)

🌍 对应协议:TCP

流式 Socket 提供一种 可靠的、面向连接的、双向字节流 通信方式。

✅ 特点:
  • 面向连接(Connection-Oriented)

    • 通信前必须建立连接(三次握手)。

  • 数据可靠传输

    • 采用 TCP 协议,保证数据无差错、不丢失、不重复。

  • 顺序传输

    • 数据按发送顺序到达接收方。

  • 双向通信(Full Duplex)

    • 双方可以同时发送与接收数据。

📘 适用场景:

  • Web服务器(HTTP)

  • 文件传输(FTP)

  • 邮件服务(SMTP)


📄 示例结构(TCP Socket):
// TCP服务器端流程
socket() → bind() → listen() → accept() → recv()/send() → close()// TCP客户端流程
socket() → connect() → send()/recv() → close()


5、② 数据报 Socket(Datagram Socket)

🌍 对应协议:UDP

数据报 Socket 提供一种 无连接的、面向报文的通信方式

✅ 特点:
  • 无连接(Connectionless)

    • 通信前无需建立连接。

  • 不可靠传输

    • 数据可能丢失或乱序,应用层需自行处理。

  • 报文独立传输

    • 每个报文是独立的,不存在“流”的概念。

  • 传输速度快,延迟低

📘 适用场景:

  • 网络语音(VoIP)

  • 视频会议

  • 实时游戏

  • 局域网广播通信


📄 示例结构(UDP Socket):
// UDP服务器端流程
socket() → bind() → recvfrom()/sendto() → close()// UDP客户端流程
socket() → sendto()/recvfrom() → close()


6、Socket 通信模型示意图

TCP(流式套接字)┌──────────────────┐                 ┌──────────────────┐│    客户端程序     │ <───────►──────►│    服务器程序     ││  socket()        │                 │  socket()        ││  connect()       │                 │  accept()        ││  send() / recv() │ ◄──────────────►│  recv() / send() │└──────────────────┘                 └──────────────────┘UDP(数据报套接字)┌──────────────────┐                 ┌──────────────────┐│    客户端程序     │ <───────►──────►│    服务器程序     ││  sendto()        │                 │  recvfrom()      ││  recvfrom()      │ ◄──────────────►│  sendto()        │└──────────────────┘                 └──────────────────┘

🌐 TCP(流式套接字)

  • 特点
    TCP 是一种 面向连接可靠传输 的通信方式。
    在通信前,客户端与服务器必须先建立连接,通信结束后再断开连接。

  • 流程说明

    1. 客户端 调用 socket() 创建套接字,然后用 connect() 向服务器发起连接请求。

    2. 服务器 创建套接字后,通过 accept() 接收连接请求。

    3. 双方连接建立后,使用 send()recv() 进行数据收发。

    4. 通信完成后,双方关闭套接字。

📌 关键特征:数据是连续的“流”,传输可靠但效率较低。


📡 UDP(数据报套接字)

  • 特点
    UDP 是一种 无连接不可靠传输 的通信方式。
    发送数据时不需要建立连接,速度快但可能丢包。

  • 流程说明

    1. 客户端 直接通过 sendto() 向服务器发送数据报。

    2. 服务器 使用 recvfrom() 接收数据,同时获取发送方地址。

    3. 若需要回应,服务器再用 sendto() 向客户端发送数据。

📌 关键特征:以独立“数据报”为单位传输,效率高但不保证可靠性。


7、Socket 通信流程对比总结

步骤TCP(SOCK_STREAM)UDP(SOCK_DGRAM)
是否建立连接是(三次握手)
数据传输方式字节流(stream)报文(datagram)
是否可靠可靠(有确认、重传)不可靠(可能丢包)
顺序性有序无序
速度较慢(开销大)较快(轻量)
应用场景文件传输、Web通信视频、语音、实时数据
典型函数socket(), connect(), send(), recv()socket(), sendto(), recvfrom()

8、总结口诀 🧠

💬 “流式连得稳,数据报传得快;
TCP保顺序,UDP抢时间。”

linux网络相关的命令

1、系统网络连接前提

  • 操作系统:Ubuntu / Linux 系统

  • 前提:确保网络已连接,可以上网。

  • 提示

    • Ubuntu 系统下使用 ifconfigip addr 查看网络状态

    • Windows 下使用 ipconfig 查看 IP 地址


2、网络连通性测试命令

1️⃣ ping 命令

作用:

  • 测试主机与目标主机之间的网络连通性

  • 可检测 网络延迟(RTT)和 丢包率

基本用法:

ping <IP地址或域名>

示例:

ping www.baidu.com       # 测试访问百度网站是否通
ping 192.168.1.101      # 测试同一局域网内主机是否通

注意事项:

  • 同一局域网内测试 IP 时,如果 ping 不通:

    • 确认目标主机 IP 正确

    • 检查本机和目标主机防火墙状态

    • 关闭防火墙或允许 ICMP(Ping)通信


3、防火墙管理命令(Ubuntu)

Ubuntu 默认防火墙为 UFW(Uncomplicated Firewall)

操作命令说明
查询防火墙状态sudo ufw status查看防火墙是否启用
开启防火墙sudo ufw enable启用防火墙保护
关闭防火墙sudo ufw disable关闭防火墙,允许所有连接

提示:

  • Ping 命令依赖 ICMP 协议,如果防火墙阻止 ICMP,Ping 会失败

  • 在 Ubuntu 虚拟机之间测试连通性时,可能需要关闭防火墙

  • Windows 防火墙也可能影响互通,需要根据实验要求关闭


4、常用网络状态查看命令

命令作用示例
ifconfig查看网络接口信息(IP、子网掩码、网关)ifconfig
ip addr查看 IP 地址和网络接口ip addr show
netstat -rn查看路由表netstat -rn
route -n查看路由信息route -n
ping测试主机连通性ping www.baidu.com
traceroute跟踪数据包路由traceroute www.baidu.com

5、练习案例(虚拟机互联)

1.启动两个 Ubuntu 虚拟机,确保它们在同一网络(同一网段)。

2.使用 ifconfigip addr 获取 IP 地址。

3.关闭防火墙:

sudo ufw disable

4.使用 ping 测试互通:

ping 192.168.1.xxx

5.成功收到响应,即表明虚拟机互联成功。


6、注意事项

1.同一局域网测试时,确保 网关、子网掩码、IP 不冲突

2.Ping 不通时,可逐步检查:

  • IP 是否正确

  • 防火墙是否开启

  • 虚拟机网络配置(桥接、NAT)

3.Windows 系统 Ping Linux 时,也需关闭 Windows 防火墙或允许 ICMP。


7、总结口诀 🧠

“Ping 测连通,防火墙挡路;
IP、掩码、网关对齐,虚拟机互通顺畅。”

三、TCP网络编程

相关API函数的介绍

socket() ------ 建立网络通信的通道

1.头文件
#include <sys/types.h>
#include <sys/socket.h>
2.函数原型
int socket(int domain, int type, int protocol);
3.函数参数
参数说明常用值
domain指定协议族(Address Family)AF_INET(IPv4)AF_INET6(IPv6)
type套接字类型SOCK_STREAM(TCP/流式)SOCK_DGRAM(UDP/数据报)
protocol指定具体协议,通常填 00 表示根据 type 自动选择 TCP 或 UDP
4.返回值
返回值说明
≥0成功,返回一个 文件描述符(fd),用于后续读写操作
-1出错,失败,通常设置 errno,可用 perror() 查看错误原因
5.函数功能
  • 功能:创建一个 套接字(Socket),作为应用程序和网络通信的端点

  • 用途

    • 用于后续 bind()/connect()/send()/recv() 等操作

    • 可以在本地进程间通信或跨网络通信

6.示例代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>int main() {int sockfd;// 创建TCP套接字sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0) {perror("socket创建失败");return -1;}printf("socket创建成功,文件描述符 = %d\n", sockfd);return 0;
}

现象:

bind() ------ 绑定函数

1.头文件
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>   // sockaddr_in结构体
2.函数原型
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
3.函数参数
参数说明
sockfdsocket() 返回的套接字文件描述符
addr指向 本地地址结构 的指针(如 struct sockaddr_in),指定 IP 和端口号
addrlen地址结构体长度,一般用 sizeof(struct sockaddr_in)

1️⃣ 通用地址结构(IPv6 可用)

struct sockaddr {unsigned short int sa_family; // 地址族char sa_data[14];             // 地址数据
};
字段名类型含义说明
sa_familyunsigned short int地址族(Address Family)指明使用哪种通信协议,如:AF_INET(IPv4)、AF_INET6(IPv6)、AF_UNIX(本地通信)
sa_datachar[14]地址数据区保存具体的地址和端口信息(实际含义取决于地址族)

2️⃣ IPv4 地址结构

struct sockaddr_in {unsigned short int sin_family;  // 地址族 AF_INETuint16_t sin_port;              // 端口号 (使用 htons() 转换)struct in_addr sin_addr;        // IP 地址unsigned char sin_zero[8];      // 填充位
};
成员名称类型说明示例
sin_familyunsigned short int地址族(Address Family)IPv4 通常设置为 AF_INETseraddr.sin_family = AF_INET;
sin_portuint16_t端口号(Port Number)⚠️ 必须使用 htons() 转换为网络字节序seraddr.sin_port = htons(8080);
sin_addrstruct in_addrIP 地址信息,内部成员 s_addr 存储 32 位 IPv4 地址seraddr.sin_addr.s_addr = inet_addr("192.168.1.10");
sin_zero[8]unsigned char[8]保留字段(填充用,使结构体大小与 sockaddr 一致)通常清零即可bzero(seraddr.sin_zero, 8);

3️⃣ IPv4 地址成员结构

struct in_addr {uint32_t s_addr; // 存放IP地址 (网络字节序)
};

4.返回值
返回值说明
0绑定成功
-1绑定失败,设置 errno 可查看错误原因(如端口已占用)
5.函数功能
  • Socket 与本地 IP 地址和端口号绑定

  • 使服务器 Socket 知道 客户端连接请求该发送到哪个端口

  • TCP:必须先 bind()(服务器端)才能 listen()

  • UDP:可选,若不绑定系统会自动分配端口

6.常见错误与解决办法
错误信息原因解决方法
bind: Address already in use端口未完全释放或处于 TIME_WAIT 状态bind() 前调用:setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
Permission denied尝试绑定 0~1023 端口(系统端口)使用普通端口号 >1024
Invalid argument地址结构传递错误或未初始化检查 sockaddr_in 结构赋值是否完整
7.示例代码
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define SERVER_IP "127.0.0.1"   // 定义服务器IP地址为本地回环地址
#define PORT_NUM 5000           // 定义服务器端口号为5000typedef struct sockaddr SA;
typedef struct sockaddr_in SIN;int main() {int sockfd;// 创建TCP套接字sockfd = socket(AF_INET, SOCK_STREAM, 0);   // 创建一个IPv4的TCP套接字,返回套接字描述符sockfdif (sockfd < 0) {perror("socket创建失败");return -1;}// 初始化服务器地址结构:、设置IPv4协议族、端口号(PORT_NUM,网络字节序)和服务器IP地址(SERVER_IP)SIN seraddr;    bzero(&seraddr, sizeof(SIN));            //清零seraddr.sin_family = AF_INET;            // 指定使用IPv4地址族seraddr.sin_port = htons(PORT_NUM);      // 将主机字节序的端口号转换为网络字节序并赋给端口字段seraddr.sin_addr.s_addr = inet_addr(SERVER_IP); // 将字符串形式的服务器IP地址转换为网络字节序并赋给地址字段int ret = bind(sockfd, (SA *)&seraddr, sizeof(SIN));    // 将套接字sockfd与服务器地址结构seraddr绑定if (ret == -1) {perror("bind failed");exit(0);}printf("Bind success! Socket fd = %d\n", sockfd);return 0;}

这段代码演示了一个最基本的 TCP 服务器套接字创建与绑定流程,为后续监听和接收客户端连接打基础。

现象:

listen() ------ 监听函数

1.头文件
#include <sys/types.h>
#include <sys/socket.h>
2.函数原型
int listen(int sockfd, int backlog);
3.函数参数
参数说明
sockfd之前创建并绑定过的套接字文件描述符(socket + bind)
backlog等待队列长度,表示在 accept() 之前可以排队等待的最大连接数
4.返回值、
返回值说明
0成功,将套接字置为监听状态
-1失败(例如套接字未绑定、资源不足等)
5.函数功能
  • 已绑定的 TCP 套接字 转换为 被动监听套接字

  • 告诉操作系统:准备好接受客户端连接请求

  • 客户端的连接请求会排队到套接字的等待队列中,长度由 backlog 决定

6.示例代码
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define SERVER_IP "127.0.0.1"   // 定义服务器IP地址为本地回环地址
#define PORT_NUM 5000           // 定义服务器端口号为5000typedef struct sockaddr SA;
typedef struct sockaddr_in SIN;int main() {int sockfd;int ret;// 创建TCP套接字sockfd = socket(AF_INET, SOCK_STREAM, 0);   // 创建一个IPv4的TCP套接字,返回套接字描述符sockfdif (sockfd < 0) {perror("socket创建失败");return -1;}printf("Socket fd = %d\n", sockfd);// 初始化服务器地址结构:、设置IPv4协议族、端口号(PORT_NUM,网络字节序)和服务器IP地址(SERVER_IP)SIN seraddr;    bzero(&seraddr, sizeof(SIN));            //清零seraddr.sin_family = AF_INET;            // 指定使用IPv4地址族seraddr.sin_port = htons(PORT_NUM);      // 将主机字节序的端口号转换为网络字节序并赋给端口字段seraddr.sin_addr.s_addr = inet_addr(SERVER_IP); // 将字符串形式的服务器IP地址转换为网络字节序并赋给地址字段ret = bind(sockfd, (SA *)&seraddr, sizeof(SIN));    // 将套接字sockfd与服务器地址结构seraddr绑定if (ret == -1) {perror("bind failed");exit(0);}printf("Bind success!");ret = listen(sockfd, 10);    // 设置监听队列长度为 10if(ret == -1) {perror("listen failed");exit(0);}printf("Listen success!");return 0;}

现象:

accept() ------ 接收客户端连接请求 

1.头文件
#include <sys/types.h>
#include <sys/socket.h>
2.函数原型
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
3.函数参数
参数说明
sockfd监听套接字的文件描述符(已 socket + bind + listen)
addr指向 sockaddr 结构的指针,用于存放客户端地址信息
addrlen指向整数的指针,输入时为 addr 的长度,返回时为实际地址长度
4.返回值
返回值说明
>=0成功,返回 新套接字文件描述符,用于与该客户端通信
-1失败(例如套接字未监听或被信号中断)
5.函数功能
  • 阻塞等待客户端连接请求(可改为非阻塞模式)

  • 一旦有客户端连接,就返回 一个新的套接字 用于通信

  • 原来的监听套接字 sockfd 继续用于监听其他客户端

6.示例代码
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define SERVER_IP "127.0.0.1"   // 定义服务器IP地址为本地回环地址
#define PORT_NUM 5000           // 定义服务器端口号为5000typedef struct sockaddr SA;
typedef struct sockaddr_in SIN;int main() {int sockfd;int ret;// 创建TCP套接字sockfd = socket(AF_INET, SOCK_STREAM, 0);   // 创建一个IPv4的TCP套接字,返回套接字描述符sockfdif (sockfd < 0) {perror("socket创建失败");return -1;}printf("Socket fd = %d\n", sockfd);// 初始化服务器地址结构:、设置IPv4协议族、端口号(PORT_NUM,网络字节序)和服务器IP地址(SERVER_IP)SIN seraddr;    bzero(&seraddr, sizeof(SIN));            //清零seraddr.sin_family = AF_INET;            // 指定使用IPv4地址族seraddr.sin_port = htons(PORT_NUM);      // 将主机字节序的端口号转换为网络字节序并赋给端口字段seraddr.sin_addr.s_addr = inet_addr(SERVER_IP); // 将字符串形式的服务器IP地址转换为网络字节序并赋给地址字段ret = bind(sockfd, (SA *)&seraddr, sizeof(SIN));    // 将套接字sockfd与服务器地址结构seraddr绑定if (ret == -1) {perror("bind failed");exit(0);}printf("Bind success!");ret = listen(sockfd, 10);    // 设置监听队列长度为 10if(ret == -1) {perror("listen failed");exit(0);}printf("Listen success!");int clifd;SIN cliaddr;socklen_t addrlen = sizeof(cliaddr);clifd = accept(serfd, (SA*)&cliaddr, &addrlen);if(clifd == -1) {perror("accept failed");exit(0);}printf("客户端已连接,套接字 fd = %d\n", clifd);return 0;}

recv() ------ 接收函数

1.头文件
#include <sys/types.h>
#include <sys/socket.h>
2.函数原型
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
3.函数参数
参数说明
sockfd用于接收数据的套接字文件描述符(accept 或 connect 返回的 fd)
buf指向接收数据缓冲区的指针,例如 char buf[40]
len要接收的最大字节数(buf 的大小)
flags通常填写 0,也可以使用位置参数,如 MSG_DONTWAIT(非阻塞)
4.返回值
返回值说明
>0成功接收到的字节数
0对端关闭连接(客户端或服务器退出/断开)
-1接收失败(网络错误、套接字错误等)
5.函数功能
  • 从指定套接字接收数据,存放到 buf 中。

  • 如果没有数据,默认会 阻塞等待(除非套接字设置为非阻塞)。

  • 用于 TCP 通信 中接收数据,是客户端或服务端收消息的关键函数。

6.示例代码
char buf[1024];
int len = recv(sockfd, buf, sizeof(buf), 0);if (len > 0) {printf("收到数据: %s\n", buf);
} else if (len == 0) {printf("对端关闭连接\n");
} else {perror("recv 失败");
}

send() ------ 发送函数

1.头文件
#include <sys/types.h>
#include <sys/socket.h>
2.函数原型
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
3.函数参数
参数说明
sockfd用于发送数据的套接字文件描述符(accept 或 connect 返回的 fd)
buf存放待发送数据的缓冲区地址
len待发送数据的字节数
flags通常填 0,也可以设置特殊发送选项(如 MSG_DONTWAIT、MSG_NOSIGNAL 等)
4.返回值
返回值说明
>0成功发送的字节数
-1发送失败(套接字错误、网络错误等)
5.函数功能
  • 将数据发送到指定套接字(TCP 或 UDP)。

  • 对 TCP:可靠传输,数据按顺序送到对端。

  • 对 UDP:无连接发送,可能丢包且无确认。

6.示例代码
char buf[] = "Hello TCP";
int len = send(sockfd, buf, strlen(buf), 0);if (len == -1) {perror("send 失败");
} else {printf("已发送 %d 字节\n", len);
}

connect() ------ 连接函数

1.头文件
#include <sys/types.h>
#include <sys/socket.h>
2.函数原型
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
3.函数参数
参数说明
sockfd套接字文件描述符(socket() 的返回值)
addr服务器地址结构(sockaddr_in 转型成 sockaddr)
addrlen地址结构的长度,通常为 sizeof(struct sockaddr_in)
4.返回值
返回值说明
0连接成功(TCP 三次握手建立完成)
-1连接失败(服务器未启动、IP/端口错误、拒绝访问等)
5.函数功能
  • 客户端用 connect() 主动向服务器发起连接请求(TCP)。

  • 执行过程中会触发 TCP 三次握手

  • 连接成功后,客户端就可以使用 send() / recv() 与服务器通信。

6.示例代码
SIN seraddr;
seraddr.sin_family = AF_INET;
seraddr.sin_port = htons(PORT_NUM);
seraddr.sin_addr.s_addr = inet_addr(SERVER_IP);int ret = connect(sockfd, (SA*)&seraddr, sizeof(seraddr));
if (ret == -1) {perror("connect 失败");exit(1);
}
printf("连接服务器成功!\n");

TCP实例:

题目:TCP 网络通信程序设计(基于 socket 的 C/S 模型)

要求:

利用 Linux 下的 socket API 编写一对基于 TCP 协议的通信程序,实现:

  • 服务器端(Server):等待客户端连接,建立通信,进行数据收发;

  • 客户端(Client):连接服务器,建立通信,进行数据收发;

  • 使用 父子进程 分别实现“发送”和“接收”功能,实现全双工通信

代码逻辑说明

1️⃣ 服务器端程序(Server)

文件功能:创建 TCP 服务器,等待客户端连接并实现双向通信。

主要步骤:
  1. 创建套接字

    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    创建一个 IPv4、面向连接的 TCP 套接字。

  2. 设置服务器地址结构

    seraddr.sin_family = AF_INET;
    seraddr.sin_port = htons(PORT_NUM);
    seraddr.sin_addr.s_addr = inet_addr(SERVER_IP);
    

    绑定本机 IP 和端口号(这里是 192.168.11.247:5000)。

  3. 端口复用、绑定和监听

    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
    bind(sockfd, (SA *)&seraddr, sizeof(SIN));
    listen(sockfd, 10);
    
    • 允许端口复用;

    • 将 socket 与 IP+端口绑定;

    • 设置监听队列。

  4. 等待客户端连接

    clifd = accept(sockfd, (SA*)&cliaddr, &addrlen);
    

    当客户端连接成功后,返回新的通信套接字。

  5. 父子进程通信机制

    • 使用 fork() 创建子进程。

    • 子进程: recv() 接收客户端发来的消息;

    • 父进程: send() 发送数据到客户端。

逻辑总结:

  • 服务端在 192.168.11.247:5000 等待连接;

  • 一旦客户端连接上后,父子进程分别负责发送与接收,实现双向通信。


2️⃣ 客户端程序(Client)

文件功能:连接服务器并进行全双工通信。

主要步骤:

  1. 创建 TCP 套接字

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
  2. 设置服务器地址

    seraddr.sin_family = AF_INET;
    seraddr.sin_port = htons(PORT_NUM);
    seraddr.sin_addr.s_addr = inet_addr(SERVER_IP);
    
  3. 连接服务器

    connect(sockfd, (SA*)&seraddr, sizeof(SA));
    

    向服务器 IP(192.168.11.247)端口 5000 发起 TCP 连接。

  4. 父子进程机制

    • 子进程: 循环 recv() 接收服务器发送的数据;

    • 父进程: 使用 send() 向服务器发送输入数据。


使用方法:

1️⃣ 编译命令:

gcc server.c -o server
gcc client.c -o client

2️⃣ 运行步骤:

  1. 在服务器主机上运行:

    ./server
    

    显示:

    Socket fd = 3
    Bind success!
    Listen success!
    

    等待客户端连接。

  2. 在另一台主机或同一主机上运行客户端:

    ./client

    若成功连接,会显示:

    Connect success!
    

    同时服务器端显示:

    
    客户端已连接,套接字 clifd = X

补充:ip地址的选择

在 socket 通信程序中:

  • 服务器端(Server) 需要绑定一个本机可用的 IP 地址;

  • 客户端(Client) 需要连接到服务器端的 IP 地址。

只有双方 IP 和端口匹配正确,且网络连通,TCP 连接才能建立成功。

用ifconfig查看本机可用的 IP 地址

截图可见:

ens33  Link encap:以太网  硬件地址 00:0c:29:5e:e7:acinet 地址:192.168.11.247  广播:192.168.15.255  掩码:255.255.248.0
lo      Link encap:本地环回inet 地址:127.0.0.1  掩码:255.0.0.0

这表示主机有两个网络接口:

接口名IP 地址说明
ens33192.168.11.247以太网接口(局域网 IP,可与其他主机通信)
lo127.0.0.1本地回环接口(仅限本机通信)

这份代码中的具体设置

✅ 如果要本机测试(服务器和客户端都在同一台电脑):

修改两段代码中的:

#define SERVER_IP "127.0.0.1"

服务器绑定:

seraddr.sin_addr.s_addr = inet_addr("127.0.0.1");

客户端连接:

seraddr.sin_addr.s_addr = inet_addr("127.0.0.1");

运行方式:

# 打开两个终端
./server
./client

这样通信会成功(在同一主机上测试)。


✅ 如果你要两台电脑通信(局域网内)

假设服务器那台电脑 IP 为:

192.168.11.247

那么:

  • 服务器代码

    #define SERVER_IP "192.168.11.247"
  • 客户端代码

    #define SERVER_IP "192.168.11.247"

并且要保证:

  • 客户端能 ping 通服务器 IP;

  • 服务器防火墙关闭或放行 5000 端口;

  • 两台电脑在同一网段(都类似 192.168.11.xxx)。

  • IP 地址选择规则

    场景服务器绑定 IP客户端连接 IP说明
    同一台主机通信(本机测试)127.0.0.1"0.0.0.0"127.0.0.1不经过网卡,最简单、安全
    局域网两台主机通信服务器使用本机局域网 IP,例如 192.168.11.247客户端填服务器那台主机的同一个 IP 地址确保在同一网段
    跨网段或公网通信公网 IP(或端口映射后的 NAT 地址)客户端连接公网 IP需保证防火墙和 NAT 规则允许访问
代码:

服务端 ------ service.c

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>#define SERVER_IP "192.168.11.247"   // 定义服务器IP地址
#define PORT_NUM 5000           // 定义服务器端口号为5000typedef struct sockaddr SA;
typedef struct sockaddr_in SIN;int main() {int sockfd;int ret;int reuse = 1;// 创建TCP套接字sockfd = socket(AF_INET, SOCK_STREAM, 0);   // 创建一个IPv4的TCP套接字,返回套接字描述符sockfdif (sockfd < 0) {perror("socket创建失败");return -1;}printf("Socket fd = %d\n", sockfd);// 初始化服务器地址结构:、设置IPv4协议族、端口号(PORT_NUM,网络字节序)和服务器IP地址(SERVER_IP)SIN seraddr;    bzero(&seraddr, sizeof(SIN));            //清零seraddr.sin_family = AF_INET;            // 指定使用IPv4地址族seraddr.sin_port = htons(PORT_NUM);      // 将主机字节序的端口号转换为网络字节序并赋给端口字段seraddr.sin_addr.s_addr = inet_addr(SERVER_IP); // 将字符串形式的服务器IP地址转换为网络字节序并赋给地址字段setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); // 设置套接字选项,允许端口地址复用ret = bind(sockfd, (SA *)&seraddr, sizeof(SIN));    // 将套接字sockfd与服务器地址结构seraddr绑定if (ret == -1) {perror("bind failed");exit(0);}printf("Bind success!\r\n");ret = listen(sockfd, 10);    // 设置监听队列长度为 10if(ret == -1) {perror("listen failed");exit(0);}printf("Listen success!\r\n");int clifd;SIN cliaddr;socklen_t addrlen = sizeof(cliaddr);clifd = accept(sockfd, (SA*)&cliaddr, &addrlen);if(clifd == -1) {perror("accept failed");exit(0);}printf("客户端已连接,套接字 clifd = %d\r\n", clifd);//创建父子进程ret = fork();if(ret == 0) {  //子进程,接收客户端发送过来的数据char r_buf[10] = {0};while(1) {recv(clifd, r_buf, sizeof(r_buf), 0);printf("客户端:%s\r\n", r_buf);memset(r_buf, 0, sizeof(r_buf));}}else {  //父进程,发送数据char t_buf[10] = {0};while (1) {scanf("%s", t_buf);getchar();  //吸收换行send(clifd, t_buf, sizeof(t_buf), 0);}}
}

客户端 ------ client.c

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>#define SERVER_IP "192.168.11.247"   // 定义服务器IP地址为本地回环地址
#define PORT_NUM 5000           // 定义服务器端口号为5000typedef struct sockaddr SA;
typedef struct sockaddr_in SIN;
int main() {int sockfd;int ret;// 创建TCP套接字sockfd = socket(AF_INET, SOCK_STREAM, 0);   // 创建一个IPv4的TCP套接字,返回套接字描述符sockfdif (sockfd < 0) {perror("socket创建失败");return -1;}printf("Socket fd = %d\n", sockfd);// 初始化服务器地址结构:、设置IPv4协议族、端口号(PORT_NUM,网络字节序)和服务器IP地址(SERVER_IP)SIN seraddr;    bzero(&seraddr, sizeof(SIN));            //清零seraddr.sin_family = AF_INET;            // 指定使用IPv4地址族seraddr.sin_port = htons(PORT_NUM);      // 将主机字节序的端口号转换为网络字节序并赋给端口字段seraddr.sin_addr.s_addr = inet_addr(SERVER_IP); // 将字符串形式的服务器IP地址转换为网络字节序并赋给地址字段ret = connect(sockfd, (SA*)&seraddr, sizeof(SA));if(ret == -1) {perror("connect failed");exit(0);}printf("Connect success!\r\n");//创建父子进程ret = fork();if(ret == 0) {  //子进程,接收服务端发送过来的数据char r_buf[10] = {0};while(1) {recv(sockfd, r_buf, sizeof(r_buf), 0);printf("服务端:%s\r\n", r_buf);memset(r_buf, 0, sizeof(r_buf));}}else {  //父进程,发送数据char t_buf[10] = {0};while (1) {scanf("%s", t_buf);getchar();  //吸收换行符send(sockfd, t_buf, sizeof(t_buf), 0);}}}

四、UDP网络编程

UDP框架

⭐ UDP 的特点:

  • 无连接:不需要三次握手

  • 不可靠:不保证送达

  • 速度快:更适合实时应用(语音、视频、广播)

UDP 服务器端流程

socket  →  bind  →  recvfrom  →  sendto  →  close
  1. socket()
    创建 UDP 套接字:

  2. bind()
    绑定服务器 IP 和端口。

  3. recvfrom()
    接收客户端发送的数据(阻塞等待)。

  4. sendto()
    将处理后的数据发送回客户端。

  5. close()
    关闭套接字。

UDP 客户端流程

socket  →  sendto  →  recvfrom  →  close
  1. socket()

    创建 UDP 套接字。

  2. sendto()

    不需要 connect,直接把数据发给服务器。

  3. recvfrom()

    接收服务器返回的数据。

  4. close()

    关闭套接字。

UDP相关函数

sendto() ------ 发送信息

1.头文件
#include <sys/types.h>
#include <sys/socket.h>
2.函数原型
ssize_t sendto(int sockfd, const void *buf, size_t len,int flags, const struct sockaddr *dest_addr,socklen_t addrlen);
3.函数参数
参数说明
sockfd套接字文件描述符(socket() 返回的 UDP 套接字)
buf指向待发送数据的缓冲区
len数据长度(字节)
flags通常填写 0,MSG_DONTWAIT 可实现非阻塞。
dest_addr目标地址结构(服务器或客户端的 IP + 端口)
addrlen地址结构长度(sizeof(struct sockaddr_in)
4.返回值
返回值说明
>=0实际发送的字节数
-1发送失败(网络错误、地址错误等)
5.函数功能
  • 使用 UDP 协议向指定 IP 和端口发送数据

  • 不需要建立连接(无 connect,无三次握手)

  • 可用于单播、广播、组播等应

6.示例代码
char buf[] = "hello udp";
int len;len = sendto(sockfd, buf, strlen(buf), 0,(struct sockaddr *)&seraddr, sizeof(seraddr));if (len == -1) {perror("sendto failed");exit(0);
}

recvfrom() ------ 接收信息

1.头文件
#include <sys/types.h>
#include <sys/socket.h>
2.函数原型
int recvfrom(int s, void *buf, int len, unsigned int flags,struct sockaddr *from, socklen_t *fromlen);
3.函数参数
参数说明
int s套接字文件描述符(UDP socket)
*void buf接收数据的缓冲区(如 char buf[40]
int len缓冲区长度(期望接收多少字节)
unsigned int flags一般填 0(也可使用 MSG_DONTWAIT 非阻塞)
*struct sockaddr from用来存放发送方(对端)地址信息
*socklen_t fromlen输入输出参数:地址结构大小(一般为 sizeof(struct sockaddr_in)
4.返回值
返回值说明
>0实际接收到的数据长度
0对端关闭(UDP 一般不会出现)
-1接收失败
5.函数功能
  • 从 UDP 套接字接收数据

  • 获取对方(发送者)的 IP 和端口号

  • 默认阻塞等待数据到来

  • 常用于 UDP 服务器端和客户端消息接收

6.示例代码
SIN cliaddr;
socklen_t addrlen = sizeof(SIN);
char r_buf[40];int recv_len = recvfrom(serfd, r_buf, sizeof(r_buf), 0,(SA*)&cliaddr, &addrlen);if (recv_len == -1) {perror("recvfrom failed");exit(0);
}printf("接收到 %d 字节: %s\n", recv_len, r_buf);

UDP实例

利用UDP协议,实现服务器和客户端之间自由通信

服务端service.c

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>#define SERVER_IP "192.168.11.247"   // 定义服务器IP地址
#define PORT_NUM 5000           // 定义服务器端口号为5000typedef struct sockaddr SA;
typedef struct sockaddr_in SIN;int main() {int sockfd;int ret;int reuse = 1;// 创建UDP套接字sockfd = socket(AF_INET, SOCK_DGRAM, 0); // 创建一个IPv4的UDP套接字,返回套接字描述符sockfdif (sockfd < 0) {perror("socket创建失败");return -1;}printf("Socket fd = %d\n", sockfd);// 初始化服务器地址结构:、设置IPv4协议族、端口号(PORT_NUM,网络字节序)和服务器IP地址(SERVER_IP)SIN seraddr;    bzero(&seraddr, sizeof(SIN));            //清零seraddr.sin_family = AF_INET;            // 指定使用IPv4地址族seraddr.sin_port = htons(PORT_NUM);      // 将主机字节序的端口号转换为网络字节序并赋给端口字段seraddr.sin_addr.s_addr = inet_addr(SERVER_IP); // 将字符串形式的服务器IP地址转换为网络字节序并赋给地址字段setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); // 设置套接字选项,允许端口地址复用ret = bind(sockfd, (SA *)&seraddr, sizeof(SIN));    // 将套接字sockfd与服务器地址结构seraddr绑定if (ret == -1) {perror("bind failed");exit(0);}printf("Bind success!\r\n");//接收对应客户端信息char buf[10] = {0};SIN cliaddr = {0};socklen_t addrlen = sizeof(SIN);ret = recvfrom(sockfd, buf, sizeof(buf), 0, (SA*)&cliaddr, &addrlen);if(ret > 0) {printf("客户端信息:%s\r\n", buf);}//打印地址信息--直接法--对应客户端的IP地址printf("new client address is:%d.%d.%d.%d:%d\r\n",(cliaddr.sin_addr.s_addr)&0xff,(cliaddr.sin_addr.s_addr>>8)&0xff,(cliaddr.sin_addr.s_addr>>16)&0xff ,(cliaddr.sin_addr.s_addr>>24)&0xff,cliaddr.sin_port);//可以输出对应的IP地址  printf("ip addr is:%s\n", inet_ntoa(cliaddr.sin_addr));//创建父子进程ret = fork();if(ret == 0) {  //子进程,接收客户端发送过来的数据char r_buf[10] = {0};while(1) {if(recvfrom(sockfd, r_buf, sizeof(r_buf), 0, (SA*)&cliaddr, &addrlen)) {printf("客户端:%s\r\n", r_buf);}memset(r_buf, 0, sizeof(r_buf));}}else {  //父进程,发送数据char t_buf[10] = {0};while (1) {fgets(t_buf, sizeof(t_buf), stdin);     // 从标准输入读取一行数据到bufsendto(sockfd, t_buf, strlen(t_buf), 0, (SA*)&cliaddr, addrlen);    // 将buf中的数据发送到指定客户端地址cliaddrmemset(t_buf, 0, sizeof(t_buf));}}
}

客户端client.c

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>#define SERVER_IP "192.168.11.247"   // 定义服务器IP地址为本地回环地址
#define PORT_NUM 5000           // 定义服务器端口号为5000typedef struct sockaddr SA;
typedef struct sockaddr_in SIN;
int main() {int sockfd;int ret;// 创建TCP套接字sockfd = socket(AF_INET, SOCK_DGRAM, 0);    // 创建一个IPv4的UDP套接字,返回套接字描述符sockfdif (sockfd < 0) {perror("socket创建失败");return -1;}printf("Socket fd = %d\n", sockfd);// 初始化服务器地址结构:、设置IPv4协议族、端口号(PORT_NUM,网络字节序)和服务器IP地址(SERVER_IP)SIN seraddr;    socklen_t addrlen = sizeof(seraddr);bzero(&seraddr, sizeof(SIN));            //清零seraddr.sin_family = AF_INET;            // 指定使用IPv4地址族seraddr.sin_port = htons(PORT_NUM);      // 将主机字节序的端口号转换为网络字节序并赋给端口字段seraddr.sin_addr.s_addr = inet_addr(SERVER_IP); // 将字符串形式的服务器IP地址转换为网络字节序并赋给地址字段ret = sendto(sockfd, "hello", sizeof("hello"), 0, (SA*)&seraddr, addrlen);if(ret > 0) {printf("sendto success\r\n");}//创建父子进程ret = fork();if(ret == 0) {  //子进程,接收服务端发送过来的数据char r_buf[10] = {0};while(1) {if(recvfrom(sockfd, r_buf, sizeof(r_buf), 0, (SA*)&seraddr, &addrlen)) {printf("服务端:%s\r\n", r_buf);}memset(r_buf, 0, sizeof(r_buf));}}else {  //父进程,发送数据char t_buf[10] = {0};while (1) {fgets(t_buf, sizeof(t_buf), stdin);     // 从标准输入读取一行数据到bufsendto(sockfd, t_buf, strlen(t_buf), 0, (SA*)&seraddr, addrlen);    // 将buf中的数据发送到指定客户端地址cliaddrmemset(t_buf, 0, sizeof(t_buf));}}}

现象:

1.打开服务端

2.用另一个终端打开客户端

3.服务器和客户端之间自由通信

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

相关文章:

  • Vue-github 用户搜索案例
  • GD32F407VE天空星开发板的电压电流检测
  • 网站优化文章怎么做蔡甸城乡建设局网站
  • 中小企业网站开发韵茵全屋定制家具品牌排行榜前十名
  • 分库分表MyCat 架构迁移 OceanBase | 百丽核心财务系统迁移经验总结与问题汇总
  • joomla 企业网站模板沈阳网站优化 唐朝网络
  • Flink 优化-反压处理
  • AI代码开发宝库系列:LangChain 工具链:从LCEL到实际应用
  • 泉州网站排名优化十大免费论文网站
  • 高校招生网站建设做网站一定要效果图吗
  • 学习笔记四:性能度量
  • 使用JavaScript和Node.js构建简单的RESTful API
  • 【生活】做蛋糕
  • (论文速读)EgoLife:走向自我中心的生活助手
  • 大模型时代,我们该如何学习?从“知识存储器”到“思维策展人”的蜕变
  • vc_redist.x64.exe安装方法,解决软件游戏缺少运行库问题
  • 【C++】继承(1):深入理解和使用
  • C语言内功强化之修饰关键字
  • 未来已来:AI 如何在 3 年内重塑工作、教育与生活
  • 追波设计网站wordpress如何去除页眉部分
  • 12. 深入Spring AI:多模态
  • 网站开发技术发展史网站建设要哪些人?
  • Argo CD vs Tekton vs Arbess,CI/CD工具一文纵评
  • 简单创建一个flask项目
  • 小迪安全v2023学习笔记(一百四十二讲)—— Linux系统权限提升篇VulnhubRbash绕过DockerLXD镜像History泄露
  • 驻马店市做网站asp.net网站本机访问慢
  • 河南网站备案所需资料厦门互联网公司排名
  • Vue.js 与 Ajax(axios)深度整合指南
  • 25年05月架构甄选范文“论负载均衡设计”,软考高级,系统架构设计师论文
  • SQL键类型详解:超键到外键全解析