在 Android 本机代码中挂起 TCP 套接字发送调用

发布于 2024-12-13 12:08:28 字数 1507 浏览 1 评论 0原文

我在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

无人问我粥可暖 2024-12-20 12:08:28

这个问题在 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文