情况:我在c中创建一个服务器守护程序,它接受多个同时连接,客户端将向服务器发送数据。我目前将每个客户端连接生成一个新线程。
问题:如果客户端非常快速地发送大量内容(例如,在不到一秒的时间内发送10行数据),服务器将看到前两行,而不是其他行
问题:如何“排队”来自客户端的数据(c中的recv
命令)?这是否需要select
或poll
?基本上,我想确保任何客户端都可以非常快速地发送大量数据,而不必担心任何内容被丢弃。如何实现这一目标?
示例代码 :(注意:下面的代码显然已被大量修改,特别是通过删除错误检查。我试图修改我的代码,以便使问题/解决方案清晰而不会陷入困境关于不相关部分的语义。请不要在这里遇到任何非标准或缺失的元素。)
//this function handles the threads
void *ThreadedFunction(void *arg) {
// do some stuff, like: pull vars out of mystruct
int nbytes;
char buf[256];
while(1) {
if((nbytes=recv(conid, buf, sizeof buf, 0)) <= 0) {
//handle break in connection
} else {
//for this example, just print out data from client to make my point
buf[nbytes] = 0;
printf("%s\n",buf);
}
}
}
//main just sets up the connections and creates threads
int main(int argc. char *argv[])
{
// bind(), listen(), etc... blah blah blah
while(1) {
conid = accept(...); //get a connection
// ... build mystruct to pass vars to threaded function ...
pthread_t p;
pthread_create(&p,NULL,ThreadedFunction,&mystruct); //create new thread
}
}
答案 0 :(得分:0)
您无需“排队”来自客户端的数据。 因为TCP会为您做到这一点。如果服务器太慢而无法为TCP接收缓冲区腾出空间,TCP的流控制甚至会降低客户端的速度。
因此,服务器或客户端的代码可能存在错误。也许客户端在每行的末尾发送'\ 0'。在这种情况下,以下代码不会打印所有行:
if((nbytes=recv(conid, buf, sizeof buf, 0)) <= 0) {
//handle break in connection
} else {
//for this example, just print out data from client to make my point
buf[nbytes] = 0;
printf("%s\n",buf);
}
如果客户端在每行的末尾发送'\ 0',那么第二行甚至是你看到的最后一行。
例如:
如果客户发送以下行:
"abc\n\0"
"def\n\0"
"ghi\n\0"
TCP通常会使用两个数据包发送,包含以下内容:
"abc\n\0"
"def\n\0ghi\n\0"
服务器通常需要2次recv调用才能接收传入的数据。 所以你的服务器将使用2个打印电话:
printf("%s\n", "abc\n\0\0");
printf("%s\n", "def\n\0ghi\n\0\0");
结果输出为:
abc
def