下面我将分最常见的几种情况来解释如何“发送数据”:

(图片来源网络,侵删)
- 网络编程:使用
send()或write()函数在套接字上发送数据。 - 文件操作:使用
fwrite()函数将数据写入文件。 - 标准输出:使用
printf()或puts()函数将数据发送到控制台(屏幕)。
网络编程中的数据发送
这是最常见与“发送数据”相关的场景,当你编写一个客户端/服务器程序时,客户端需要向服务器发送请求,服务器需要向客户端发送响应。
这里我们使用的是 Berkeley Sockets (套接字) API,它在所有主流操作系统上都是可用的。
核心函数:send()
send() 函数用于通过一个已连接的套接字发送数据。
#include <sys/socket.h> ssize_t send(int sockfd, const void *buf, size_t len, int flags);
参数说明:

(图片来源网络,侵删)
sockfd: 你想要发送数据的套接字文件描述符,你可以把它想象成一个已经建立好的“通信管道”。buf: 一个指向你要发送的数据的指针,通常是字符数组或结构体的地址。len: 你想要发送的数据的长度(以字节为单位)。flags: 发送标志,通常设置为0,表示使用默认的发送方式(阻塞发送)。
返回值:
- 成功时,返回实际发送的字节数。
- 出错时,返回
-1,并设置errno来表示具体的错误。
完整示例:客户端发送字符串到服务器
这个例子将展示一个简单的 TCP 客户端,它连接到服务器并发送一条消息 "Hello, Server!"。
代码:client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> // 用于 close()
#include <sys/socket.h>
#include <netinet/in.h> // 用于 sockaddr_in 结构体
#include <arpa/inet.h> // 用于 inet_addr()
int main() {
int sockfd;
struct sockaddr_in server_addr;
// 1. 创建套接字
// AF_INET 表示使用 IPv4
// SOCK_STREAM 表示使用 TCP
// 0 表示使用默认的协议
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
// 2. 设置服务器地址信息
server_addr.sin_family = AF_INET; // 地址族
server_addr.sin_port = htons(8080); // 端口号,htons 将主机字节序转换为网络字节序
// 将 "127.0.0.1" (本机地址) 转换为网络地址格式
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
// 3. 连接到服务器
if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("Connection failed");
exit(EXIT_FAILURE);
}
printf("Connected to server.\n");
// 4. 准备要发送的数据
char message[] = "Hello, Server!";
int message_len = strlen(message);
// 5. 发送数据
// 使用 send() 函数
int bytes_sent = send(sockfd, message, message_len, 0);
if (bytes_sent < 0) {
perror("Send failed");
exit(EXIT_FAILURE);
}
printf("Sent %d bytes: %s\n", bytes_sent, message);
// 6. 关闭套接字
close(sockfd);
return 0;
}
如何编译和运行:
-
服务器端代码 (需要配合一个简单的服务器程序,这里省略,你可以用
netcat简单模拟):# 在一个终端运行 netcat 监听 8080 端口作为简易服务器 nc -l 8080
-
客户端代码:
# 编译客户端 gcc client.c -o client # 运行客户端 ./client
预期输出 (在客户端终端):
Connected to server.
Sent 14 bytes: Hello, Server!
预期输出 (在服务器/netcat 终端):
Hello, Server!
文件操作中的数据发送
这里的“发送”指的是将数据从内存写入到硬盘上的文件。
核心函数:fwrite()
fwrite() 函数用于将一块数据写入到文件流中。
#include <stdio.h> size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
参数说明:
ptr: 指向要写入数据的内存块的指针。size: 每个数据项的大小(以字节为单位)。nmemb: 要写入的数据项的数量。stream: 指向FILE对象的指针,该对象标识了要写入的文件。
返回值:
- 成功时,返回实际写入的数据项的数量(不是字节数)。
- 出错时,返回一个小于
nmemb的值。
完整示例:将结构体数组写入文件
这个例子将一个包含学生信息的结构体数组写入到一个二进制文件中。
代码:write_file.c
#include <stdio.h>
#include <stdlib.h>
// 定义一个学生结构体
struct Student {
int id;
char name[50];
float score;
};
int main() {
// 1. 准备要发送(写入)的数据
struct Student students[] = {
{101, "Alice", 95.5},
{102, "Bob", 88.0},
{103, "Charlie", 76.5}
};
int num_students = sizeof(students) / sizeof(students[0]);
// 2. 以二写模式打开文件
// "wb" 表示 "write binary" (二进制写入)
FILE *file = fopen("students.dat", "wb");
if (file == NULL) {
perror("Failed to open file for writing");
return EXIT_FAILURE;
}
// 3. 发送(写入)数据
// sizeof(struct Student) 是每个学生结构体的大小
// num_students 是学生数量
size_t items_written = fwrite(students, sizeof(struct Student), num_students, file);
if (items_written != num_students) {
perror("Failed to write all data to file");
fclose(file);
return EXIT_FAILURE;
}
printf("Successfully wrote %zu students to file.\n", items_written);
// 4. 关闭文件
fclose(file);
return 0;
}
如何编译和运行:
gcc write_file.c -o write_file ./write_file
运行后,会在当前目录下生成一个 students.dat 文件,里面包含了二进制的学生数据。
标准输出中的数据发送
这是最基础的方式,将数据“发送”到你的屏幕上。
核心函数:printf()
printf() 函数根据格式化字符串将数据发送到标准输出流 (stdout)。
#include <stdio.h> int printf(const char *format, ...);
简单示例:
#include <stdio.h>
int main() {
int age = 30;
char name[] = "David";
// 发送格式化字符串到屏幕
printf("Name: %s, Age: %d\n", name, age);
return 0;
}
输出:
Name: David, Age: 30
| 场景 | 核心函数 | 功能 | 头文件 |
|---|---|---|---|
| 网络通信 | send() |
通过套接字发送数据 | sys/socket.h |
| 文件操作 | fwrite() |
将数据块写入文件流 | stdio.h |
| 标准输出 | printf() |
将格式化数据发送到屏幕 | stdio.h |
当你在 C 语言中需要“发送数据”时,首先要明确你的目标是什么:
- 是通过网络发送给另一个程序? -> 使用
send() - 是保存到硬盘上的一个文件? -> 使用
fwrite() - 是显示在用户的屏幕上? -> 使用
printf()
