Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.56/25: Рейтинг темы: голосов - 25, средняя оценка - 4.56
0 / 0 / 0
Регистрация: 03.02.2012
Сообщений: 21

UDP сокет. Ошибка в программе.

26.02.2012, 20:56. Показов 5255. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте. Здесь я приведу фрагмент своей программы, в который закралась ошибка. В нём описано, как сервер, используя протокол UDP, принимает запрос от клиента. Делает он это с помощью функции recvfrom. От этой функции он получает адрес клиента. Затем, использую функцию connect, связывает свой сокет с этим адресом, что поможет впоследствии отфильтровать запросы от других клиентов. Возникает здесь ошибка следующего характера: После связывания, команда send работает некорректно, она не отправляет клиенту никаких данных. Возможно, вопрос покажется вам глупым, однако прошу сделать скидку на то, что я ещё новичок по части сетевого программирования. Спасибо.

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
#define REQ_START 1 //Идентификатор команды запроса МАДа
#define LEN_BUF_SOCKET 1000 //длина буфера временного хранения данных сервера
#define SERV_PORT 2000 //порт сокета сервера
 
static int servHandle;  //дескриптор сокета управления сервера
static sockaddr_in servAddress; //адрес сокета сервера
static int lenData; //длина принятой дейтаграммы
static int buf_sock[LEN_BUF_SOCKET];    //буфер временного хранения данных для сервера
static sockaddr_in madAddress;  //адрес сокета МАДа, предназначенного для передачи данных
static unsigned int madLenAddr; //размер структуры адреса МАДа
static int req_START[3]={REQ_START, 0 /*номер версии программного обеспечения МАД*/, 0 /*ID МАД*/}; //пакет запроса МАДа на запуск программы
 
 
int main()
{
    //создание сокета управления
    servHandle=socket(AF_INET,SOCK_DGRAM,0);
    if (servHandle==-1)
    {
        perror("socket not create\n");
        exit(1);
    }
    printf("Создан сокет управления\n");
    //установка адреса сервера и связывание адреса с сокетом
    servAddress.sin_family=AF_INET;
    servAddress.sin_port=htons(SERV_PORT);
    servAddress.sin_addr.s_addr=htonl(INADDR_ANY);
    if ( bind(servHandle, reinterpret_cast<sockaddr*>(&servAddress), sizeof(servAddress) ))
    {
        perror("socket not bind\n");
        exit(1);
    }
    printf("Cокет управления связан со своим адресом\n");
 
    //получение запроса от МАДа и соединение с ним сокета
    for(;;)
    {
        lenData=recvfrom(servHandle, reinterpret_cast<void*>(buf_sock), sizeof(buf_sock), 0, reinterpret_cast<struct sockaddr*>(&madAddress), &madLenAddr);
        printf("Размер структуры адреса равен %d\n", madLenAddr);
        if (lenData==sizeof(req_START) && buf_sock[0]==REQ_START )
        {
            connect(servHandle, reinterpret_cast<struct sockaddr*>(&madAddress), sizeof(madAddress));
            printf("Принят запрос от МАДа на запуск его программы. Версия программного обеспечения МАДа %d. Идентификационный номер МАДа %d\n", buf_sock[1], buf_sock[2]);
            printf("Произошло соединение сокета сервера\n");
            send(servHandle,ans_START_serv, sizeof (ans_START_serv), 0); //разрешение старта программы на МАДе
            break;
        }
        printf("Принят неправильный пакет\n");
    }
}
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
26.02.2012, 20:56
Ответы с готовыми решениями:

Как только происходит попытка создать сокет для UDP - сокет TCP сразу ломается (выдает 10093).
Добрый день. Пытаюсь сделать соединение, использующее два канала обмена данными - TCP для управления в режиме клмиента, и UDP - для...

Производительность Try-Catch в Сокет UDP
Приветствую, есть такая конструкция. IPEndPoint Address = new IPEndPoint(IPAddress.Parse(Ip), (int)Port); Socket = new...

UDP отправка на закрытый сокет (ERROR)
Уже неделю не могу решить эту проблему! Я клиентов на сервере обрабатываю асинхронно в ReceiveCallback(IAsyncResult ar), когда от клиента...

14
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
26.02.2012, 21:06
Цитата Сообщение от korrav Посмотреть сообщение
printf("Размер структуры адреса равен %d\n", madLenAddr);
какой размер выводится?

Добавлено через 3 минуты
Цитата Сообщение от korrav Посмотреть сообщение
connect
Цитата Сообщение от korrav Посмотреть сообщение
send
у тебя же датаграммный сокет

к тому же, ты пытаешься использовать уже привязанный сокет.
по какому протоколу ты хочешь отправить данные?
к то такой ans_START_serv?
0
Модератор
 Аватар для vxg
3407 / 2178 / 354
Регистрация: 13.01.2012
Сообщений: 8,448
26.02.2012, 21:22
madLenAddr не инициализирован. может поэтому вы получаете некорректный сокет. смотрели что вообще записывается при приеме в madAddress?

Добавлено через 6 минут
connect & send для датаграмного сокета допустимы. по отношению к уже привязанному сокету - тоже
1
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
26.02.2012, 21:32
Цитата Сообщение от vxg Посмотреть сообщение
madLenAddr не инициализирован.
кстати да.
The argument addrlen is a value-result argument, which the caller should initialize before the call to the
size of the buffer associated with src_addr, and modified on return to indicate the actual size of the source address.
1
0 / 0 / 0
Регистрация: 03.02.2012
Сообщений: 21
27.02.2012, 07:57  [ТС]
Когда я выковыривал этот фрагмент из своей программы, я, к сожалению, забыл о ans_START_serv. Восполняю:
C
1
2
3
#define OK  1 //заявление, что команда либо выполнена успешно, либо начала выполняться
#define ANS_START_SERVER 1  //Идентификатор команды подтверждение сервера
int ans_START_serv[4]={ANS_START_SERVER, OK, OK, OK}; //ответ-подтверждение сервера
Хотя в данном случае, это, похоже и неважно.
Итак, printf сообщает, что madLenAddr=16. Я проинициализировал madLenAddr, однако, это ситуацию не изменило. Я переписал кусочек с send, чтобы конкретизировать ошибку, вот так:
C
1
2
3
4
5
if(send(servHandle,ans_START_serv, sizeof (ans_START_serv), 0)==-1) //разрешение старта программы на МАДе
{
   perror("Ошибка при выполнении команды send");
   exit(1);
}
Программа сообщает следующее:
Ошибка при выполнении команды send: Destination address required
Похоже, что не нравится форма предоставления адреса получателя, а вот почему не нравиться, мне пока не понятно. Надеюсь, что вы, как люди более опытные, поможете ускорить моё понимание в этом вопросе. Теперь, что касательно, применения функций send и connect. Соглашусь, что довольно нетипично их использование применительно к UDP сокету, однако, если верить этой статье http://www.rsdn.ru/article/unix/sockets.xml это всё-таки возможно. Чтобы избавить вас от поиска нужного фрагмента, я приведу его здесь :
Некоторую путаницу вносят присоединённые датаграммные сокеты (connected datagram sockets). Дело в том, что для сокета с типом SOCK_DGRAM тоже можно вызвать функцию connect, а затем использовать send и recv для обмена данными. Нужно понимать, что никакого соединения при этом не устанавливается. Операционная система просто запоминает адрес, который вы передали функции connect, а затем использует его при отправке данных. Обратите внимание, что присоединённый сокет может получать данные только от сокета, с которым он соединён.
Эти свойства "законнектенных" сокетов мне, в данном случае, довольно выгодны, поэтому я взял их на вооружение в своей программе.
0
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
27.02.2012, 08:03
korrav, в топике, я тебя уже предупреждал про код и теги. исправляй. в следующий раз получишь предупреждение.
0
0 / 0 / 0
Регистрация: 03.02.2012
Сообщений: 21
27.02.2012, 09:00  [ТС]
Цитата Сообщение от niXman Посмотреть сообщение
korrav, в топике, я тебя уже предупреждал про код и теги. исправляй. в следующий раз получишь предупреждение.
Я на форуме ещё плохо ориентируюсь. Сообщите, пожалуйста, ещё раз всё, что я не правильно делаю касательно тегов и кода. Я сейчас пытался найти ваши предыдущие предупреждения и у меня ничего не получилось.
0
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
27.02.2012, 09:34
предыдущее предупреждение в конце первого поста. мелким шрифтом.

при написании сообщения, в тулбаре редактора, есть список языков программирования. (скрин в атаче)
кликаешь на нужный, и в редактор вставляются соответствующие теги. вот между ними и пишешь код.
для цитат тоже есть теги. желтый балун.
Миниатюры
UDP сокет. Ошибка в программе.  
0
0 / 0 / 0
Регистрация: 03.02.2012
Сообщений: 21
27.02.2012, 09:42  [ТС]
Всё понятно. Просто из-за мелкого шрифта я не заметил свою ошибку раннее. Сейчас прочитал правила использования редактора сообщений форума (природная лень не позволила мне сделать это раньше). Впредь буду следовать им.
0
Модератор
 Аватар для vxg
3407 / 2178 / 354
Регистрация: 13.01.2012
Сообщений: 8,448
27.02.2012, 09:45
тестировал под виндой - работает
тест-клиент
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//------------------------------------------------------------------------------
#include <winsock>
#include <stdio.h>
#include <string>
#include <iostream>
//------------------------------------------------------------------------------
int main(int argc, char* argv[])
{
    WSADATA wsa_data;
    if (WSAStartup(0x101, &wsa_data) || wsa_data.wVersion != 0x101) return -1;
 
    SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (s == INVALID_SOCKET) return -1;
 
    SOCKADDR_IN sa;
    sa.sin_family = AF_INET;
    sa.sin_port = htons(2000);
    sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
 
    char *msg = "ZXCASD";
    if
    (
        sendto
        (
            s,
            msg, 7,
            0,
            (SOCKADDR *)&sa, sizeof(sa)
        ) == SOCKET_ERROR
    )
        return -1;
 
    char buffer[1024];
    int buffer_size = sizeof(buffer);
    if
    (
        recvfrom(s, buffer, buffer_size, 0, 0, 0) ==
            SOCKET_ERROR
    )
        return -1;
    printf("message=%s\n", buffer);
 
    closesocket(s);
 
    WSACleanup();
 
    system("pause");
    return 0;
}
тест-сервер
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//------------------------------------------------------------------------------
#include <winsock>
#include <stdio.h>
//------------------------------------------------------------------------------
int main(int argc, char* argv[])
{
    WSADATA wsa_data;
    if (WSAStartup(0x101, &wsa_data) || wsa_data.wVersion != 0x101) return -1;
 
    SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (s == INVALID_SOCKET) return -1;
 
    SOCKADDR_IN sa;
    sa.sin_family = AF_INET;
    sa.sin_port = htons(2000);
    sa.sin_addr.S_un.S_addr = inet_addr("0");
 
    if (bind(s, (SOCKADDR *)&sa, sizeof(sa)) == SOCKET_ERROR) return -1;
 
    SOCKADDR_IN nsa;
    int sizeof_nsa = sizeof(nsa);
 
    char buffer[1024];
    int buffer_size = sizeof(buffer);
    if
    (
        recvfrom(s, buffer, buffer_size, 0, (SOCKADDR *)&nsa, &sizeof_nsa) ==
            SOCKET_ERROR
    )
        return -1;
    printf("message=%s\n", buffer);
 
    if (connect(s, (SOCKADDR *)&nsa, sizeof_nsa) == SOCKET_ERROR) return -1;
 
    char *msg = "QWEASD";
    if (send(s, msg, 7, 0) == SOCKET_ERROR) return -1;
 
    closesocket(s);
 
    WSACleanup();
 
    system("pause");
    return 0;
}
0
0 / 0 / 0
Регистрация: 03.02.2012
Сообщений: 21
27.02.2012, 11:52  [ТС]
Очень странно, почему у меня по сути тоже самое не работает под Linux. Попробую поиграться с преобразованием типов, которое я произвожу над структурой адреса в recvfrom:
C++
1
lenData=recvfrom(servHandle, reinterpret_cast<void*>(buf_sock), sizeof(buf_sock), 0, reinterpret_cast<struct sockaddr*>(&madAddress), &madLenAddr);
а также в connect:
C++
1
connect(servHandle, reinterpret_cast<struct sockaddr*>(&madAddress), sizeof(madAddress));
Переделаю этот момент и посмотрю, что будет.

Добавлено через 1 час 51 минуту
Я изменил код программы. Теперь madAddress имеет тип sockaddr. Таким образом я избавился от приведения типов в вышеуказанных функциях. И это, к сожалению, не помогло. Также следует отметить, что сообщения от клиента принимаются, правильно идентифицируются, сокет сервера при применении функции connect успешно связывается с адресом клиента, во всяком случае никакой ошибки не возвращается:

C++
1
2
3
4
5
if(-1==connect(servHandle, madAddress, sizeof(madAddress)))
{
    perror("Не работает функция connect\n");
    exit(1);
}
Когда я посылаю сообщение клиенту пользуясь функцией sendto с указанием в явном виде его адреса, клиент успешно принимает сообщение.
И тем не менее.... Так что танцы с бубнами продолжаются.
0
Модератор
 Аватар для vxg
3407 / 2178 / 354
Регистрация: 13.01.2012
Сообщений: 8,448
27.02.2012, 11:54
а мой пример пробывали запускать на линухе? работает?
0
0 / 0 / 0
Регистрация: 03.02.2012
Сообщений: 21
27.02.2012, 12:00  [ТС]
Сейчас попробую.
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
27.02.2012, 12:49
connect() у Вас просто не работает, т.к. madLenAddr в recvfrom() 0.
0
0 / 0 / 0
Регистрация: 03.02.2012
Сообщений: 21
27.02.2012, 22:28  [ТС]
Блин, оказалось, что неправильно инициализировал madLenAddr. Программа довольно объёмная, вот я и подправил не тот define. Как только исправил эту ошибку, программа заработала. Всех благодарю за помощь и прошу прощения, что отвлёк из-за своей невнимательности.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
27.02.2012, 22:28
Помогаю со студенческими работами здесь

Один сокет для TCP и UDP
Привет. Клиент-серверное приложение в один промежуток времени использует TCP, но через некоторое время нужно начать передавать и принимать...

Отправить сериализованный объект через сокет по UDP
Доброй ночи, уважаемые форумчане! Нужна консультация по отправке сериализованного объекта по UDP-протоколу (размер файла невелик, файл...

Как через UDP сокет соединить трёх клиентов без сервера?
Люди подскажите как через UDP сокет соединить трёх клиентов без сервера

Материнка 775 сокет и процессор 771 сокет, Совместимость
Ребят помогите пожалуйста, попробовал разобраться Сам и только запутался больше... Вообщем имеется материнка g31t-m rev 1.0 вот ссылка...

4 планки Apacer DDR3 по 4Gb/1333MHz от старой МВ сокет 775 могу ли я их использовать на сокет 2011
недавно решил перейти с LGA775 на LGA2011. Финансы урезаны поэтому пока приобрёл только процессор Intel Core i7 - 3820 oem, 3.60GHz/ 10 MB/...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит переходные токи и напряжения на элементах схемы. . . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru