在C语言套接字编程中刷新套接字流。

11

我想知道在C中进行套接字编程时如何刷新套接字流。我尝试了所有选项-使用以下代码设置TCP_NODELAY-

setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));      

注意:所有的flagsockfd都已正确声明。

我曾在send()之前和之后都使用过此函数,但并没有任何区别。

还有人建议在每次send()之后使用shutdown(),但这只适用于一个实例。当我再次使用它发送一些文本时,它不起作用-事实上,在我使用shutdown()之后连接被关闭。

shutdown(sockfd, SHUT_WR);

有人能在这方面提供帮助吗?

我想补充一下 - 服务器是一个Java socket,客户端是一个C socket。 C socket实现了JVMTI接口,并将信息发送到Java socket。


1
为了明确起见,您应该提到您正在使用哪个平台——Windows还是*nix。 - batbrat
你能发布更多的代码吗?你有检查从send返回的值吗? - Sam Post
是的,我将其存储在名为“bytes_sent”的变量中。如果从客户端发送了20个字符,则该变量正确显示已发送“20字节”。我在命令提示符上打印发送的字节数。一旦连接关闭,所有发送的数据都会在服务器上打印,直到此时为止,客户端没有发送任何数据。 - MohamedSanaulla
数据可能会被卡在接收端的输入缓冲区中,请使用wireshark进行检查。同时,确保在调用上面的setsockopt()之前设置了 flag = 1 - mark4o
我正在使用本地(C ++)语言实现JVMTI接口(JVMTI代理)。从JVMTI代理(客户端套接字)获取的数据被发送到另一个Java进程(服务器套接字)。尽管数据已经在服务器套接字上打印出来,但这只发生在我退出客户端套接字之后。 - MohamedSanaulla
显示剩余3条评论
5个回答

5

通过在Google上进行一些研究,似乎没有一种显式地刷新套接字流的方法。您可以设置TCP_NODELAY,然后它将关闭TCP Nagle算法。这应该确保数据立即发送,而不是等待缓冲区满了才发送。

您是否使用过Wireshark或其他工具来查看在设置TCP_NODELAY时发生了什么?


我没有使用任何工具来检查幕后发生的情况。我观察到的是,一旦套接字连接关闭或客户端完成执行,数据立即发送到服务器。 - MohamedSanaulla
我甚至发现没有明确的方法来刷新套接字,但有些人说他们可以通过设置TCP_NODELAY或使用shutdown()来实现。 - MohamedSanaulla
如果不使用这样的工具,你就无法知道在连接关闭时数据是否已发送。 - nos
您可以禁用 Nagle,但我不知道如何禁用延迟 ACK,这也可能是问题的原因。 - Mooing Duck

4

您可能需要阅读最终 SO_LINGER 页面或为什么我的 TCP 不可靠,我认为这适用于您的情况。

编辑:

在 TCP 套接字上多次调用 send() 并不罕见 :) 我是指正常使用。您可能在服务器端遇到了问题,服务器等待一定数量的字节并且阻塞等待。
据我所知,JVM TI 不会指定任何通过网络传输的协议,因此您需要自己制定协议。定义客户端发送和服务器期望的记录结构,如果大小不同,则在其中放置数据长度。您还可以从服务器实现某些应用程序级别的确认消息回到客户端。


我完整地阅读了这篇文章,尽管我大部分内容都无法理解。但我能够明白作者想要表达的是- 使用send()函数,然后调用shutdown()函数。但是如果我需要多次发送数据怎么办?一旦调用了shutdown()函数就不可能了,对吗? - MohamedSanaulla
在服务器端,我使用Scanner实例来读取流。因此,每当流上有数据可用时,“hasNext()”方法返回TRUE,并使用“next()”方法进行读取。我们是否仍然需要知道发送的数据大小? - MohamedSanaulla
1
最好让另一方知道可以期待什么。问题在于TCP以块(IP数据包)的形式传输数据,这些块不一定与应用程序发送的数据对齐。请问自己 - 服务器如何知道客户端的一段数据何时结束,另一段数据何时开始? - Nikolai Fetissov
其实你是正确的。我在服务器端使用Scanner时犯了一个错误。我的朋友建议我用BufferedReader替换它。我用BufferedReader逐字节地读取它。非常感谢您的帮助。 - MohamedSanaulla

2

只需使用fdopen。在Linux中,任何东西都是文件。 例如:

FILE *f = fdopen(socketdescriptor, "w+");
. . .
n = write(socketdescriptor, "this is a message", 17);
fflush(f);

...

2

由于数据始终尽可能快地发送,考虑到接收方的可用缓冲空间和避免网络拥塞,因此您无法显式刷新套接字。设置TCP_NODELAY允许在仍有未完成的确认时发送小于最大大小的数据包。


2
这很不幸,因为什么是“合理的”是有争议的。当我知道我已经将所有数据写入套接字以执行命令,现在我希望服务器尽快回复时,必须等待数十毫秒,这是否合理? - Michael

1

socket-unix-faq 表示您无法刷新套接字


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接