Если чтение / запись сокета завершается неудачей по любой причине, кроме EINTR или EAGAIN / EWOULDBLOCK, вы должны рассматривать это как фатальную ошибку. Не повторяйте операцию, просто остановите и закройте розетку. Но ваш код этого не делает, он пытается повторить неудачную операцию.
Кроме того, при чтении вы не обрабатываете случай, когда чтение возвращает 0, когда узел отключается изящно . В этом случае ошибка сокета не сообщается.
Вместо этого попробуйте что-то вроде этого:
bool WriteSocket(int pSocket, unsigned char* pData, uint32_t pNumBytes, uint32_t &pNumBytesWritten, uint32_t &pNumWrites)
{
int rc;
uint32_t numRetries = 0;
pNumBytesWritten = 0;
pNumWrites = 0;
while ( pNumBytes > 0 )
{
rc = write(pSocket, pData, pNumBytes);
if ( rc < 0 )
{
if ( errno == EINTR )
continue;
if ( (errno == EAGAIN) || (errno == EWOULDBLOCK) )
{
++numRetries;
if ( numRetries < 5 )
{
// TODO: use select() or epoll() w/ timeout to
// detect when then socket is writable again...
continue;
}
}
return false;
}
++pNumWrites;
pNumBytesWritten += rc;
pNumBytes -= rc;
pData += rc;
numRetries = 0;
}
return true;
}
bool ReadSocket(int pSocket, unsigned char* pData, uint32_t pNumBytes)
{
int rc;
uint32_t numRetries = 0;
while ( pNumBytes > 0 )
{
rc = read(pSocket, pData, pNumBytes);
if ( rc < 0 )
{
if ( errno == EINTR )
continue;
if ( (errno == EAGAIN) || (errno == EWOULDBLOCK) )
{
++numRetries;
if ( numRetries < 5 )
{
// TODO: use select() or epoll() w/ timeout to
// detect when then socket is readable again...
continue;
}
}
return false;
}
else if ( rc == 0 )
{
return false;
}
else
{
pNumBytes -= rc;
pData += rc;
numRetries = 0;
}
}
return true;
}