Форум программистов
 
Расширенный поиск
Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail.

Вернуться   Форум программистов > C++ > C/C++ Сетевое программирование
Регистрация

Восстановить пароль
Повторная активизация e-mail

Excel VBA, CAD, Софт, ОС, Windows, Ubuntu, Android, VPS
Win Api, Assembler, C++, Java, Pascal, Lazarus, Delphi, OpenGL, DirectX
C#, Qt, .NET, ASP.NET, Windows Forms, ADO.NET, Framework, WPF, UWP, WinRT, XAML
HTML, CSS, JavaScript, Ajax, PHP, Perl, Python, Ruby, SQL, WordPress, API, XML, JSON, ActionScript, Flash

Ответ
 
Опции темы
Старый 05.12.2016, 12:16   #1
sasha1993
Пользователь
 
Регистрация: 26.06.2009
Сообщений: 42
Репутация: 10
По умолчанию Работа с UDP, таймаут для setsockopt

Доброго времни суток. Пользуюсь Windows 8.1, Visual Studio 2013, C++. Пытаюсь использовать setsockopt для установки таймаута у recvfrom, в общем проблема в том,что setsockopt возвращает -1, а печать ошибки (perror("Error"); или « std::strerror(errno)) возвращает строку "No error", и в общем таймаут не работает.
Подскажите что я делаю не так ?
вот "главный" кусочек кода:
Код:

while (true)
    {
        
        if (setsockopt(receivefd, SOCK_DGRAM, SO_KEEPALIVE, (const char*)&val, sizeof DWORD) < 0) {
            perror("Error");
            std::cout << "log(-1) failed: " << std::strerror(errno) << '\n';
        }
        recvlen = recvfrom(receivefd, buf, BUFSIZE, 0, (struct sockaddr *)&receiveaddr, &receiveaddrlen);
        if (recvlen > 0) {
            buf[recvlen] = 0;
            printf("received message: "%s"\n", buf);
            char lightbulbID  = rand() % 8 + 1;
            lightbulbID += '0';
            if (sendto(sendfd, "HI", strlen("HI"), 0, (struct sockaddr *)&sendaddr, sizeof(sendaddr)) >= 0) {
                printf("dending message: hello from outside%c\n", lightbulbID);
            }
        //  MessageBoxA(NULL, buf, "Error", MB_OK);
        }
 
    }

И полный листинг проги, она пока не хитрая (и не акуратноя).
Код:

// UDPActivity.cpp : Defines the entry point for the console application.
//
 
#include "stdafx.h"
#pragma comment(lib,"ws2_32.lib")
 
#include <stdio.h>
#include <WinSock2.h>
#include <Ws2tcpip.h>
#include <iostream>
#include <stdio.h>  
#include <stdlib.h>  
 
#define BUFSIZE 2048
 
int _tmain(int argc, _TCHAR* argv[])
{
 
    WSAData wsaData;
    WORD DLLVersion = MAKEWORD(2, 1);
    if (WSAStartup(DLLVersion, &wsaData) != 0)
    {
        MessageBoxA(NULL, "Winsock startup failed", "Error", MB_OK);
    }
    ////////////////
    SOCKADDR_IN  receiveaddr;
    int receiveaddrlen = sizeof(receiveaddr);
    //addr.sin_addr.s_addr = inet_pton("127.0.0.1");  //127.0.0.1  //192.168.113.30  //169.254.81.194
    inet_pton(AF_INET, "127.0.0.1", &receiveaddr.sin_addr);
    receiveaddr.sin_family = AF_INET;
    receiveaddr.sin_port = htons(2222);
 
 
    SOCKET receivefd;
    if ((receivefd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
 
        MessageBoxA(NULL, "cannot create socket. ", "Error", MB_OK);
 
    }
 
 
    
    if (bind(receivefd, (struct sockaddr *)&receiveaddr, sizeof(receiveaddr)) < 0) {
    //  MessageBoxA(NULL, "Bind failed. ", "Error", MB_OK);
 
    }
    
    
 
 
 
    ////////////////
    SOCKADDR_IN  sendaddr;
    int sendaddrlen = sizeof(sendaddr);
    //addr.sin_addr.s_addr = inet_pton("127.0.0.1");  //127.0.0.1  //192.168.113.30  //169.254.81.194
    inet_pton(AF_INET, "127.0.0.1", &sendaddr.sin_addr);
    sendaddr.sin_family = AF_INET;
    sendaddr.sin_port = htons(1111);
    
 
    SOCKET sendfd;
    if ((sendfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
 
    //  MessageBoxA(NULL, "cannot create socket. ", "Error", MB_OK);
 
    }
 
 
 
    if (bind(sendfd, (struct sockaddr *)&sendaddr, sizeof(sendaddr)) < 0) {
        MessageBoxA(NULL, "Bind failed. ", "Error", MB_OK);
 
    }
 
    //char[] my_message = "hello UDP";
 
    {
 
 
        if (sendto(sendfd, "hello from outside", strlen("hello from outside"), 0, (struct sockaddr *)&sendaddr, sizeof(sendaddr)) < 0) {
            MessageBoxA(NULL, "ending failed. ", "Error", MB_OK);
        }
 
    }
    //struct sockaddr_in remaddr;     /* remote address */
    //socklen_t addrlen = sizeof(remaddr);            /* length of addresses */
    int recvlen;                 /* # bytes received */
    //  int fd;                         /* our socket */
    char buf[BUFSIZE];     /* receive buffer */
 
 
    DWORD val = 600;
 
    while (true)
    {
        
        if (setsockopt(receivefd, SOCK_DGRAM, SO_KEEPALIVE, (const char*)&val, sizeof DWORD) < 0) {
            perror("Error");
            std::cout << "log(-1) failed: " << std::strerror(errno) << '\n';
        }
        recvlen = recvfrom(receivefd, buf, BUFSIZE, 0, (struct sockaddr *)&receiveaddr, &receiveaddrlen);
        if (recvlen > 0) {
            buf[recvlen] = 0;
            printf("received message: "%s"\n", buf);
            char lightbulbID  = rand() % 8 + 1;
            lightbulbID += '0';
            if (sendto(sendfd, "HI", strlen("HI"), 0, (struct sockaddr *)&sendaddr, sizeof(sendaddr)) >= 0) {
                printf("dending message: hello from outside%c\n", lightbulbID);
            }
        //  MessageBoxA(NULL, buf, "Error", MB_OK);
        }
 
    }
 
 
 
    return 0;
}

sasha1993 вне форума   Ответить с цитированием
Старый 05.12.2016, 13:02   #2
Pavia
Лис
Профессионал
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 1,015
Репутация: 1120
По умолчанию

Цитата:
печать ошибки (perror("Error"); или « std::strerror(errno)) возвращает строку "No error"
Согласно MSDN.
Для получения ошибки надо использовать WSAGetLastError.
Код ошибке не кладётся в errno из за проблем с многопоточностью.
SO_KEEPALIVE неприменим к SOCK_DGRAM. Так как в протоколе UDP нет понятия сессии.
__________________
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .
Pavia вне форума   Ответить с цитированием
Старый 05.12.2016, 17:33   #3
sasha1993
Пользователь
 
Регистрация: 26.06.2009
Сообщений: 42
Репутация: 10
По умолчанию

Изменил на

Код:

if (setsockopt(receivefd, SOCK_DGRAM, SO_RCVTIMEO, (const char*)&val, sizeof DWORD) < 0)

И вывел ошибки с помошью WSAGetLastError(), там 10022 (Invalid argument).
Какой аргумент неверный в этот раз ?
sasha1993 вне форума   Ответить с цитированием
Старый 05.12.2016, 17:57   #4
Pavia
Лис
Профессионал
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 1,015
Репутация: 1120
По умолчанию

SOCK_DGRAM неверный, это не уровень. Нужно указывать уровень к которому применяются настройки один из этих. И параметр SO_RCVTIMEO применяется с уровнем
SOL_SOCKET
Код:

if (setsockopt(receivefd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&val, sizeof DWORD) < 0)

__________________
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .

Последний раз редактировалось Pavia; 05.12.2016 в 18:56.
Pavia вне форума   Ответить с цитированием
Ответ



Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
таймаут idhttp get niva622 Работа с сетью в Delphi 3 25.04.2016 10:40
Другое [PHP/Delphi] Работа с UDP - Заказать программу Mik92 Фриланс 3 07.04.2015 23:59
Таймаут соединения. deromik C# (си шарп) 0 19.06.2013 17:39
Полином для расчёта crc16 udp пакета. ATAMAN200 Общие вопросы C/C++ 4 04.10.2010 10:00
Как выставить таймаут операции connect() для сокетов по закрытому порту GanjaKyp Работа с сетью в Delphi 1 16.03.2009 22:59




03:18.


Powered by vBulletin® Version 3.8.8 Beta 2
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.

купить трафик


как улучшить посещаемость, а также решения по монетизации сайтов, видео и приложений

RusProfile.ru


Справочник российских юридических лиц и организаций.
Проекты отопления, пеллетные котлы, бойлеры, радиаторы
интернет магазин respective.ru