用C语言写的Socket客户端,怎么接收数据库传过来的数据,有点搞不懂咋整
- 问答
- 2026-01-16 14:32:07
- 4
你说用C语言写了个Socket客户端,但不知道怎么接收从数据库传过来的数据,感觉有点懵,这个事儿其实得拆开看,因为这里有个关键点:你的C语言客户端并不是直接和数据库“对话”的,数据库(比如MySQL、PostgreSQL)有自己一套复杂的通信协议,你的C语言程序要是想直接连上去,你得去实现它那个协议,那可太麻烦了,一般没人这么干。
通常的做法是,在数据库和你的C语言客户端中间,加一个“中间人”,这个中间人一般是一个服务端程序,它负责做两件事:
- 它用专门的方法(比如各种数据库连接库)去和数据库打交道,执行SQL语句,拿到数据。
- 它自己也是一个Socket服务端,用简单的、你能轻松处理的协议,等着你的C语言客户端来连接,然后把从数据库拿到的数据“转发”给你。
这么一来,你的问题就变成了:我的C语言Socket客户端,怎么接收另一个服务端程序发来的数据? 这就简单多了,下面我直接说这个该咋整。
第一步:建立连接 这个你肯定已经会了,就是常规的Socket客户端三步走。
- 创建一个Socket,用
socket()函数。 - 设置服务端的地址和端口,就是那个“中间人”服务端的IP和端口,填到一个
struct sockaddr_in结构体里。 - 连接上去,用
connect()函数。
连接成功之后,你就拿到了一条通往服务端的“数据管道”。
第二步:最关键的一步——循环接收数据 数据从服务端传过来,可能不是一下子全部送到的,它可能像水流一样,断断续续地传过来,比如数据库里有1万条记录,服务端可能分10次、每次1000条地发给你,所以你绝对不能只调用一次接收函数就觉得完事儿了。
这里你要用到一个核心函数:recv()。

recv() 函数的工作方式是:它会把当前Socket接收缓冲区里已经到达的数据,拷贝到你指定的那个内存块(我们叫它缓冲区)里,你需要自己准备一个数组(char buffer[1024];)来当这个缓冲区。
你怎么知道数据什么时候收完了呢?这里有三个关键点:
-
检查
recv()的返回值:这是最重要的,这个返回值告诉你实际接收到了多少个字节的数据。- 如果返回值 大于0,说明成功收到了这么多字节的数据,你需要赶紧处理这些数据(比如打印出来,或者存起来)。
- 如果返回值 等于0,这代表对方(服务端)已经优雅地关闭了连接,这意味着数据已经全部发送完毕了,这时候你的循环就应该结束了。
- 如果返回值 等于-1,说明出错了,你需要检查错误代码(
errno)看看是啥问题,然后进行错误处理。
-
协议约定:怎么判断一个“数据包”的边界? 服务端怎么告诉你“我一句话说完啦”?这需要你们事先约定好一个简单的“协议”,常见的办法有:

- 用特定的结束符:比如约定每条数据后面都跟一个换行符
\n,你收到数据后,就在缓冲区里找这个\n,找到了就说明一条完整的数据收到了。 - 定长数据:如果每条数据长度都一样,那就很简单,收满固定长度就行。
- 长度头+数据体:这是最靠谱的方法,服务端先发送一个固定长度的数字(比如4个字节),告诉你它后面要发送的数据体有多长,你的客户端就先收4个字节,解析出长度N,然后再循环收,直到收满N个字节,这样就保证了一个完整数据包不会被拆散或粘在一起。
- 用特定的结束符:比如约定每条数据后面都跟一个换行符
-
处理“粘包”问题:因为TCP是流式的,没有消息边界,你一次
recv()调用,可能会收到大半条消息,也可能收到一条半消息,所以你准备好的那个缓冲区,可能里面装着不完整的“半句话”,这就是为什么你需要根据上面约定的协议,来从字节流中切分出完整的应用层消息。
第三步:处理和解析数据
服务端发给你的数据,通常是你和它约定好的格式,最简单的就是纯文本,比如用逗号隔开的(CSV格式):
1,张三,25,北京\n
2,李四,30,上海\n
你收到这样的字符串后,需要用C语言里的字符串处理函数,strtok() 来分割字符串,然后把每个字段转换成你需要的数据类型(比如把“25”这个字符串转换成整数25)。
复杂一点的可能用JSON或XML格式,那你就需要找一个现成的C语言库(比如cJSON)来帮你解析了。
一个简单的代码思路(伪代码风格)
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
int main() {
// ... 省略了创建socket和connect的代码,假设 sockfd 是已经连接成功的socket描述符
char buffer[1024]; // 准备一个缓冲区
int received_bytes;
char* complete_message; // 用来指向一个完整的消息
char* saveptr; // 给strtok_r用的
// 循环接收,直到服务端断开连接
while ((received_bytes = recv(sockfd, buffer, sizeof(buffer) - 1, 0)) > 0) {
buffer[received_bytes] = '\0'; // 手动加上字符串结束符,方便后面处理
// 假设我们约定用换行符 \n 分隔每条消息
complete_message = strtok_r(buffer, "\n", &saveptr);
while (complete_message != NULL) {
// 这里就拿到一条完整的数据了,"1,张三,25,北京"
printf("收到一条完整数据:%s\n", complete_message);
// 接下来可以解析这条数据
// 比如用 strtok_r(complete_message, ",") 来分割字段
// 取下一条消息
complete_message = strtok_r(NULL, "\n", &saveptr);
}
}
if (received_bytes == 0) {
printf("服务端关闭了连接,\n");
} else if (received_bytes == -1) {
perror("recv出错");
}
close(sockfd);
return 0;
}
你别想着C客户端直接收数据库的数据,那样太难,正确的路子是让一个服务端帮你从数据库取数据,然后你的C客户端只管用 recv() 函数循环地从服务端收,收的时候要时刻检查返回值,并且根据你们约定好的“暗号”(比如换行符)来把收到的字节流切成一段段有意义的“话”,切出来之后,再按照约定的格式(比如用逗号隔开)去解析每一句话,就能得到你想要的数据了,核心就是 recv() 循环和协议解析,多试几次,慢慢就明白了。
本文由凤伟才于2026-01-16发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://www.haoid.cn/wenda/81845.html
