在我的代码中,客户端将向服务器发起请求,此时,服务器将继续向客户端发送数据,直到出现特殊输出(例如" END"),然后客户端将停止读取。 这里有一些代码(只是一个例子):
self.delegate?.childViewControllerResponse(parameter)
此代码工作正常,但由于进程中的某些上下文切换,服务器在客户端读取之前写入两次,因此客户端一次读取两行,例如:
5532127
332
65723
8912
2421
1268
32END
如图所示,有时2个或多个写入被分组为1个读取,因此当然结束时不会处理END。
我尝试使用/**Client**/
char req[] = "some-request";
write(socket,req,strlen(req));
while(1)
{
read(socket,readline,100);
strtok(readline, "\n");
if(strcmp(readline,"END") == 0){ //if end of sending
break;
}
/** HANDLE OUTPUT **/
}
/** Server **/
int data[] = {5532,127,332,65,723,8,912,2,421,126,8,3,2}
int i;
for(i = 0 ; i < sizeof(data); i++)
{
write(socket, data[i], sizeof(data[i]);
}
write(socket, "END", 3);
功能,该功能大部分时间都有效,但仍然不是解决方案。
那么任何想法如何确保服务器在没有空的情况下不写入缓冲区?
答案 0 :(得分:1)
您正在使用面向流的套接字。服务器无法知道客户端是否已经接收到数据,并且在循环中多次写入之间没有任何区别,或者只有一次写入发送整个阵列。
您将需要使用面向数据包的东西,或者有办法弄清楚您的&#34;数据包&#34;。正如您所知,您不能依赖时间,因此您需要定义某种协议。简单的方法是只读取整数*,并将一个特殊值作为结束。
顺便说一下。您的代码在编号表示方面也存在一些问题。你需要使用固定长度类型(int可以是16或32位,所以使用像uint32_t这样的东西),你需要知道endianess问题(应该使用htonl / ntohl或类似的)。
答案 1 :(得分:1)
我可以在你的代码中看到一些问题。
在发送原始int服务器端时使用strtok(readline, "\n");
客户端。这意味着,在其中一个已发送的整数中,0x..10
或0x10..
会将其更改为(分别)0x..00
或0x00..
。切勿在原始字节上使用strxx
函数!
接下来,您正在使用面向流的套接字。您无法保证不会对数据包发送进行分组或拆分。因此,您应该整理接收器中的所有内容,直到您有3个包含END
的连续字符。但你不能使用strxx
函数......
最后,传输原始整数,并等待3个字符END。但是如果你尝试发送{12, 17743, 17408, 13}
(在大端系统上),你将遇到一个主要问题:17743 = 0x454F,17408 = 0x4400 =&gt;你有完全“结束”!在一个小端,魔术值将是20293 = 0x4F45和68 = 0x0044。
规则是:
htonx
函数)以避免字节序问题在您的用例中,您应该简单地转移文本表示,使用sprintf
转换整数,用空格分隔,最后以\n
结尾。