【发布时间】:2011-12-20 16:35:39
【问题描述】:
我在 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();
【问题讨论】:
-
如何创建套接字(选项?)。如果接收者总是在同一台主机上,你可以尝试使用域套接字吗?
-
不,接收套接字在不同的机器上,所以我不能使用 unix 域套接字(我说,我有 Android 到 Linux 的配置)。
-
2 锁定/解锁有什么用?是否还有其他线程也在使用此套接字?使用流套接字我会简单地做
bytes_written = write (sockfd, pArray, size);。 -
你设置mSocket等于sockfd吗?
-
您确定是
send阻塞而不是互斥锁吗?为什么首先需要这些?