【发布时间】:2011-04-12 04:11:02
【问题描述】:
第一个stackoverflow问题!我已经搜索过......我保证。我还没有找到任何答案来解决我的困境。我有一个……至少可以说是一个严重恶化的问题。长话短说,我正在为一款游戏开发基础架构,其中移动应用程序(Android 应用程序和 iOS 应用程序)使用套接字与服务器通信,将数据发送到数据库。后端服务器脚本(我称之为 BES 或后端服务器)有几千行代码。本质上,它有一个 main 方法接受到套接字的传入连接并将它们分叉,以及一个从套接字读取输入并确定如何处理它的方法。大多数代码位于从数据库发送和接收数据并将其发送回移动应用程序的方法中。除了我添加的最新方法外,它们都工作正常。此方法从数据库中抓取大量数据,将其编码为 JSON 对象,然后将其发送回移动应用程序,移动应用程序也会从 JSON 对象中对其进行解码并执行它需要执行的操作。我的问题是这个数据非常大,而且大多数时候不会在一次数据写入中通过套接字。因此,我在套接字中添加了一个额外的数据写入,通知应用程序它即将接收的 JSON 对象的大小。但是,在此写入发生后,下一次写入会向移动应用发送空数据。
奇怪的是,当我删除发送 JSON 对象大小的第一个写入时,JSON 对象的实际发送工作正常。它非常不可靠,我必须希望它一口气发送所有内容。更奇怪的是,当我将第二次写入发送的数据大小设置为一个巨大的数字时,iOS 应用程序会正确读取它,但它会将数据放在一个空数组的中间。
世界上到底发生了什么?非常感谢任何见解!下面只是我在服务器端的两个写命令的基本sn-p。
请记住,在此脚本中的其他任何地方,读取和写入都可以正常工作,但这是我执行 2 次背靠背写入操作的唯一地方。
服务器脚本位于使用 Berkeley 套接字的原生 C 语言的 Ubuntu 服务器上,而 iOS 使用称为 AsyncSocket 的包装类。
int n;
//outputMessage contains a string that tells the mobile app how long the next message
//(returnData) will be
n = write(sock, outputMessage, sizeof(outputMessage));
if(n < 0)
//error handling is here
//returnData is a JSON encoded string (well, char[] to be exact, this is native-C)
n = write(sock, returnData, sizeof(returnData));
if(n < 0)
//error handling is here
移动应用程序进行两次读取调用,得到outputMessage 就好了,但returnData 始终只是一堆空数据,除非我将sizeof(returnData) 覆盖为一个非常大的数字,在这种情况下,iOS将在一个空数据对象(确切地说是 NSData 对象)的中间接收数据。还需要注意的是,我在 iOS 端的 AsyncSocket 类中使用的方法读取数据的长度达到了它从第一次写入调用接收到的长度。因此,如果我告诉它读取,比如 10000 字节,它将创建一个该大小的 NSData 对象,并在从套接字读取时将其用作缓冲区。
非常感谢任何帮助。提前谢谢大家!
【问题讨论】:
-
你怎么知道 write 发送的东西是空的(相对于你的阅读应用程序有问题)?这听起来更像是不考虑 TCP 是面向流而不是面向数据包的常见问题。一个 write() 可能需要多次 read() 调用才能接收,反之亦然。无论实验室的情况如何,您都需要考虑到这一点。
-
我不确定最初的问题是什么,但已通过改用
iovec结构并使用writev而不是write来解决这个问题。你是对的,它实际上并没有写空的东西。write返回结果始终是正确的字节数。我什至可以让客户端看到它读取任何数据的唯一方法是使客户端将读取的数据放入的缓冲区巨大,并且不知何故,实际上在该缓冲区的中间,就是数据。这很奇怪。但现在我正在阅读它,直到它收到一个空终止符并将其作为iovec通过套接字发送。 -
如果是这种情况,它只是在您的测试用例中被“修复”。总有一天,一些用户的连接速度会很慢,连接非常拥塞,或者您偶然会快速发送数据/读取数据缓慢,您(或更可能是毫无戒心的用户)将再次遇到同样的问题。仔细阅读格雷格的回复
-
@nos 他先写数据包的大小,我想这是为了他可以像 TCP 一样将流转换为数据包,所以他读取大小然后读取由大小指定的整个数据包.如果他这样做,那么客户端不应受到碎片的影响。他现在以原子方式写入大小,然后写入有效负载,因此交错写入不会破坏“流”。
标签: c linux ios sockets asyncsocket