以下是 Linux 网络通信核心函数的详细参数说明及示例代码,涵盖 TCP/UDP 的关键接口:
**1. socket()
- 创建套接字
函数原型
c
复制代码
int socket(int domain, int type, int protocol);
参数说明
参数 |
说明 |
domain |
协议族:AF_INET (IPv4)、AF_INET6 (IPv6)、AF_UNIX (本地通信) |
type |
套接字类型:SOCK_STREAM (TCP)、SOCK_DGRAM (UDP) |
protocol |
通常填 0 ,由系统自动选择(如 TCP 或 UDP) |
示例
c
复制代码
// 创建 TCP 套接字
int tcp_sock = socket(AF_INET, SOCK_STREAM, 0);
if (tcp_sock == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
// 创建 UDP 套接字
int udp_sock = socket(AF_INET, SOCK_DGRAM, 0);
**2. bind()
- 绑定地址
函数原型
c
复制代码
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数说明
参数 |
说明 |
sockfd |
套接字描述符 |
addr |
指向 sockaddr_in 结构体的指针(存储 IP 和端口信息) |
addrlen |
地址结构体的长度(sizeof(struct sockaddr_in) ) |
示例
c
复制代码
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET; // IPv4
addr.sin_port = htons(8080); // 端口 8080(转换为网络字节序)
addr.sin_addr.s_addr = htonl(INADDR_ANY); // 绑定到所有本地 IP
if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
perror("bind");
close(sockfd);
exit(EXIT_FAILURE);
}
**3. listen()
- 监听连接(TCP)
函数原型
c
复制代码
int listen(int sockfd, int backlog);
参数说明
参数 |
说明 |
sockfd |
已绑定的套接字描述符 |
backlog |
等待连接队列的最大长度(通常设为 5~10) |
示例
c
复制代码
if (listen(sockfd, 5) == -1) {
perror("listen");
close(sockfd);
exit(EXIT_FAILURE);
}
**4. accept()
- 接受连接(TCP)
函数原型
c
复制代码
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数说明
参数 |
说明 |
sockfd |
处于监听状态的套接字描述符 |
addr |
用于保存客户端地址信息的结构体指针(可为 NULL ) |
addrlen |
地址结构体的长度指针(可为 NULL ) |
示例
c
复制代码
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");
close(sockfd);
exit(EXIT_FAILURE);
}
printf("Client connected from %s:%d\n",
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
**5. connect()
- 连接服务器(TCP/UDP)
函数原型
c
复制代码
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
示例(TCP)
c
复制代码
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);
server_addr.sin_addr.s_addr = inet_addr("192.168.1.100"); // 服务器 IP
if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
perror("connect");
close(sockfd);
exit(EXIT_FAILURE);
}
**6. send()
/ recv()
- 发送/接收数据(TCP)
函数原型
c
复制代码
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);
参数说明
参数 |
说明 |
sockfd |
已连接的套接字描述符 |
buf |
数据缓冲区指针 |
len |
数据长度 |
flags |
控制标志(通常填 0 ) |
示例
c
复制代码
// 发送数据
char *msg = "Hello, Server!";
if (send(client_fd, msg, strlen(msg), 0) == -1) {
perror("send");
}
// 接收数据
char buffer[1024];
ssize_t n = recv(client_fd, buffer, sizeof(buffer), 0);
if (n == -1) {
perror("recv");
} else if (n == 0) {
printf("Connection closed\n");
} else {
buffer[n] = '\0';
printf("Received: %s\n", buffer);
}
**7. sendto()
/ recvfrom()
- 发送/接收数据(UDP)
函数原型
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);
示例
c
复制代码
// UDP 发送数据到指定地址
struct sockaddr_in dest_addr;
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(8080);
dest_addr.sin_addr.s_addr = inet_addr("192.168.1.100");
sendto(udp_sock, "Hello", 5, 0,
(struct sockaddr*)&dest_addr, sizeof(dest_addr));
// UDP 接收数据并获取来源地址
struct sockaddr_in src_addr;
socklen_t src_len = sizeof(src_addr);
char buffer[1024];
recvfrom(udp_sock, buffer, sizeof(buffer), 0,
(struct sockaddr*)&src_addr, &src_len);
**8. close()
- 关闭套接字
函数原型
c
复制代码
int close(int sockfd);
示例
c
复制代码
close(client_fd); // 关闭客户端套接字
close(server_fd); // 关闭服务端套接字
**9. setsockopt()
- 设置套接字选项
函数原型
c
复制代码
int setsockopt(int sockfd, int level, int optname,
const void *optval, socklen_t optlen);
示例(设置地址重用)
c
复制代码
int reuse = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) {
perror("setsockopt");
}
完整 TCP 服务端示例
c
复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
int main() {
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
// 设置地址重用
int reuse = 1;
setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(8080);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(server_fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
perror("bind");
close(server_fd);
exit(EXIT_FAILURE);
}
if (listen(server_fd, 5) == -1) {
perror("listen");
close(server_fd);
exit(EXIT_FAILURE);
}
printf("Server listening on port 8080...\n");
while (1) {
struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
int client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &client_len);
if (client_fd == -1) {
perror("accept");
continue;
}
char *response = "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World!";
send(client_fd, response, strlen(response), 0);
close(client_fd);
}
close(server_fd);
return 0;
}
总结
- 函数协作流程 :
- TCP 服务端 :
socket()
→ bind()
→ listen()
→ accept()
→ send()/recv()
→ close()
- TCP 客户端 :
socket()
→ connect()
→ send()/recv()
→ close()
- UDP 通信 :
socket()
→ bind()
(可选) → sendto()/recvfrom()
→ close()
- 关键细节 :
- 字节序转换 :使用
htons()
, ntohs()
等函数处理端口和 IP 地址。
- 错误处理:所有函数调用后需检查返回值。
- 资源释放 :通信结束后必须调用
close()
关闭套接字。