Начну с кодом:Winsock RECV дает 10014 ошибку
typedef std::vector<unsigned char> CharBuf;
static const int RCV_BUF_SIZE = 1024;
SOCKET m_socket = a connected and working socket;
// ...
CharBuf buf; // Declare buffer
buf.resize(RCV_BUF_SIZE); // resize buffer to 1024
char* p_buf = reinterpret_cast<char*>(&buf[0]); // change from unsigned char to char
//char p_buf[RCV_BUF_SIZE];
int ret = recv(m_socket, p_buf, RCV_BUF_SIZE, 0); // Does not work
for (int i=0; i<RCV_BUF_SIZE; ++i) // Works (does not crash, so the buffer is ok)
char c = p_buf[i];
//...
Теперь, когда я запускаю этот код RET становится -1 и WSAGetLastError() возвращает 10014, что означает указатель плохо.
Однако я не понимаю, почему это не должно работать? Если я закомментирую строку reinterpret_cast и использую строку ниже, она работает!
Можно утверждать, что reinterpret_cast является рискованным, но я думаю, что это должно быть хорошо, поскольку и unsigned char, и signed char имеют тот же самый размер.
std :: векторы должны быть безопасными для прямого доступа в память, насколько я знаю.
Забавно, что когда я делаю то же самое с тем же векторным типом в send(), он работает! Отправить функцию:
void SendData(const CharBuf& buf)
{
buf.resize(RCV_BUF_SIZE); // resize buffer to 1024
const char* p_buf = reinterpret_cast<const char*>(&buf[0]); // change from unsigned char to char
int ret = send(m_socket, p_buf, (int)buf.size(), 0); // Works
}
Как мы видим, никакой разницы, кроме CharBuf, являющейся константой в этом случае, может это что-то изменить?
Почему recv() более чувствителен, чем send()? Как может recv() даже знать, что указатель недействителен (что явно не так)? все, что должно увидеть, это массив символов!
По запросу вся моя функция приема (имейте в виду, что я не могу заклинание каждую функцию в нем, но я думаю, что они должны быть понятны сами по себе.
bool TcpSocket::ReceiveData(CharBuf* pData)
{
if (!CheckInitialized("ReceiveData"))
return false;
if (m_status != CONNECTED_STAT)
{
AddToErrLog("Socket not connected", 1, "ReceiveData");
return false;
}
int ret;
pData->resize(RCV_BUF_SIZE);
char* p_buf = reinterpret_cast<char*>(&pData[0]);
ret = recv(m_socket, p_buf, RCV_BUF_SIZE, 0);
switch (ret)
{
case 0: // Gracefully closed
AddToLog("Connection gracefully closed", 2);
Shutdown(); // The connection is closed, no idea to keep running
return true;
case SOCKET_ERROR: // Error
ret = WSAGetLastError();
if (ret == 10004) // This indicates the socket was closed while we were waiting
AddToLog("Socket was shut down while waiting for data", 1, "ReceiveData(1)");
else
AddToErrLog("Receive data failed with code: " + CStr(ret));
AddToLog("Connection ended with error", 2);
Shutdown();
return false;
default: // Normal operation
pData->resize(ret); // Remove unused space
return true;
}
}
Ничего. Я нашел это, когда я вставлял функцию. Как всегда, вы обнаружите свою ошибку, когда пытаетесь объяснить ее кому-то еще :) Я оставляю ее читателю, чтобы выяснить, что не так, но я дам & pData [0 ] как подсказка. Спасибо за вашу помощь: D
OS может сказать, что вы передаете ему плохой указатель и можете вернуть EFAULT вместо того, чтобы просто убить вашу программу. Укажите точный код, который вы используете, или минимальный тестовый пример. Что у вас в порядке. – Thanatos
Отрывки выглядят ОК. Итак ... В фактическом коде, который вы компилируете, вы дважды проверили, что 'buf' на самом деле имеет выделенный буфер? Вы проверили, случайно ли вы вызываете 'buf.reserve()' вместо 'buf.resize()'? Вы проверили значение 'p_buf', чтобы убедиться, что оно выглядит разумным, прежде чем передать его на' recv'? – TheUndeadFish
Если вы проверите всю функцию, я уверен, что вы обнаружите, где я сделал ошибку, указатели могут обмануть вас иногда :) – DaedalusAlpha