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

发布时间:2026/8/15 11:24:44
Linux网络部分——TCP协议服务端客户端交互接口,入门级硬核解析1.0 bit::Shadow✧(≖ ◡ ≖✿目录TCP与UDP差异最核心差异监听listen()listen 的直观理解它在做什么listen错误时枚举的使用原理区分与C是很有必要的“C进阶知识5.0”blog待链接listen造成accept的诞生原理accept正常返回的套接字sockfd与listensockfd的对比了解TCP套接字的状态限定待深入accept1. 回顾 accept() 的函数原型2. 为什么不需要初始化因为它是输出参数netstat telnet使用必看blog普通监视telnet的使用链接前链接链接后客户端connect()客户向服务打电话☎️以求建立链接TCP简易服务端客户端框架的搭建gitee复习必看TCP与UDP差异最核心差异TCP是有状态、有连接的可靠协议UDP是无状态、无连接的不可靠协议对比维度UDP你用的SOCK_DGRAMTCPSOCK_STREAM连接状态无连接发数据前不需握手面向连接需三次握手建立连接可靠性不可靠丢包不重传可能乱序可靠确认重传、保证顺序数据边界保留边界每次sendto对应一次recvfrom无边界流式多次send可被一次recv读完传输效率高头部开销小无拥塞控制低头部大有流量/拥塞控制典型应用DNS、视频直播、实时游戏、VoIPHTTP、FTP、SSH、邮件、数据库Socket 类型SOCK_DGRAMSOCK_STREAM核心函数sendto/recvfromconnect/accept/send/recv监听listen()listen的直观理解它在做什么继续用我们之前的“打电话”比喻socket()创建了一个“电话机”创建套接字。bind()给电话机绑定了号码绑定 IP 和端口。listen()则是把电话机切换到“响铃待机模式”。它告诉操作系统内核“我准备好了现在开始监听这个端口随时准备接听客户端的来电请求。”在代码层面它的函数原型通常是cint 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()的函数原型cint 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提权winstance-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提权winstance-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: wpts/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: wpts/0telnet的使用你应该仔细观看动态的变化待补充链接前链接链接后客户端connect()客户向服务打电话☎️以求建立链接#includesys/socket.h int connect(int sockfd, const sockaddr* __addr, socklen_t len);参数含义方向sockfd客户端创建的套接字一般输入型_addr服务端的IP与端口号输入型参数len结构体大小输入型参数返回值成功返回0失败返回-1并设置errno感谢支持长期连载欢迎关注