C、sendfile() 和 send() 区别

作者:编程家 分类: c++ 时间:2025-08-25

C、sendfile() 和 send() 是在Linux系统中用于网络通信的两个函数。它们的作用都是发送数据,但在实际应用中有一些区别。

sendfile() 函数用于在两个文件描述符之间直接传输数据,无需将数据从用户空间复制到内核空间。它适用于发送大量数据,比如文件的传输。sendfile() 函数的原型如下:

c

#include

ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

send() 函数则是用于发送数据到已连接的套接字。它将数据从用户空间复制到内核空间,并通过套接字发送出去。send() 函数的原型如下:

c

#include

#include

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

在发送数据方面,sendfile() 函数比 send() 函数更高效。因为 sendfile() 函数避免了数据复制的过程,直接在内核空间中进行操作,从而节省了内存和CPU的开销。而 send() 函数则需要将数据从用户空间复制到内核空间,增加了一次数据复制的过程。

sendfile() 适用于文件传输

sendfile() 函数适用于需要在两个文件描述符之间传输数据的场景。一个典型的应用是在网络服务器中传输静态文件。例如,一个网站的图片文件可以通过 sendfile() 函数直接从磁盘读取并发送到客户端,而无需在用户空间和内核空间之间复制数据。

下面是一个简单的示例代码:

c

#include

#include

#include

#include

#include

#include

#include

#include

#define BUFFER_SIZE 4096

int main() {

int server_fd, client_fd;

struct sockaddr_in server_addr, client_addr;

socklen_t client_len;

int file_fd;

struct stat stat_buf;

off_t offset = 0;

ssize_t sent_bytes;

// 创建服务器套接字

server_fd = socket(AF_INET, SOCK_STREAM, 0);

if (server_fd < 0) {

perror("socket");

return -1;

}

// 绑定服务器地址和端口

server_addr.sin_family = AF_INET;

server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

server_addr.sin_port = htons(8080);

if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {

perror("bind");

return -1;

}

// 监听连接

if (listen(server_fd, 10) < 0) {

perror("listen");

return -1;

}

// 接受客户端连接

client_len = sizeof(client_addr);

client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_len);

if (client_fd < 0) {

perror("accept");

return -1;

}

// 打开文件

file_fd = open("example.txt", O_RDONLY);

if (file_fd < 0) {

perror("open");

return -1;

}

// 获取文件状态

fstat(file_fd, &stat_buf);

// 发送文件

sent_bytes = sendfile(client_fd, file_fd, &offset, stat_buf.st_size);

if (sent_bytes < 0) {

perror("sendfile");

return -1;

}

// 关闭文件和套接字

close(file_fd);

close(client_fd);

close(server_fd);

return 0;

}

send() 适用于网络通信

send() 函数适用于已连接的套接字之间的数据传输。它可以用于发送各种类型的数据,包括文本、二进制等。

下面是一个简单的示例代码:

c

#include

#include

#include

#include

#include

#define BUFFER_SIZE 4096

int main() {

int server_fd, client_fd;

struct sockaddr_in server_addr, client_addr;

socklen_t client_len;

char buffer[BUFFER_SIZE];

ssize_t sent_bytes;

// 创建服务器套接字

server_fd = socket(AF_INET, SOCK_STREAM, 0);

if (server_fd < 0) {

perror("socket");

return -1;

}

// 绑定服务器地址和端口

server_addr.sin_family = AF_INET;

server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

server_addr.sin_port = htons(8080);

if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {

perror("bind");

return -1;

}

// 监听连接

if (listen(server_fd, 10) < 0) {

perror("listen");

return -1;

}

// 接受客户端连接

client_len = sizeof(client_addr);

client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_len);

if (client_fd < 0) {

perror("accept");

return -1;

}

// 发送数据

strcpy(buffer, "Hello, world!");

sent_bytes = send(client_fd, buffer, strlen(buffer), 0);

if (sent_bytes < 0) {

perror("send");

return -1;

}

// 关闭套接字

close(client_fd);

close(server_fd);

return 0;

}

在网络通信中,sendfile() 和 send() 是两个常用的函数。sendfile() 适用于在文件描述符之间传输数据,send() 适用于已连接的套接字之间传输数据。sendfile() 函数更高效,可以避免数据复制过程,适用于大文件传输。而 send() 函数则适用于各种类型的数据传输。在实际应用中,我们需要根据具体场景选择合适的函数来发送数据。