У меня проблема с функцией отправки (или записи) сокета на Android.
Есть моя сетевая библиотека, которую я использую на Linux и Android. Код написан на C.
На Android приложение создает сервис, который загружает собственный код и создает соединение с помощью моей сетевой библиотеки. Соединение - это сокет TCP. Когда я вызываю send (или пишу, без разницы), код в этом звонке зависает в большинстве случаев. Иногда он разворачивается через 10-120 секунд. Иногда он дольше ждет (пока я не убью приложение). Размер отправляемых данных составляет около 40-50 байт. Первая отправка данных (рукопожатие, 5 байт) никогда не зависает (или мне просто везет). Передача с зависанием, как правило, следующая после пакета рукопожатия. Время между отправкой первого рукопожатия и зависанием составляет около 10-20 секунд.
Сокет используется в другом потоке (я использую pthread), где вызывается recv. Но сейчас я не отправляю данные на Android, поэтому recv просто ждет, когда я позвоню send.
Я уверен, что другая сторона ждет данных - я вижу, что recv на другой стороне возвращается с EAGAIN каждые 3 секунды (я установил тайм-аут) и сразу же вызывает 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();