我需要每0.02秒将数据发送到另一个进程。
服务器代码:
//set socket, bind, listen
while(1){
sleep(0.02);
echo(newsockfd);
}
void echo (int sock)
{
int n;
char buffer[256]="abc";
n=send(sock,buffer,strlen(buffer),0);
if (n < 0) error("ERROR Sending");
}
客户端代码:
//connect
while(1)
{
bzero(buffer,256);
n = read(sock,buffer,255);
printf("Recieved data:%s\n",buffer);
if (n < 0)
error("ERROR reading from socket");
}
问题在于:
客户端显示如下内容:
Recieved data:abc
Recieved data:abcabcabc
Recieved data:abcabc
....
它是如何发生的?当我设定睡眠时间时:
...
sleep(2)
...
没关系:
Recieved data:abc
Recieved data:abc
Recieved data:abc
...
答案 0 :(得分:5)
TCP套接字不保证框架。当您通过TCP套接字发送字节时,这些字节将以相同的顺序在另一端接收,但它们不一定以相同的方式分组 - 它们可以以任何方式分割,组合在一起或重新组合操作系统认为合适。
如果您需要成帧,则需要发送某种数据包标头以指示每个数据块的开始和结束位置。这可以采用分隔符(例如,\n
或\0
来指示每个块结束的位置)或长度值(例如,每个块的头部的数字来表示如何很长时间。)
此外,正如其他受访者所指出的那样,sleep()
取整数,所以你实际上根本就没有睡觉。
答案 1 :(得分:3)
sleep
以unsigned int
为参数,因此sleep(0.02)
实际上是sleep(0)
。
unsigned int sleep(unsigned int seconds);
请改用usleep(20)
。它会在几微秒内睡觉:
int usleep(useconds_t usec);
答案 2 :(得分:2)
操作系统可以自由缓冲数据(即为什么不只是发送一个完整的数据包而不是多个数据包)
除了睡眠采用无符号整数。
答案 3 :(得分:2)
原因是操作系统正在缓冲要发送的数据。它将根据大小或时间进行缓冲。在这种情况下,您没有发送足够的数据,但是您发送的速度足够快,操作系统选择在将其放入线路之前进行批量处理。
当您添加sleep(2)
时,操作系统选择在下一个“abc”进入之前选择发送一个“abc”。
您需要了解TCP只是一个字节流。它没有消息或大小的概念。您只需在一端将线上字节放在线上,然后在另一端将其取下。如果你想做特定的事情,那么你需要在阅读时解释数据的特殊方式。因此,正确的解决方案是为此创建一个实际的协议。该协议可以像“每个3个字节是一个消息”一样简单,或者在发送大小前缀的地方更复杂。
根据您的其他要求,UDP也可能是一个很好的解决方案。
答案 4 :(得分:2)
sleep(0.02)
实际上是
sleep(0)
因为参数是unsigned int,所以隐式转换会为你做。所以你在这里根本没有睡觉。您可以使用sleep(2)
来休眠2微秒。接下来,即使您有,也不能保证您的消息将以不同的帧发送。如果你需要这个,你应该应用某种分隔符,我见过
'\0'
字符。
答案 5 :(得分:2)
TCPIP堆栈缓冲数据,直到有相当数量的数据,或直到他们认为不再有来自应用程序并发送他们已经获得的数据。
您需要做两件事。首先,关闭Nagle的算法。其次,理清某种框架机制。
关闭Nagle的算法将使堆栈“立即发送数据”,而不是等待你想要发送更多的机会。它实际上导致网络效率降低,因为您没有填满以太网帧,需要记住千兆位,需要使用巨型帧来获得最佳吞吐量。但在你的情况下,及时性比吞吐量更重要。
您可以通过非常简单的方式进行自己的构建,例如,首先发送一个整数,表示消息的剩余时间。在读取器端,您将读取整数,然后读取该字节数。对于下一条消息,您将发送另一个整数,表示该消息的持续时间等等。
那种事情还可以,但不是很强大。您可以查看类似ASN.1或Google协议缓冲区的内容。
我使用过Objective System的ASN.1库和工具(它们不是免费的),并且它们在处理消息完整性,框架等方面做得很好。它们很好,因为它们不会从中读取数据网络连接一次一个字节,因此效率和速度也不算太差。读取的任何额外数据都将保留并包含在下一个消息解码中。
我自己没有使用Google协议缓冲区,但它们可能具有相似的特性,并且可能还有其他类似的序列化机制。出于速度/效率的原因,我建议避免使用XML序列化。