01 / 两端如何建立连接
Socket 是操作系统提供的通信接口。对于 TCP,服务端先绑定地址并等待连接,客户端再连接这个地址。建立连接后,两端都可以发送和接收字节。
服务端:socket → bind → listen → accept → recv / send → close
客户端:socket → connect → send / recv → close
accept() 返回一个新的连接描述符;原来的监听描述符继续接受其他连接。程序需要分别关闭它们。
02 / 常用 API
| 函数 | 作用 | 留意什么 |
socket() | 创建通信端点 | IPv4 TCP 常用 AF_INET、SOCK_STREAM。 |
bind() | 指定本地地址和端口 | 演示服务优先绑定 127.0.0.1,避免意外对公网开放。 |
listen() | 进入监听状态 | backlog 是待处理连接队列相关参数,并非总用户数。 |
accept() | 取出一条新连接 | 阻塞模式下会等待连接到达。 |
connect() | 连接远端地址 | 失败时检查地址、端口、路由和 errno。 |
send() / recv() | 写入 / 读取字节流 | 一次调用不保证传输完整应用消息。 |
close() | 释放描述符 | 包括失败路径,都需要正确清理。 |
03 / 连接本机端口的最小示例
这个程序仅建立连接,然后关闭。请先在本机 127.0.0.1:8080 启动你自己的 TCP 测试服务;没有监听服务时,连接失败是正常结果。
#include <arpa/inet.h>
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
int main(void) {
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1) { perror("socket"); return 1; }
struct sockaddr_in peer = {0};
peer.sin_family = AF_INET;
peer.sin_port = htons(8080);
if (inet_pton(AF_INET, "127.0.0.1", &peer.sin_addr) != 1) {
close(fd);
return 1;
}
if (connect(fd, (struct sockaddr *)&peer, sizeof peer) == -1) {
perror("connect");
close(fd);
return 1;
}
puts("connected");
close(fd);
return 0;
}
保存为 connect.c,使用 cc -Wall -Wextra -O2 connect.c -o connect 编译,再运行 ./connect。htons() 将端口转换为网络字节序;inet_pton() 将文字 IP 地址转换为二进制格式。
04 / 写真实程序前,再检查四件事
- 消息边界。TCP 是字节流。发送两次不代表接收端正好读取两次;用长度前缀或明确分隔符定义应用协议。
- 短读与短写。检查实际返回字节数,循环处理剩余数据。
recv() 返回 0 表示对端有序关闭。
- 错误与超时。区分
EINTR、非阻塞模式下的 EAGAIN 和不可恢复错误,为连接与读写设置超时策略。
- 资源与安全。连接数、缓冲区和消息长度都应有上限。TCP 本身不提供加密,敏感网络通信需要 TLS 等经过验证的安全协议。
进一步阅读:本机 man 2 socket、man 2 connect、man 2 recv。