在 C 语言网络编程中,除了基础的 socket
、bind
、listen
、accept
、connect
、send
和 recv
之外,还有许多高级函数用于更高效地管理网络通信。本文将介绍 fcntl
、getpeername
、getsockname
、getsockopt
、ioctl
、read
、socketpair
、write
、getprotoent
以及 select
、poll
、epoll
等重要函数,并提供示例代码。
1. 高级网络编程函数概述
函数名 | 作用 |
---|---|
fcntl | 控制文件描述符的属性,如非阻塞模式 |
getpeername | 获取已连接套接字的对端地址 |
getsockname | 获取本地套接字地址 |
getsockopt | 获取套接字选项 |
setsockopt | 设置套接字选项,如超时、缓冲区大小等 |
ioctl | 设备控制,如设置非阻塞模式 |
read / write | 直接对套接字进行读写 |
socketpair | 创建一对相互连接的套接字 |
getprotoent | 获取协议信息 |
recvmmsg / sendmmsg | 批量接收/发送多个消息 |
cmsg | 发送和接收辅助数据 |
sockatmark | 检测带外数据 |
sendfile | 在文件和套接字之间高效传输数据 |
select | 监听多个文件描述符,等待可读/可写事件 |
poll | 类似 select ,但支持更多事件 |
epoll | 高效管理多个文件描述符的事件 |
address_families | 介绍地址族,如 AF_INET 、AF_INET6 等 |
ip / ipv6 | 解析 IP 层协议 |
tcp / udp | 解析 TCP/UDP 传输层协议 |
unix | 解析 Unix 域套接字 |
2. 示例代码
2.1 fcntl
设置非阻塞模式
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
void set_nonblocking(int sockfd) {
int flags = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
}
2.2 getpeername
获取对端地址
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
void print_peer_info(int sockfd) {
struct sockaddr_in addr;
socklen_t addr_len = sizeof(addr);
getpeername(sockfd, (struct sockaddr*)&addr, &addr_len);
printf("Connected to %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
}
2.3 getsockopt
获取缓冲区大小
#include <stdio.h>
#include <sys/socket.h>
void print_recv_buffer_size(int sockfd) {
int size;
socklen_t len = sizeof(size);
getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &size, &len);
printf("Receive buffer size: %d bytes\n", size);
}
2.4 sendfile
发送文件
#include <sys/sendfile.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
void send_file(int sockfd, const char *filename) {
int filefd = open(filename, O_RDONLY);
off_t offset = 0;
struct stat stat_buf;
fstat(filefd, &stat_buf);
sendfile(sockfd, filefd, &offset, stat_buf.st_size);
close(filefd);
}
2.5 epoll
监听多个套接字
#include <sys/epoll.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
void monitor_sockets(int sockfd1, int sockfd2) {
int epfd = epoll_create1(0);
struct epoll_event ev1 = {.events = EPOLLIN, .data.fd = sockfd1};
struct epoll_event ev2 = {.events = EPOLLIN, .data.fd = sockfd2};
epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd1, &ev1);
epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd2, &ev2);
struct epoll_event events[2];
int nfds = epoll_wait(epfd, events, 2, -1);
for (int i = 0; i < nfds; i++) {
printf("Socket %d is ready to read\n", events[i].data.fd);
}
close(epfd);
}
3. 结论
本文介绍了 C 语言高级网络编程中常用的函数,并提供了相应示例代码。不同函数在不同场景下发挥作用,比如 fcntl
设置非阻塞、getsockopt
获取选项、epoll
监听多个连接等。掌握这些函数有助于编写更高效的网络应用。
更多详细信息,可以参考 Linux 手册。
如果你有任何问题或建议,欢迎留言讨论!