Socket 网络编程是构建网络应用的基础,核心 API 涵盖了套接字创建、地址绑定、连接管理、数据传输等关键操作。以下是主要函数的功能说明、参数解析及示例代码:
1. 套接字创建与配置
socket()
:创建套接字
- 功能:创建通信端点,返回套接字描述符。
- 原型:
int socket(int domain, int type, int protocol);
- 参数:
domain
:地址族(如AF_INET
(IPv4)、AF_INET6
(IPv6))。type
:套接字类型(SOCK_STREAM
(TCP)、SOCK_DGRAM
(UDP))。protocol
:协议(通常设为0
,自动选择)。
- 示例:
int tcp_sock = socket(AF_INET, SOCK_STREAM, 0); // TCP 套接字 int udp_sock = socket(AF_INET, SOCK_DGRAM, 0); // UDP 套接字
bind()
:绑定地址和端口
- 功能:将套接字与本地地址和端口绑定(服务端使用)。
- 原型:
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
- 示例(IPv4):
struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(8080); // 端口转换为网络字节序 addr.sin_addr.s_addr = INADDR_ANY; // 绑定所有接口 bind(sock, (struct sockaddr*)&addr, sizeof(addr));
2. 连接管理
listen()
:监听连接(TCP 服务端)
- 功能:设置服务端套接字为监听状态,等待客户端连接。
- 原型:
int listen(int sockfd, int backlog);
- 参数:
backlog
:等待连接队列的最大长度(如5
)。
- 示例:
listen(sock, 5); // 允许最多5个等待连接
connect()
:建立连接(TCP 客户端)
- 功能:客户端主动连接到服务端。
- 原型:
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
- 示例:
struct sockaddr_in serv_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(80); // HTTP 端口 inet_pton(AF_INET, "93.184.216.34", &serv_addr.sin_addr); // example.com connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
accept()
:接受连接(TCP 服务端)
- 功能:接受客户端连接,返回新的套接字用于通信。
- 原型:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
- 示例:
struct sockaddr_in client_addr; socklen_t addr_len = sizeof(client_addr); int client_sock = accept(sock, (struct sockaddr*)&client_addr, &addr_len);
3. 数据传输
send()
和 recv()
:面向连接(TCP)
-
send()
:发送数据。ssize_t send(int sockfd, const void *buf, size_t len, int flags);
-
recv()
:接收数据。ssize_t recv(int sockfd, void *buf, size_t len, int flags);
- 示例:
char msg[] = "Hello, Server!"; send(client_sock, msg, strlen(msg), 0); // 发送数据 char buffer[1024]; ssize_t bytes = recv(client_sock, buffer, sizeof(buffer), 0); // 接收数据
sendto()
和 recvfrom()
:无连接(UDP)
-
sendto()
:发送数据到指定地址。ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
-
recvfrom()
:接收数据并获取发送方地址。ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
- 示例:
// 发送数据到目标地址 struct sockaddr_in dest_addr; dest_addr.sin_family = AF_INET; dest_addr.sin_port = htons(8080); inet_pton(AF_INET, "192.168.1.2", &dest_addr.sin_addr); sendto(udp_sock, msg, strlen(msg), 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr)); // 接收数据并获取来源地址 struct sockaddr_in src_addr; socklen_t addr_len = sizeof(src_addr); recvfrom(udp_sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&src_addr, &addr_len);
4. 关闭连接
close()
:关闭套接字
- 功能:释放套接字资源。
- 原型:
int close(int sockfd);
- 示例:
close(client_sock); // 关闭客户端套接字 close(sock); // 关闭服务端套接字
5. 错误处理
- 检查返回值:所有函数返回
-1
表示失败。 - 错误信息:使用
perror()
或strerror(errno)
获取错误描述。if (connect(sock, ...) == -1) { perror("connect failed"); exit(EXIT_FAILURE); }
代码示例:TCP 服务端与客户端
服务端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main() {
int server_fd, client_sock;
struct sockaddr_in addr;
char buffer[1024] = {0};
// 1. 创建 TCP 套接字
server_fd = socket(AF_INET, SOCK_STREAM, 0);
// 2. 绑定地址和端口
addr.sin_family = AF_INET;
addr.sin_port = htons(8080);
addr.sin_addr.s_addr = INADDR_ANY;
bind(server_fd, (struct sockaddr*)&addr, sizeof(addr));
// 3. 监听连接
listen(server_fd, 5);
// 4. 接受连接
client_sock = accept(server_fd, NULL, NULL);
// 5. 接收并响应数据
read(client_sock, buffer, sizeof(buffer));
printf("Client: %s\n", buffer);
send(client_sock, "Hello from server!", 18, 0);
// 6. 关闭连接
close(client_sock);
close(server_fd);
return 0;
}
客户端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main() {
int sock;
struct sockaddr_in serv_addr;
// 1. 创建 TCP 套接字
sock = socket(AF_INET, SOCK_STREAM, 0);
// 2. 连接服务端
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(8080);
inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr);
connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
// 3. 发送并接收数据
send(sock, "Hello from client!", 18, 0);
char buffer[1024] = {0};
read(sock, buffer, sizeof(buffer));
printf("Server: %s\n", buffer);
// 4. 关闭连接
close(sock);
return 0;
}
总结
API | 用途 | TCP | UDP |
---|---|---|---|
socket() | 创建套接字 | ✔️ | ✔️ |
bind() | 绑定地址和端口 | ✔️ | ✔️ |
listen() | 监听连接(服务端) | ✔️ | ❌ |
accept() | 接受连接(服务端) | ✔️ | ❌ |
connect() | 建立连接(客户端) | ✔️ | ✔️* |
send() /recv() | 面向连接数据传输 | ✔️ | ❌ |
sendto() /recvfrom() | 无连接数据传输 | ❌ | ✔️ |
close() | 关闭套接字 | ✔️ | ✔️ |
注:UDP 的 connect()
用于固定通信地址,但非必需。
掌握这些核心 API 后,您可构建 TCP/UDP 客户端和服务端程序,处理网络通信中的连接、数据传输和错误场景。