Linux 的 TCP 网络编程常用API
在 Linux 的 TCP 网络编程中,常用的 API 主要涉及套接字(Socket)的创建、绑定、监听、连接、数据传输和关闭等操作。以下是这些关键 API 的详细解释和示例:
1. socket()
- 创建套接字
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
- 功能:创建一个新的套接字。
- 参数:
domain
:协议族,如AF_INET
(IPv4)、AF_INET6
(IPv6)。type
:套接字类型,如SOCK_STREAM
(TCP)、SOCK_DGRAM
(UDP)。protocol
:协议类型,通常设为0
(自动选择)。
- 返回值:成功返回套接字文件描述符,失败返回
-1
。 - 示例:
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {perror("socket creation failed");exit(EXIT_FAILURE);
}
2. bind()
- 绑定地址和端口
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
- 功能:将套接字绑定到特定的 IP 地址和端口(通常用于服务器)。
- 参数:
sockfd
:socket()
返回的套接字描述符。addr
:指向struct sockaddr
的指针,包含 IP 和端口信息。addrlen
:地址结构的长度。
- 返回值:成功返回
0
,失败返回-1
。 - 示例:
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY; // 绑定到所有本地接口
server_addr.sin_port = htons(8080); // 端口号if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {perror("bind failed");exit(EXIT_FAILURE);
}
3. listen()
- 开始监听连接
#include <sys/socket.h>
int listen(int sockfd, int backlog);
- 功能:将套接字设置为监听模式,等待客户端连接(仅用于 TCP 服务器)。
- 参数:
sockfd
:绑定的套接字描述符。backlog
:等待连接队列的最大长度(如5
)。
- 返回值:成功返回
0
,失败返回-1
。 - 示例:
if (listen(sockfd, 5) == -1) {perror("listen failed");exit(EXIT_FAILURE);
}
4. accept()
- 接受客户端连接
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
- 功能:从监听队列中接受一个客户端连接(阻塞调用)。
- 参数:
sockfd
:监听的套接字描述符。addr
:返回客户端的地址信息(可设为 ``)。addrlen
:地址结构的长度(传入传出参数)。
- 返回值:成功返回新的套接字描述符(用于通信),失败返回
-1
。 - 示例:
struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
int client_fd = accept(sockfd, (struct sockaddr *)&client_addr, &client_len);
if (client_fd == -1) {perror("accept failed");exit(EXIT_FAILURE);
}
5. connect()
- 连接到服务器
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
- 功能:客户端发起连接到服务器(仅用于 TCP 客户端)。
- 参数:
sockfd
:socket()
返回的套接字描述符。addr
:服务器的地址信息。addrlen
:地址结构的长度。
- 返回值:成功返回
0
,失败返回-1
。 - 示例:
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 服务器 IP
server_addr.sin_port = htons(8080); // 服务器端口if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {perror("connect failed");exit(EXIT_FAILURE);
}
6. send()
和 recv()
- 数据传输
#include <sys/socket.h>
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
- 功能:
send()
:发送数据到连接的套接字。recv()
:从连接的套接字接收数据。
- 参数:
sockfd
:通信的套接字描述符。buf
:数据缓冲区。len
:数据长度。flags
:特殊选项(通常设为0
)。
- 返回值:
- 成功返回实际发送/接收的字节数,失败返回
-1
。 - 返回
0
表示连接已关闭。
- 成功返回实际发送/接收的字节数,失败返回
- 示例:
char buffer[1024] = "Hello, Server!";
send(client_fd, buffer, strlen(buffer), 0);memset(buffer, 0, sizeof(buffer));
int bytes_received = recv(client_fd, buffer, sizeof(buffer), 0);
if (bytes_received > 0) {printf("Received: %s\n", buffer);
}
7. close()
- 关闭套接字
#include <unistd.h>
int close(int fd);
- 功能:关闭套接字描述符,释放资源。
- 参数:
fd
为套接字描述符。 - 返回值:成功返回
0
,失败返回-1
。 - 示例:
close(client_fd);
close(sockfd);
8. 其他常用 API
setsockopt()
:设置套接字选项(如超时、缓冲区大小)。getsockname()
/getpeername()
:获取本地或对端的地址信息。htonl()
/htons()
/ntohl()
/ntohs()
:主机字节序与网络字节序转换。
完整 TCP 服务器/客户端示例
服务器端
// 创建套接字 -> 绑定 -> 监听 -> 接受连接 -> 收发数据 -> 关闭 |
客户端
// 创建套接字 -> 连接服务器 -> 收发数据 -> 关闭 |
关键注意事项
- 错误处理:所有 API 调用后需检查返回值。
- 阻塞与非阻塞:默认阻塞,可通过
fcntl()
或setsockopt()
设为非阻塞。 - 多路复用:高并发场景使用
select()
、poll()
或epoll()
。 - 线程安全:多线程环境下需注意套接字描述符的共享问题