Linux TCP 和 UDP 通信

TCP与UDP

TCP与UDP对比

TCP

特点:面向连接、可靠传输、流量控制、拥塞控制、全双工

优点:可靠性(ACK确认、超时重传)、顺序性

缺点:首部开销大(20字节)、连接管理复杂、延迟高

应用场景:HTTP/HTTPS、文件传输(FTP)、邮件(SMTP/IMAP)

UDP

特点:无连接、尽力交付、无重传、无拥塞控制、低开销

优点:传输效率高(8字节首部)、实时性强

缺点:数据可能丢失、乱序

应用场景:视频流(RTP)、DNS查询、在线游戏、VoIP

TCP通信

TCP网络编程流程

服务器流程:

1.创建流式套接字--socket()

2.填充服务器的网络信息结构体--struct sockaddr_in

3.将套接字于服务器的网络信息结构体绑定--bind()

4.将套接字设置成被动监听状态--listen()

5.阻塞等待客户端连接--accept()

6.收发数据---recv()/send()

7.关闭套接字--close()

socket编程

socket函数

头文件:#include <sys/socket.h>

函数原型:int socket(int domain, int type, int protocol);

参数:

•domain就是通信域,也可以说是协议族,常见通信域如下:

•AF_INETIPV4

•AF_INET6IPV6

•AF_PACKET原始套接字使用

•AF_UNIX本地通信

•AF_LOCAL本地通信

•type表示socket的类型,常用的socekt类型如下:

•SOCK_STREAMTCP使用

•SOCK_DGRAMUDP使用

•SOCK_RAW原始套接字

•protocol表示附加协议无附加协议填0(自动选择默认协议)

返回值:成功返回套接字(文件描述符-非负整数),失败返回-1(并重置错误码)

bind函数

头文件:#include <sys/socket.h>

函数原型:int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数:

•sockfd就是文件描述符(由socket函数返回)

•addr表示地址结构体指针(const struct sockaddr*),指向要绑定给sockfd的协议地址,该结构体根据创建socket时的协议族不同而不同,这里以IPV4为例:

cs 复制代码
struct sockaddr_in {
    sa_family_t sin_family;   // 地址族
    in_port_t sin_port;       // 16位端口号
    struct in_addr sin_addr;  // 32位IP地址
};

struct in_addr {
    uint32_t s_addr;          // 32位IPv4地址
};

•addrlen表示地址的长度

返回值:成功返回0,失败返回-1(并重置错误码)

listen函数

头文件:#include <sys/socket.h>

函数原型:int listen(int sockfd, int backlog);

参数:

•sockfd表示要监听的socket套接字

•backlog表示半连接队列的长度(即socket可以排队的最大连接个数)

返回值:成功返回0,失败返回-1(并重置错误码)

accept函数

头文件:#include <sys/socket.h>

函数原型:int accept(int sockfd, struct sockaddr*addr, socklen_t*addrlen);

参数:

•sockfd表示处于监听状态的socket

•addr用于保存客户端地址的结构体指针,如果不关心客户端的信息,可以传NULL

•addrlen输入时为addr的缓冲区大小,输出时为实际地址长度,如果不关心客户端的信息,可以传NULL

返回值:成功返回新的socket文件描述符(由内核生成,代表着与返回客户端的TCP连接,专用于与客户端通信),失败返回-1(并重置错误码)

connect函数

头文件:#include <sys/socket.h>

函数原型:int connect(int sockfd, const struct sockaddr*addr, socklen_taddrlen);

参数:

•sockfd表示客户端的socket套接字

•addr表示目标服务器的地址结构体

•addrlen地址结构体的长度

返回值:成功返回0,失败返回-1(并重置错误码)

recv函数

头文件:#include <sys/socket.h>

函数原型:ssize_t recv(int sockfd, void *buf, size_tlen, int flags);

参数:

•sockfd表示客户端的socket套接字

•buf用于存储接收的数据

•len数据大小

•flags控制选项(如MSG_DONTWAIT非阻塞,MSG_PEEK窥视数据,0阻塞)

返回值:成功返回实际接收数据字节数,失败返回-1(并重置错误码)

send函数

头文件:#include <sys/socket.h>

函数原型:ssize_tsend(int sockfd, const void *buf, size_tlen, int flags);

参数:

•sockfd表示客户端的socket套接字

•buf要发送的数据首地址

•len数据大小

•flags控制选项(如MSG_DONTWAIT非阻塞,MSG_PEEK窥视数据,0阻塞)

返回值:成功返回实际发送数据字节数,失败返回-1(并重置错误码)

close函数

头文件:#include <unistd.h>

函数原型:int close(int fd);

参数:

•fd表示要关闭的套接字

返回值:成功返回0,失败返回-1

TCP网络编程流程

客户端流程:

1.创建流式套接字--socket()

2.填充服务器的网络信息结构体--struct sockaddr_in

3.与服务器建立连接--connect()

4.收发数据---recv()/send()

5.关闭套接字--close()

完整TCP连接建立

完整TCP连接建立过程

四次挥手

UDP通信

UDP通信流程

sendto/recvfrom

recvfrom

recvfrom函数

头文件:#include <sys/socket.h> #include <sys/types.h>

函数原型:ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);

参数:

•sockfd表示客户端的socket套接字

•buf要接收的数据首地址

•len可接受数据的最大长度

•flags控制选项(如MSG_DONTWAIT非阻塞,MSG_PEEK窥视数据,0阻塞)

•src_addr源地址,获取发送方的信息

•addrlen地址长度

返回值:成功返回接收字节数,失败返回-1(并重置错误码)

sendto

sendto函数

头文件:#include <sys/socket.h> #include <sys/types.h>

函数原型:ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);

参数:

•sockfd表示客户端的socket套接字

•buf要发送的数据首地址

•len数据大小

•flags控制选项(如MSG_DONTWAIT非阻塞,MSG_PEEK窥视数据,0阻塞)

•dest_addr目的地址,数据将要发向哪一个ip地址的主机

•addrlen地址长度

返回值:成功返回发送字节数,失败返回-1(并重置错误码)

单播

单播:一对一通信,数据包从单一源地址发送到单一目标地址

流程与各层职责:

应用层

•调用sendto()发送数据到指定目标IP和端口

•调用recvfrom()接收来自特定源的数据

传输层

•封装UDP头部:源端口、目标端口、长度、校验和

•不建立连接,直接发送数据报

网络层

•封装IP头部:源IP、目标IP(单播地址,如192.168.1.100)

•根据目标IP查找路由表,选择下一跳

数据链路层

•根据目标IP的MAC地址(通过ARP解析)封装以太网帧

•通过物理网络设备(如网卡)发送到目标主机

组播

组播:一对多通信,数据包发送到一个组播组,组内所有成员均可接收

流程与各层职责:

应用层

•发送端:调用发送数据到组播地址(如239.255.0.1)

•接收端:调用加入组播组(IP_ADD_MEMBERSHIP)

传输层

•封装UDP头部:目标端口为组播端口(如12345)

•组播成员无需提前建立连接

网络层

•封装IP头部:目标IP为组播地址(D类地址,224.0.0.0~239.255.255.255)

•接收端通过IGMP报文通知路由器加入/离开组播组

•路由器维护组播组成员列表,仅向存在成员的子网转发数据

数据链路层

•组播MAC地址映射:将IP组播地址转换为以太网组播MAC(如01:00:5E:XX:XX:XX)

•交换机/路由器:根据组播MAC地址复制数据包到多个端口

setsockopt

setsockopt函数

头文件:#include <sys/socket.h>

函数原型:int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);

参数:

•sockfd目标套接字描述符,表示需要配置的套接字

•level选项层级(如SOL_SOCKET、IPPROTO_IP)

•optname选项名称(如SO_REUSEADDR、IP_ADD_MEMBERSHIP)

•optval指向选项值的指针,类型和长度需与optname匹配

•optlenoptval指向的数据长度

返回值:成功返回0,失败返回非0数据

广播

广播:一对所有通信,数据包发送到同一网络内的所有主机

流程与各层职责:

应用层

•发送端:调用setsockopt()启用广播选项(SO_BROADCAST)

•调用sendto()发送数据到广播地址(如255.255.255.255)

传输层

•封装UDP头部:目标端口为广播端口(如9999)

•接收端无需加入组,但需监听指定端口

网络层

•封装IP头部:目标IP为广播地址(受限广播255.255.255.255或定向广播192.168.1.255)

•受限广播仅在本局域网内传播,路由器默认不转发

•定向广播可跨子网(需路由器支持,通常被禁用)

数据链路层

•广播MAC地址:FF:FF:FF:FF:FF:FF

•交换机将广播包泛洪到所有端口(除源端口)

相关推荐
无足鸟ICT12 分钟前
【RHCA+】查看变量
linux·运维·服务器
Kina_C22 分钟前
Linux DNS 服务器-从高速缓存到辅助 DNS 部署指南
linux·运维·服务器·dns
suaizai_35 分钟前
TypeScript 7 正式发布!Vue 暂被 “拒之门外“ !!!
linux·运维·ubuntu
2401_873479401 小时前
SOC告警日志中IP归属不明怎么办?部署IP离线库三步提升响应效率
网络·网络协议·tcp/ip
慕伏白2 小时前
【慕伏白】Linux 系统如何根据端口号关闭进程
linux·运维·服务器
letisgo52 小时前
VMware Workstation + Ubuntu 26.04 LTS 小白运维部署手册
linux·运维·ubuntu
蓝创工坊Blue Foundry2 小时前
图片文字提取到 Excel:批量任务如何先定义要交付的字段
运维·服务器·开发语言·数据库·自动化·ocr·excel
IT探索2 小时前
Linux 查找文件指令总结
linux·算法
晚风吹长发2 小时前
Docker使用——Docker容器及相关命令
linux·运维·服务器·docker·容器·架构
电子科技圈2 小时前
先进封装、芯粒架构和3D集成——先进异构集成亟需兼具标准化与定制化能力的互联及总线IP解决方案
tcp/ip·设计模式·架构·软件构建·代码规范·设计规范