Linux Socket 网络编程学习笔记

一、Socket 是什么

Socket 是一套网络编程接口,把网络通信抽象成文件描述符,可以像读写文件一样收发网络数据。

  • AF_INET:IPv4 协议
  • SOCK_STREAM:TCP 流式套接字
  • SOCK_DGRAM:UDP 数据报套接字

二、通用基础 API

1. socket 创建套接字

c 复制代码
int socket(int domain, int type, int protocol);
  • domain:协议族,AF_INET 代表 IPv4
  • type:套接字类型,SOCK_STREAM(TCP) / SOCK_DGRAM(UDP)
  • protocol:协议编号,填 0 自动匹配
  • 返回值:成功返回套接字文件描述符;失败返回 -1

TCP:socket(AF_INET, SOCK_STREAM, 0)

UDP:socket(AF_INET, SOCK_DGRAM, 0)

2. bind 绑定 IP 与端口

c 复制代码
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • sockfd:socket 返回的文件描述符
  • addr:地址结构体,实际传 struct sockaddr_in,需要强制转换 (struct sockaddr *)&var
  • addrlen:地址结构体大小 sizeof(struct sockaddr_in)
  • 返回:成功 0,失败 -1

✅ 服务端必须 bind;客户端 TCP 一般不需要 bind,内核自动分配临时端口。

INADDR_ANY:监听本机所有网卡,必须套 htonl(INADDR_ANY)。

3. connect 发起连接(TCP 客户端)

c 复制代码
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • 功能:向服务端发起 TCP 连接请求,触发三次握手。
  • sockfd:客户端 socket fd
  • addr:目标服务端地址(IP、端口)
  • addrlen:地址结构体大小
  • 返回:成功返回 0;失败返回 -1

UDP 也可以调用 connect,但不会产生网络报文,仅仅在内核记录对端地址,后续可以直接 send/recv,不用 sendto/recvfrom。

4. send 发送数据(TCP)

c 复制代码
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
  • sockfd:通信文件描述符(accept 返回 cfd)
  • buf:待发送数据缓冲区首地址
  • len:想要发送的数据字节长度
  • flags:标志位,日常填 0
  • 返回值:成功返回实际发送字节数;失败 -1

send 不保证全部发完;返回值小于 len 属于正常现象,业务代码建议循环发送。

5. recv 接收数据(TCP)

c 复制代码
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
  • buf:接收缓冲区
  • len:缓冲区最大可接收字节
  • flags:默认 0
  • 返回:
    *

    0:收到的字节数量

    • 0:对端关闭连接(TCP 断开)
    • -1:出错

⚠️ 考试高频考点:recv 返回 0 代表对方关闭 socket,不是没有数据。

6. listen 设置监听(TCP 服务端)

c 复制代码
int listen(int sockfd, int backlog);
  • sockfd:已经 bind 过的 socket
  • backlog:未处理连接请求队列的最大长度,并发连接排队上限。
  • 返回:成功 0,失败 -1

socket→bind→listen 顺序不能颠倒。listen 把套接字从主动套接字变成被动监听套接字,等待别人来连接。

7. accept 接受客户端连接(TCP 服务端)

c 复制代码
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  • sockfd:listen 之后的监听套接字
  • addr:输出参数,保存客户端的 IP 端口信息,不需要可以填 NULL
  • addrlen:输入输出参数,传入结构体大小;调用结束返回真实客户端地址长度
  • 返回值:成功返回新的通信文件描述符 cfd;失败 -1

重点区分两个 fd:

  • sockfd:监听套接字,一直用来等待新连接
  • cfd:accept 返回,专门和这一个客户端收发数据

三、UDP 专用接口 sendto / recvfrom

UDP 是无连接,没有 connect 建立连接,每次收发都要携带对方地址。

c 复制代码
// 发送
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
               const struct sockaddr *dest_addr, socklen_t addrlen);

// 接收
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                 struct sockaddr *src_addr, socklen_t *addrlen);
  • sendto:发送的时候带上目标 IP 端口
  • recvfrom:接收的时候,同时拿到发送方的地址信息
  • UDP 不存在返回 0 代表断开;UDP 无连接,对方退出你收不到任何通知。

如果你 UDP 调用 connect,之后可以直接使用 send/recv,不再需要 sendto/recvfrom。

四、地址结构体 sockaddr_in

c 复制代码
struct sockaddr_in {
    sa_family_t    sin_family;   // 协议族 AF_INET
    in_port_t      sin_port;     // 端口,**网络字节序 htons()**
    struct in_addr sin_addr;     // IPv4 地址结构体
    char           sin_zero[8];  // 占位填充,置 0
};

struct in_addr {
    in_addr_t s_addr; // 32 位 IP,网络大端
};

赋值示例

c 复制代码
struct sockaddr_in ser;
ser.sin_family = AF_INET;
ser.sin_port = htons(8888);
ser.sin_addr.s_addr = inet_addr("192.168.1.100");

易错:inet_addr() 返回已经是网络大端,不要再套 htonl!

五、TCP 与 UDP 对比

项目 TCP UDP
连接 面向连接,三次握手建立连接 无连接,直接发数据包
可靠性 可靠,丢包重传、有序 不可靠,不保证到达、不保证顺序
数据边界 字节流,没有消息边界 数据报,保留消息边界
开销 大 小
典型 API socket-bind-listen-accept-connect-send-recv socket-bind-sendto-recvfrom

UDP 头部简要

UDP 头部 4 个字段:源端口、目的端口、数据包长度、校验和,之后直接携带业务数据。特点:机制简单,资源开销小,不可靠。

TCP 三次握手简要

  1. 客户端发送 SYN 报文,请求建立连接
  2. 服务端返回 SYN+ACK 报文
  3. 客户端回复 ACK,连接正式建立,之后传输业务数据

六、TCP 完整调用流程

服务端

text 复制代码
socket() → bind() → listen() → accept()阻塞等待连接 → send()/recv() → close()

客户端

text 复制代码
socket() → connect() → send()/recv() → close()

七、高频坑点总结

  1. TCP recv 返回 0 = 对方关闭连接;UDP recvfrom 永远不会返回 0 代表断开。
  2. sin_port 端口必须 htons() 转为网络字节序。
  3. accept 第二个参数是输出参数,用来拿到客户端 IP 端口,不需要可以填 NULL。
  4. listen 只是开启监听,不会接收连接;真正获取连接靠 accept。
  5. send 返回值不等于你传入 len,不一定全部发送完成,需要循环处理。
  6. UDP 无连接,对方进程退出,本程序不会收到任何通知。
相关推荐
2401_868534782 小时前
数据交换方式
服务器·网络
艾芯微科技2 小时前
钰泰 ETA6973PQ3Y|QFN3×3 2A 同步降压 Buck,I2C 可配置多档输出,动态调压 PMIC
网络·单片机·嵌入式硬件·fpga开发·集成测试·51单片机
默|笙2 小时前
【Linux网络】_udp_socket(认识)
linux·网络·udp
程序员梅雨2 小时前
ZooKeeper面经总结
java·大数据·linux·分布式·后端·zookeeper·中间件
lingran__2 小时前
Linux进程万字详解(二)|进程状态深度剖析:调度队列、内核链表、D状态设计哲学、僵尸孤儿进程与Slab机制
linux·进程管理·内核链表·pcb·僵尸进程·孤儿进程·进程状态
2401_868534783 小时前
以太网物理层标准
服务器·网络
2601_951615203 小时前
网站模板 网站网页模板下载
前端·网络·html
PC2005-cloud3 小时前
Mysql学习笔记:InnoDB Cluster 集群从零搭建实战,基于 Docker 实现高可用读写分离架构
笔记·学习·mysql
小陈phd3 小时前
深入理解agent学习笔记(七)——动态提示词与Skills
笔记·学习
我命由我123453 小时前
田野笔记极简理解
经验分享·笔记·学习·职场和发展·求职招聘·职场发展·学习方法