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 无连接,对方进程退出,本程序不会收到任何通知。
相关推荐
牛马也想出海16 分钟前
海外社媒代理IP:TikTok、IG等6大社媒平台防封号IP选型指南
运维·服务器·网络·新媒体运营
昌原的儿子LEO21 分钟前
【Linux网络编程】TCP套接字核心函数详解|三次握手|send/recv/listen/accept接口梳理
linux·网络·tcp/ip
我爱cope22 分钟前
【计算机网络 | 网络层12:SDN:控制平面与数据平面分离意味着什么?】
网络·学习·计算机网络·平面
阿崽meitoufa25 分钟前
Prompt Engineering for Agent:让 Agent 稳定运行的提示词写法
网络·人工智能·microsoft
筝筝ba28 分钟前
extended/factory_reset.robot
linux·运维·服务器·网络·网络协议·p2p
网安小学生(兼顾数据库版)29 分钟前
CRA漏洞通报义务倒计时:9.11生效要求深度解读
网络·安全·web安全
wangduqiang74731 分钟前
如何借助AI申请专利不依靠代理机构
linux
优化Henry33 分钟前
5G网络切片之S-NSSAIlist相关参数解析
运维·服务器·网络·笔记·学习·信息与通信
子有内涵39 分钟前
【Linux】C++ 实现可扩展 TCP 服务器|回响、字典、远程命令
linux·运维·服务器