在 Android 本机代码中挂起 TCP 套接字发送调用
我在 Android 上使用套接字发送(或写入)功能时遇到问题。
我在 Linux 和 Android 上使用了我的网络库。代码是用 C 语言编写的。
在 Android 上,应用程序创建一个服务,该服务加载本机代码并在我的网络库的帮助下创建连接。连接是TCP套接字。当我调用 send (或 write,没有区别)时,大多数情况下代码会在此调用中挂起。有时,它会在 10-120 秒后取消挂起。有时,它会等待更长的时间(直到我终止应用程序)。发送的数据大小约为 40-50 字节。第一次数据发送(握手,5 个字节)永远不会挂起(或者我只是幸运)。挂起发送通常是握手数据包之后的下一个发送。第一次握手包发送和挂起发送之间的时间大约是10-20秒。
套接字在另一个线程(我使用pthread)上使用,其中调用了recv。但是,我这次没有向Android发送数据,所以当我调用send时recv只是在等待。 我确信另一端正在等待数据——我看到另一端的recv每3秒返回一次EAGAIN(我设置了超时)并立即再次调用recv。 Recv 始终等待 10 个字节(数据包的最小大小)。
我无法在 Linux 到 Android 传输或 Linux 到 Linux 上重现此行为,只能在 Adnroid 到 Linux 上重现。我可以用两个可用的不同 Android 设备重现此问题,因此我认为这不是某个特定设备的硬件损坏的问题。
我尝试设置 SO_KEEPALIVE 和 TCP_NODELAY 选项但没有成功。
什么会导致发送/写入调用挂起?如何解决此问题?
使用此代码创建的套接字:
int sockfd, n;
addrinfo hints, *res, *ressave;
bzero(&hints, sizeof(addrinfo));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
if ((n = getaddrinfo(host, serv, &hints, &res)) != 0)
{ /* stripped error handling*/ }
ressave = res;
do
{
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sockfd < 0) continue;
if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0)
{
break; /* success */
}
close(sockfd); /* ignore this one */
} while ((res = res->ai_next) != NULL);
挂起发送操作是:
mWriteMutex.lock();
mSocketMutex.lockRead();
ssize_t n = send(mSocket, pArray, size, 0);
mSocketMutex.unlock();
mWriteMutex.unlock();
I have a problem with socket send (or write) function on android.
There is my network lib that I use on Linux and Android. Code is written in C.
On Android, application creates a service, which loads a native code and creates the connection with the help of my network lib. Connection is the TCP socket. When I call send (or write, no difference), code hangs in this call in most cases. Sometimes, it unhangs after 10-120 seconds. Sometimes, it waits longer (until I kill the application). Data size being sent is about 40-50 bytes. First data sending (handshake, 5 bytes) never hangs (or I am just lucky). The hanging send is, usually, next after handshake packet. Time between this first handshake packet sending and hanging sending is about 10-20 seconds.
The socket is used on another thread (I use pthread), where the recv is called. But, I do not send data to Android in this time, so recv is just waiting when I call send.
I am sure that other side is waiting for the data – I see that recv on other side returns with EAGAIN every 3 seconds (I set timeout) and immediately calls recv again. Recv is waiting 10 bytes always (minimal size of packet).
I am unable to reproduce this behavior on Linux-to-Android transfer or Linux-to-Linux, only on Adnroid-to-Linux. I am able to reproduce this with two available to me different Android devices, so I don’t think this is the problem in broken hardware of one particular device.
I tried to set SO_KEEPALIVE and TCP_NODELAY options with no success.
What can issue the hang-up on send/write calls and how can I resolve this?
Socket created with this code:
int sockfd, n;
addrinfo hints, *res, *ressave;
bzero(&hints, sizeof(addrinfo));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
if ((n = getaddrinfo(host, serv, &hints, &res)) != 0)
{ /* stripped error handling*/ }
ressave = res;
do
{
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sockfd < 0) continue;
if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0)
{
break; /* success */
}
close(sockfd); /* ignore this one */
} while ((res = res->ai_next) != NULL);
Hanging send operation is:
mWriteMutex.lock();
mSocketMutex.lockRead();
ssize_t n = send(mSocket, pArray, size, 0);
mSocketMutex.unlock();
mWriteMutex.unlock();
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这个问题在 Nikolai N Fetissov 的评论中得到了解决——他的正确问题解开了我的思路,我在 RWMutex 中发现了一个问题。
The problem is solved with the help of Nikolai N Fetissov in commentaries - his right question has unblocked my mind and I found a problem in RWMutex.