У меня есть клиентский код C ++ UDP — на основе сокетов WSA — который работает хорошо. Код был изначально написан на VS6, и я недавно перекомпилировал его в VS2010 для 64-битной среды с небольшими изменениями.
Теперь sendto () не может отправить что-либо, если нет Sleep (..) или какой-либо эквивалентной задержки после sendto () и до closesocket (). «Сбой» означает, что sendto () возвращает правильный объем данных, но я не вижу сообщений в сети (я использовал wireshark, чтобы проверить это).
Это мой код:
void CTest::SendHello()
{
SOCKET sSocket;
sSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(m_strDstIpAddr);
addr.sin_port = htons(m_nTxPort);
int nMsgLen = 8;
char pTxBuffer[8];
*((DWORD*) &pTxBuffer[ 0]) = 0x11223344;
*((DWORD*) &pTxBuffer[ 4]) = 0;
int nSent = sendto(sSocket, pTxBuffer, nMsgLen, 0, (struct sockaddr *) &addr, sizeof(addr));
Sleep(10); // <- this seems to be necessary
if (nSent != nMsgLen)
{
CString s = "error sending HELO\n";
AfxMessageBox(s);
}
closesocket(sSocket);
}
Без Sleep () код ничего не отправляет, но не возвращает ошибок. С Sleep () это работает. Кроме того, это происходит в версии выпуска, когда компилируется для отладки, код также работает без Sleep ().
Кажется, как будто closesocket () закрывает сокет, прежде чем сообщение будет окончательно отправлено, но я подумал, что sendto () является синхронной функцией. Я пытался использовать SO_LINGER, но это не относится к сокетам SOCK_DGRAM.
Так как код находится внутри DLL, я не могу создать сокет в ctor и удалить его в dtor, потому что SendHello () может вызываться из разных контекстов потока, и мне нравится избегать усложнения кода.
спасибо за любую помощь
В UDP нет упорядочения данных между отправителем и получателем, и данные, отправленные с использованием сокетов UDP-дейтаграмм, не гарантируются. Все, что делает сон в вашем случае, практически обеспечивает достаточно времени для получения данных на другом конце. Если вам нужно подтверждение получения и проверка ошибок, то вы можете либо кодировать схему для UDP, либо использовать TCP. Фактически, вы можете полностью отключить сервер, и ваш клиент с радостью запустит UDP-пакеты без ошибок, даже если никто не слушает.
чтобы застраховать соединение, посмотрите на connect (). Ничто не мешает использовать соединение с UDP, и вы можете использовать send () recv ().