У меня установлен сокет TCP / IP для неблокирования, который блокирует в любом случае. На сокет ссылаются только в одном потоке. Этот код работает на Windows (с несколькими заменами вызовов), но не на Linux. У меня есть код, который выглядит следующим образом (Не обращайте внимания на приведение в стиле C - это было написано долго go. Кроме того, я немного урезал его, поэтому дайте мне знать, если я случайно урезал шаг Скорее всего, я действительно делаю этот шаг. Фактический код находится на другом компьютере, поэтому я не могу скопировать и вставить.):
// In the real code, these are class members. I'm not bonkers
int mSocket;
sockaddr_in mAddress;
void CreateSocket(
unsigned int ipAddress,
unsigned short port)
{
// Omitting my error checking in this question for brevity because everything comes back valid
mSocket = socket(AF_INET, SOCK_STREAM, 0); // Not -1
int oldFlags = fctnl(mSocket, F_GETFL, 0); // Not -1
fcntl(mSocket, F_SETFL, oldFlags | O_NONBLOCK); // Not -1
mAddress.sin_family = AF_INET;
mAddress.sin_addr.s_addr = ipAddress; // address is valid
mAddress.sin_port = htons((u_short)port); // port is not 0 and allowed on firewall
memset(mAddress.sin_zero, 0, sizeof(mAddress.sin_zero));
// <Connect attempt loop starts here>
connect(mSocket, (sockaddr*)&mAddress, sizeof(mAddress)); // Not -1 to exit loop
// <Connect attempt loop ends here>
// Connection is now successful ('connect' returned a value other than -1)
}
// ... Stuff happens ...
// ... Then this is called because 'select' call shows read data available ...
void AttemptReceive(
MyReturnBufferTypeThatsNotImportant &returnedBytes)
{
// Read socket
const size_t bufferSize = 4096;
char buffer[bufferSize];
int result = 0;
do {
// Debugging code: sanity checks
int socketFlags = fcntl(mSocket, F_GETFL, 0); // Not -1
printf("result=%d\n", result);
printf("O_NONBLOCK? %d\n", socketFlags & O_NONBLOCK); // Always prints "O_NONBLOCK? 2048"
result = recv(mSocket, buffer, bufferSize, 0); // NEVER -1 or 0 after hundreds to thousands of calls, then suddenly blocks
// ... Save off and package read data into user format for output to caller ...
} while (result == bufferSize);
}
Я считаю, потому что AttemptReceive вызывается в ответ на выберите, чтобы в сокете было ровно столько байтов, сколько кратно размеру буфера (4096). Я несколько подтвердил это с помощью операторов printf, поэтому он никогда не блокируется при первом l oop проходе. Каждый раз, когда возникает эта ошибка, последние две строки, которые должны быть напечатаны перед блоками потоков:
result=4096
O_NONBLOCK? 2048
Изменение строки recv
на recv(mSocket, buffer, bufferSize, MSG_DONTWAIT);
фактически «исправляет» проблему (внезапно recv иногда возвращает -1 с errno EWOULDBLOCK / EAGAIN (оба равны друг другу в моей ОС)), но я боюсь, что просто накладываю пластырь на так называемую рану. Любые идеи?
PS адрес "localhost", но я не думаю, что это имеет значение.
Примечание: я использую старый компилятор (не по выбору), g ++ 4.4. 7-23 из 2010. Это может иметь какое-то отношение к проблеме.