Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

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

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

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 05.12.2016, 11:16   #1
sasha1993
Пользователь
 
Регистрация: 26.06.2009
Сообщений: 43
По умолчанию Работа с 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, 12:02   #2
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

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

Изменил на

Код:
if (setsockopt(receivefd, SOCK_DGRAM, SO_RCVTIMEO, (const char*)&val, sizeof DWORD) < 0)
И вывел ошибки с помошью WSAGetLastError(), там 10022 (Invalid argument).
Какой аргумент неверный в этот раз ?
sasha1993 вне форума Ответить с цитированием
Старый 05.12.2016, 16:57   #4
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

SOCK_DGRAM неверный, это не уровень. Нужно указывать уровень к которому применяются настройки один из этих. И параметр SO_RCVTIMEO применяется с уровнем
SOL_SOCKET
Код:
if (setsockopt(receivefd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&val, sizeof DWORD) < 0)
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .

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


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
таймаут idhttp get niva622 Работа с сетью в Delphi 3 25.04.2016 09:40
Другое [PHP/Delphi] Работа с UDP - Заказать программу Mik92 Фриланс 3 07.04.2015 22: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 21:59