Linux网络部分——TCP协议服务端客户端交互接口,入门级硬核解析1.0

@bit::Shadow
✧(≖ ◡ ≖✿

目录

TCP与UDP差异

最核心差异

监听listen()

[listen 的直观理解(它在做什么?)](#listen 的直观理解(它在做什么?))

🔗listen错误时枚举的使用原理(区分与C是很有必要的)"C++进阶知识5.0"blog(待链接)

listen造成accept的诞生原理

accept正常返回的套接字(sockfd)与listensockfd的对比(了解)

TCP套接字的状态限定(待深入)

accept()

[1. 回顾 accept() 的函数原型](#1. 回顾 accept() 的函数原型)

[2. 为什么不需要初始化?因为它是"输出参数"](#2. 为什么不需要初始化?因为它是"输出参数")

[🔗netstat telnet使用(必看)blog](#🔗netstat telnet使用(必看)blog)

普通监视

🔗telnet的使用

链接前

链接

链接后

客户端

connect()客户向服务打电话☎️以求建立链接


TCP简易服务端客户端框架的搭建gitee(复习必看)

TCP与UDP差异

最核心差异

TCP是有状态 、有连接 的可靠 协议;UDP是无状态 、无连接 的不可靠协议;

对比维度 UDP(你用的 SOCK_DGRAM) TCP(SOCK_STREAM)
连接状态 无连接(发数据前不需握手) 面向连接(需三次握手建立连接)
可靠性 不可靠(丢包不重传,可能乱序) 可靠(确认重传、保证顺序)
数据边界 保留边界 (每次 sendto 对应一次 recvfrom) 无边界(流式) (多次 send 可被一次 recv 读完)
传输效率 高(头部开销小,无拥塞控制) 低(头部大,有流量/拥塞控制)
典型应用 DNS、视频直播、实时游戏、VoIP HTTP、FTP、SSH、邮件、数据库
Socket 类型 SOCK_DGRAM SOCK_STREAM
核心函数 sendto / recvfrom connect / accept / send / recv

监听listen()

listen 的直观理解(它在做什么?)

继续用我们之前的"打电话"比喻:

  • socket() 创建了一个"电话机"(创建套接字)。

  • bind() 给电话机绑定了号码(绑定 IP 和端口)。

  • listen() 则是把电话机切换到"响铃待机模式" 。它告诉操作系统内核:"我准备好了,现在开始监听这个端口,随时准备接听客户端的来电请求。"

在代码层面,它的函数原型通常是:

c

复制代码
int listen(int sockfd, int backlog);
  • sockfd:刚才创建的那个套接字。

  • backlog :这是最核心的参数,它限制了"全连接队列(Accept 队列)"的最大长度。(不宜过大、过小)

🔗listen错误时枚举的使用原理(区分与C是很有必要的)"C++进阶知识5.0"blog(待链接)

listen造成accept的诞生原理

使用端(使用listen的)原套接字状态改变!

在listen调用之前,TCP套接字处于主动状态。(即类似UDP的状态)

在listen调用之后,TCP套接字处于被动状态 ,只能接受信息**链接,**无法被用以发送信息。

因此我们常使用listen的套接字命名为"_listenSockfd"

匿名服务端应该怎样接受与发送信息?

答案是"accept"再创建sockfd(因此就引入了多线程,多进程等版本(单进程版本在实际工程中不存在!))

accept正常返回的套接字(sockfd)与listensockfd的对比(了解)

|-----------------|-----------------------------------------|-------------------------------|
| | 监听套接字(Listening Socket) | 已连接套接字(Connected Socket) |
| 创建时机 | socket() + bind() + listen() 后产生 | accept() 从全连接队列中取出后返回 |
| 身份 | "前台接待员" | "专属客服代表" |
| 职责 | 只负责监听新的连接请求(三次握手) | 只负责收发数据(读写业务数据) |
| 能否 write? | 不能 (理论上强行写会报错 EPIPE 或 ENOTCONN) | 能(服务端通过它回复 HTTP 响应、文件数据等) |
| 数量 | 整个服务端通常只有 1 个 | 每个客户端连接对应 1 个,可能有成千上万个 |

TCP套接字的状态限定(待深入)

TCP是有严格状态机的。一个套接字在任意时刻只能处于一种状态:

套接字类型 TCP状态 允许的操作
主动套接字(客户端) CLOSED → SYN_SENT → ESTABLISHED 只能connect()发起连接,成功后收发数据
被动套接字(监听) CLOSED → LISTEN 只能accept()接收新连接,不能收发数据
已连接套接字(服务端) ESTABLISHED → CLOSE_WAIT → ... 只能read()/write()收发数据,不能accept()

accept()

阻塞等待对象链接。

1. 回顾 accept() 的函数原型

c

复制代码
int accept(int _listensockfd, struct sockaddr *addr, socklen_t *addrlen);
  • 第一个参数 :监听套接字(你已经listen()好的那个)。

  • 第二个参数 :struct sockaddr *addr ------ 这是一个"输出参数"。

  • 第三个参数 :socklen_t *addrlen ------ 这是一个"输入输出参数"。


2. 为什么不需要初始化?因为它是"输出参数"

在C语言中,函数参数有两种用途:

参数类型 方向 调用者要做的事 函数要做的事
输入参数 调用者 → 函数 填充好数据再传进去 读取并使用
输出参数 函数 → 调用者 分配好内存即可 往里面写数据
输入输出参数 双向 既要初始化,又要读取函数写回的值 既要读取,也要修改

accept()的第二个参数 addr 是一个典型的"输出参数":

  • 调用前 :你只需要提供一块足够大的内存 (struct sockaddr_in 或 struct sockaddr_storage),里面的值无所谓,可以是随机垃圾。

  • 调用后 :内核会把客户端的IP地址和端口号填进这个结构体,然后返回给你。

🔗netstat telnet使用(必看)blog

普通监视

部分进程PID隐藏(权限不足、可使用sudo提权)

bash 复制代码
w@instance-qhw6x01g:~/e2026/Auguest/TCPServerClient/build$ netstat -tanp | grep LISTEN
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:45825         0.0.0.0:*               LISTEN      10811/node          
tcp        0      0 127.0.0.1:6010          0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      72312/./tcpServer   
tcp        0      0 127.0.0.1:43557         0.0.0.0:*               LISTEN      10587/code-a5b50095 
tcp        0      0 127.0.0.1:36239         0.0.0.0:*               LISTEN      10558/code-a5b50095 
tcp        0      0 0.0.0.0:428             0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:35897         0.0.0.0:*               LISTEN      9347/code-df53daabb 
tcp6       0      0 :::781                  :::*                    LISTEN      -                   
tcp6       0      0 :::22                   :::*                    LISTEN      -                   
tcp6       0      0 ::1:6010                :::*                    LISTEN      -    

sudo提权

bash 复制代码
w@instance-qhw6x01g:~/e2026/Auguest/TCPServerClient/build$ sudo netstat -tanp | grep LISTEN
[sudo] password for w: 
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      730/systemd-resolve 
tcp        0      0 127.0.0.1:45825         0.0.0.0:*               LISTEN      10811/node          
tcp        0      0 127.0.0.1:6010          0.0.0.0:*               LISTEN      72588/sshd: w@pts/0 
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      72312/./tcpServer   
tcp        0      0 127.0.0.1:43557         0.0.0.0:*               LISTEN      10587/code-a5b50095 
tcp        0      0 127.0.0.1:36239         0.0.0.0:*               LISTEN      10558/code-a5b50095 
tcp        0      0 0.0.0.0:428             0.0.0.0:*               LISTEN      2793/has_agent      
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      4337/sshd: /usr/sbi 
tcp        0      0 127.0.0.1:35897         0.0.0.0:*               LISTEN      9347/code-df53daabb 
tcp6       0      0 :::781                  :::*                    LISTEN      1037/./bcm-agent    
tcp6       0      0 :::22                   :::*                    LISTEN      4337/sshd: /usr/sbi 
tcp6       0      0 ::1:6010                :::*                    LISTEN      72588/sshd: w@pts/0 

🔗telnet的使用

你应该仔细观看动态的变化(待补充)

链接前

链接

链接后


客户端

connect()客户向服务打电话☎️以求建立链接

cpp 复制代码
#include<sys/socket.h>

int connect(int sockfd, const sockaddr* __addr, socklen_t len);

|--------|----------------|-------|
| 参数 | 含义 | 方向 |
| sockfd | 客户端创建的套接字 | 一般输入型 |
| _addr | 服务端的IP与端口号 | 输入型参数 |
| len | 结构体大小 | 输入型参数 |

返回值:

  • 成功:返回 0

  • 失败:返回 -1,并设置 errno

感谢支持,长期连载

欢迎关注

相关推荐
Android系统攻城狮31 分钟前
Linux Gstreamer深度解析之gst_audio_ring_buffer_delay调用流程与实战(七十二)
linux·运维·服务器·gstreamer音视频·音视频进阶
快乐的韭菜根根1 小时前
ubuntu 安装slurm并配置
linux·运维·ubuntu
花间相见2 小时前
【计算基础|网络14】网络层:IP、ICMP 与 ping
网络·网络协议·tcp/ip
OnlineProxy3 小时前
为 LangChain 和 CrewAI 构建自定义工具:将代理 IP 轮换封装至智能体函数中
网络协议·tcp/ip·langchain
倒头就睡的小比特3 小时前
Linux基础指令3
linux·服务器
梦帮科技3 小时前
Kali Linux Scapy 畸形报文构造学——深度解剖非法 TCP Flags 与反常序列号
linux·爬虫·神经网络·算法·数学建模·系统架构·模拟退火算法
半杯咖啡半行码4 小时前
Linux 驱动开发入门:内核模块编程基础
linux·服务器·网络
智能直播5 小时前
RK3528 V4L2 框架 UVC 接口自动获取 H.264 / MJPEG / YUYV 格式:从内核采集到硬解分发
java·网络·实时音视频·视频编解码·h.264
别动我齐刘海5 小时前
Linux 系统调试学习2
linux·运维·c++·人工智能·学习·机器学习·机器人
龙虾电话5 小时前
语音机器人打断不进去:VAD 双阈值迟滞里一个共用的 bool,和它引发的连锁误判
linux