Вызов recvfrom() из вызванной асинхронно функции блокирует не только нить, в которой функция, но и вызывавший поток (возврат в него не происходит). Почему и как это обойти?
ps Это, если верно считаю, уже третья тема по советам переформулировать и задать новый вопрос в предыдущих, где никто ничем не смог помочь, в чём любой может убедиться, если почитает предыдущие темы внимательно, а именно мои комментарии к ответам.
pps vs2017 solution
recvfrom - блокирующая функция (ОС Виндовс)
https://docs.microsoft.com/en-us/windows/desktop/api/winsock/nf-winsock-recvfrom
...
if no incoming data is available at the socket, the recvfrom function blocks and waits for data to arrive according to the blocking rules defined for WSARecv with the MSG_PARTIAL flag not set unless the socket is nonblocking. In this case, a value of SOCKET_ERROR is returned with the error code set to WSAEWOULDBLOCK. The select, WSAAsyncSelect, or WSAEventSelect can be used to determine when more data arrives.
...
Попробуйте использовать асинхронные операции WSA2: https://docs.microsoft.com/en-us/windows/desktop/api/winsock2/nf-winsock2-wsarecv
std::async не гарантирует выполнения в отдельном потоке и содержит кучу ограничений на асинхронный запуск, и, вполне естественно, что у вас зависает весь поток.
Спасибо всем за помощь, вот решение:
bool UdpClient::stopListen = false;
void UdpClient::listen(SOCKET RecvSocket, sockaddr_in addr, onReceive o, UdpClient::onError _onError)
{
int size = sizeof(addr);
char rBuff[1024];
int buffSize = sizeof(rBuff);
while (stopListen) {
int err = recvfrom(RecvSocket, rBuff, sizeof(rBuff), 0, (sockaddr*)&addr, &buffSize);
if (err > 0) {
rBuff[err] = 0;
if (o)
o(rBuff);
}
else {
if (_onError) {
std::ostringstream out;
out << "recv failed: " << WSAGetLastError();
_onError(out.str());
}
closesocket(RecvSocket);
WSACleanup();
return;
}
}
}
std::shared_future<void> UdpClient::receive(onReceive r, int port, const std::string& ip)
{
std::ostringstream out;
std::future<void> k;
std::shared_future<void> m;
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
if (_onError) {
out << "WSAStartup failed with error: " << iResult;
_onError(out.str());
}
return m;
}
sockaddr_in ServerAddr;
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons(port);
inet_pton(AF_INET, ip.c_str(), &ServerAddr.sin_addr);
SOCKET RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (RecvSocket == INVALID_SOCKET) {
if (_onError) {
out << "socket failed with error: " << WSAGetLastError();
_onError(out.str());
}
WSACleanup();
return m;
}
int err = bind(RecvSocket, (sockaddr*)&ServerAddr, sizeof(ServerAddr));
if (err == SOCKET_ERROR) {
if (_onError) {
out << "bind failed with error: " << WSAGetLastError();
_onError(out.str());
}
closesocket(RecvSocket);
WSACleanup();
return m;
}
auto n = std::async(std::launch::async, listen, RecvSocket, ServerAddr, r, _onError).share();
//std::shared_future<std::future<void>> f(n);
return n;
}
Виртуальный выделенный сервер (VDS) становится отличным выбором
Я недавно начал заниматься C++, и пишу простую программку которая получает данные из файла который находится в интернетеСама функция:
У меня возникает проблема с определением типа возвращаемого значения перегруженной функции внутри шаблонаВозвращаемый тип зависит от параметра,...
Куки заранее получил через авторизацию браузера CefBrowserДелаю так: