Linux网络编程:TCP网络协议

TCP传输控制协议

cs ,client ,server

bs ,browser(浏览器),server

p2p peer to peer

cs ,bs 区别

cs, 专用客户段

bs ,通用的客户端

2.使用协议

Cs ,应用,标准,自定义

bs 应用层 http

3.功能强弱

cs 相对复杂

bs 相对简单

4. 资源

Cs ,资源在本地

Bs ,由发送给客户

在p2p 网络下载工具中,用的多。

刚开始下载数据的时候,自己的进度是0%, 会有其他的客户端,和服务器,给 咱们自己传递数据。

随着时间的推移,自己的下载进度到了90%,这个时候会有其他的新到达客户端,开始下载数据。

咱们自己也会给新到达的客户端,发送数据。在整个过程中,自己及时下载者,也是上传者。所有身份, 相当于及时客户端,也是服务器

特征:

1.有链接 三次握手

  1. 可靠传输

3.流式套接字,数据没有边界。 连续的,有顺序的。

4.全双工,双缓存区

5.发送次数和接收次数不需要对应。

6.有写阻塞 64K

7 如果对方端口连接,另外一方可以感知 4次挥手

1.应答 ack num

2.超时重传

  1. 实时性弱

4.网络资源消耗大

有链接,服务器和客户端之间,一旦连接建立。链路就会一直保持。 直到其中一方表示要断

在利用Wireshark工具进行抓包的时候只有三次挥手,因为系统将【ACK】和【自己的 FIN】合并了再发出去,所以看起来少了一个

使用wireshark抓包的时候,如果外网ens33,如果是测试自己与自己连接用回环接口loopback,不确定时使用any即可

监听套接字和通信套接字的关系

tcp 相关函数

int socket(int domain, int type, int protocol);

功能:程序向内核提出创建一个基于内存的套接字描述符

参数:domain 地址族,PF_INET == 》AF_INET ==>互联网程序

PF_UNIX ==》 AF_UNIX ==>单机程序

type 套接字类型:

SOCK_STREAM 流式套接字 ===》TCP

SOCK_DGRAM 用户数据报套接字:=>UDP

SOCK_RAW 原始套接字 ===》IP

protocol 协议 ==》0 表示自动适应应用层协议。

返回值:成功 返回申请的套接字id

失败 -1;

绑定地址可以不用写固定ip地址,可以调用宏INADDR_ANY

该宏代表监听本机所有网卡(回环 lo、内网网卡、公网网卡),任何网卡收到目标端口 50000 的包,这个 socket 都能接收

2、int bind(int sockfd, struct sockaddr *my_addr,socklen_t addrlen);

功能:如果该函数在服务器端调用,则表示将参数1相关

的文件描述符文件与参数2 指定的接口地址关联,

用于从该接口接受数据。

3、 int listen(int sockfd, int backlog);

功能:在参数1所在的套接字id上监听等待链接。

参数:sockfd 套接字id

backlog 允许三次握手的排队数。

返回值:成功 0

失败 -1;

3、 int listen(int sockfd, int backlog);

功能:在参数1所在的套接字id上监听等待链接。

参数:sockfd 套接字id

backlog 允许三次握手的排队数。

返回值:成功 0

失败 -1;

4、int accept(int sockfd, struct sockaddr *addr,socklen_t *addrlen);

功能:从已经监听到的队列中取出有效的客户端链接并

接入到当前程序。

参数:sockfd 套接字id

addr 如果该值为NULL ,表示不论客户端是谁都接入。

如果要获取客户端信息,则事先定义变量

并传入变量地址,函数执行完毕将会将客户端

信息存储到该变量中。

addrlen: 参数2的长度,如果参数2为NULL,则该值

也为NULL;

如果参数不是NULL,&len;

一定要写成len = sizeof(struct sockaddr);

返回值:成功 返回一个用于通信的新套接字id; 通信套接字

从该代码之后所有通信都基于该id

失败 -1;

5.ssize_t recv(int sockfd, void *buf, size_t len,

int flags);

功能:从指定的sockfd套接字中以flags方式获取长度

为len字节的数据到指定的buff内存中。

参数:sockfd

如果服务器则是accept的返回值的新fd

如果客户端则是socket的返回值旧fd

buff 用来存储数据的本地内存,一般是数组或者

动态内存。

len 要获取的数据长度

flags 获取数据的方式,0 表示阻塞接受。

返回值:成功 表示接受的数据长度,一般小于等于len

失败 -1;

  1. int send(int sockfd, const void *msg,size_t len, int flags);

功能:从msg所在的内存中获取长度为len的数据以flags

方式写入到sockfd对应的套接字中。

参数:sockfd:

如果是服务器则是accept的返回值新fd

数据封包拆包

协议头

如果是客户端则是sockfd的返回值旧fd

msg 要发送的消息

len 要发送的消息长度

flags 消息的发送方式。

返回值:成功 发送的字符长度

失败 -1;

客户端 自动连接服务器。

int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

功能:该函数固定有客户端使用,表示从当前主机向目标

主机发起链接请求。

参数:sockfd 本地socket创建的套接子id

addr 远程目标主机的地址信息。

addrlen: 参数2的长度。

返回值:成功 0

失败 -1;

黏包问题

tcp在通信过程中,数据之间没有边界,接收方不能还原数据。发送方可以发送多次,接收发 ,一次性接送,导致数据不能正常解析的现象。

可以通过以下方法解决

  • 长度头(首选):头部 4 字节存消息长度(网络序),先收长度再收对应数据。
  • 分隔符:消息末尾加标记,不能出现在消息内容内。
  • 固定包长:所有报文长度一致。
    注意,用sleep或者usleep只能临时缓解,减缓发送时长,临时性解决

5. UDP 与 TCP 对比

对比维度 UDP TCP
连接方式 无连接 面向连接(三次握手)
可靠性 不可靠,不保证送达 可靠,确认 + 重传
有序性 不保证顺序 保证按序到达
传输方式 面向报文 面向字节流
头部开销 8 字节 20~60 字节
流量/拥塞控制 无 有
通信模式 单播、广播、多播 仅单播
典型场景 音视频、游戏、DNS、QUIC HTTP、文件传输、数据库连接

一句话总结:TCP 追求可靠,UDP 追求高效。选择哪个协议,取决于业务能否容忍丢包,以及是否愿意在应用层自己实现可靠性。

相关推荐
Shanks.3 小时前
2026 远程控制软件实测:ToDesk / 向日葵 / RustDesk / TeamViewer 在跨城与弱网下的真实差距
网络·远程工作·软件需求
Jeremy_WW4 小时前
802.3协议解读 06:117章节 RS 和 200GMII / 400GMII I
网络·网络协议·信息与通信·光模块·802.3协议
坤坤子吖5 小时前
Linux网络编程:自定义应用层协议与 JSON 序列化
linux·服务器·网络·c++·笔记·json
顧棟5 小时前
INFINI Gateway 服务器端口重用(SO_REUSEPORT)实现与分析
网络·gateway
沫璃染墨6 小时前
从零入门计算机网络系列(十八):TCP连接管理详解——从三次握手与四次挥手到TIME_WAIT机制
运维·服务器·网络·c++·网络协议·tcp/ip·tcp
LabVIEW开发7 小时前
Omron PLC:接 LabVIEW 常踩的 5 个坑
服务器·网络·labview·labview知识·labview功能·labview程序
南京码讯光电技术有限公司7 小时前
工业5G/4G路由器怎么选?核心参数解析与工业级网关选购指南
网络·智能路由器
爱和冰阔落7 小时前
【Linux网络】JsonCpp 怎么实现序列化?从 Request/Response 到网络计算器消息设计
linux·运维·网络·php
feng_you_ying_li20 小时前
linux之数据链路层
linux·网络·智能路由器