1 / 1 / 1
Регистрация: 12.04.2012
Сообщений: 34
1

Небольшая доработка UDP чата

13.01.2013, 13:09. Показов 1262. Ответов 11
Метки нет (Все метки)

Здравствуйте, у меня есть готовый чат на UDP, он работает, но мне нужно, что-бы большие сообщения разделялись на меченные фрагменты. У меня есть набросанные на листе пометки, там создаётся структура из заголовка длинной в 4 байта, и буфера длинной в 51 байт. Но у меня ни как не получается внедрить это в код, что-бы оно работало.


Сервер

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
56
57
58
59
60
61
62
//#pragma comment ( lib, "ws2_32.lib" )
  #include <stdio.h>
  #include <winsock2.h>
 
  int main()
  {
        char buff[1024];                                     // Буфер
    printf("UDP Server Started\n");
 
    // Инициализация WinSock
    WORD wVersionRequested = MAKEWORD (2,2);                // Версия библиотеки
    WSADATA wsaData;
    int err = WSAStartup(wVersionRequested, &wsaData);
    if (err !=0)                                             // Если не равно 0
    {
      printf("WSAStartup error: %d\n",WSAGetLastError());    // Номер ошибки
    }
    else printf("WinSock initialized\n");                    // Инициализация прошла успешно
 
    // Открытие и закрытие сокета
    SOCKET my_sock = socket(AF_INET,SOCK_DGRAM,0);           // Протокол IPv4, UDP
    if (my_sock==INVALID_SOCKET)                             // Если функция завершилась неудачно
    {
      printf("Socket error: %d\n",WSAGetLastError());
      WSACleanup();                                          // Завершение работы с WinSock
    }
 
    // Связывание сокета 
    sockaddr_in sin;                                                  // Заполнени структуры
    sin.sin_family=AF_INET;                                           // Семейство адресов IPv4
    sin.sin_addr.s_addr=htonl(INADDR_ANY);                            // Все адреса локального компьютера
    sin.sin_port=htons(5150);                                         // Номер порта 5150
                                                                      // Привязка сокета к сетевому адресу
    if (bind(my_sock,(sockaddr *) &sin, sizeof(sin))==SOCKET_ERROR)   // Если функция завершилась неудачно 
    {
      printf("bind error: %d\n",WSAGetLastError());                   // Вывод сообщения и номера ошибки
      closesocket(my_sock);                                           // Завершение работы с сокетом
    }
 
    // Обработка присланных пактов
    while(1)                                                          // Заголовок бесконечного цикла
    {
        sockaddr_in client_addr;                                      // Заполнение структуры
        int client_addr_size = sizeof(client_addr);                   // Размер структуры
        int bsize= recvfrom(my_sock,buff,sizeof(buff)-1,0, (sockaddr *) &client_addr, &client_addr_size);
        if (bsize==SOCKET_ERROR)                                      // Если ошибка
        printf("recvfrom() error: %d\n",WSAGetLastError());                     
 
      // Определяем IP-адрес клиента и прочие атрибуты
      HOSTENT *hostent;                                                  // Заполняем структуру
      hostent = gethostbyaddr((char *)&client_addr.sin_addr,4,AF_INET);  // Определяем имя хоста
      printf("New message from %s, ip %s, port %d\n", (hostent)?hostent->h_name:"Unknown host",
      inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
      
      // Добавление завершающего нуля
      buff[bsize]=0;
 
      // Вывод на экран 
      printf("C=>S:%s\n",&buff[0]);
    }
    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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#pragma comment ( lib, "ws2_32.lib" )
  #include <stdio.h>
  #include <winsock2.h>
 
  int main()
  {
    char SERVERADDR[4];     // Адрес сервера
    char buff[1024];     // Буфер
 
    printf("UDP Client Started\n");
 
    // Инициализация WinSock
    WORD wVersionRequested = MAKEWORD (2,2);
    WSADATA wsaData;
    int err = WSAStartup(wVersionRequested, &wsaData);
    if (err !=0) 
    {
      printf("WSAStartup error: %d\n",WSAGetLastError());
    }
 
    // Открытие и закрытие сокета
    SOCKET my_sock=socket(AF_INET, SOCK_DGRAM, 0);
    if (my_sock==INVALID_SOCKET)
    {
      printf("socket() error: %d\n",WSAGetLastError());
      WSACleanup();
    } 
 
    printf("Enter Server IP: ");
    gets(SERVERADDR);                      // Ввод IP-адреса
 
 
    #pragma pack (1)
    struct msg_t;
    {
       long len;
       char buf[51];
    }
    #pragma pack (0)
 
 
    // Связывание сокета
    sockaddr_in dest_addr;
    dest_addr.sin_family=AF_INET;
    dest_addr.sin_port=htons(5150);
    dest_addr.sin_addr.s_addr=inet_addr(SERVERADDR);
 
    while(1)
    {
      // чтение сообщения с клавиатуры
      printf("C=>S:");fgets(buff,sizeof(buff)-1,stdin);
 
      // Передача сообщений на сервер
      sendto(my_sock,buff,strlen(buff),0, (sockaddr *) &dest_addr,sizeof(dest_addr));
    }
 
    closesocket(my_sock);                      // Закрытие сокета
    return 0;
  }
http://img13.imageshost.ru/img... 32266a.jpg
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
13.01.2013, 13:09
Ответы с готовыми решениями:

Вывод udp пакетов. Непонятен код. Небольшая часть кода
Нашел на просторах интернета вот такой код... вернее здесь я убрал лишние хэйдеры и некоторые не...

Небольшая доработка
Программа переводит из 2 системы счисления в 10, необходимо,чтобы при вводе отрицательного числа...

Создание чата по UDP
Всем здрасьте. Задумал учить сокеты. Решил для этого создать некий простой чат в локальной сети по...

Небольшая доработка с формой
Вообщем как добавить картинку в форму,чтобы для каждой записи была отдельная картинка? (Access...

11
Модератор
3338 / 2117 / 345
Регистрация: 13.01.2012
Сообщений: 8,255
13.01.2013, 14:53 2
Цитата Сообщение от Bassist Посмотреть сообщение
мне нужно, что-бы большие сообщения разделялись на меченные фрагменты
зачем?
"как бы аська" на UDP
Прием пакетов по UDP
1
1 / 1 / 1
Регистрация: 12.04.2012
Сообщений: 34
13.01.2013, 14:57  [ТС] 3
Задание такое.
0
Модератор
3338 / 2117 / 345
Регистрация: 13.01.2012
Сообщений: 8,255
13.01.2013, 15:37 4
тогда придется собирать пакеты с учетом порядка (так как не факт что будут доставляться в порядке отправки) с отдельной обработкой "очень долгого запаздывания" некоторых пакетов

Добавлено через 7 секунд
будет весело
0
1 / 1 / 1
Регистрация: 12.04.2012
Сообщений: 34
13.01.2013, 15:49  [ТС] 5
А вверху на фотографии листка есть и sendto для отправки и recvfrom для приёма. Разве они не обеспечат правильную отправку и сборку сообщения по 55 байт в каждом фрагменте? Вобще эти пометки делал преподаватель, так что пока бы мне интегрировать это в код а там посмотрим, из всего вышенаписанного я написал код.

C++
1
2
3
4
5
6
7
    #pragma pack (1)
    struct msg_t;
    {
       long len;
       char buf[51];
    }
    #pragma pack (0)
Я не понимаю строку Msg_t msg; как и где она должна быть в коде?
0
Модератор
3338 / 2117 / 345
Регистрация: 13.01.2012
Сообщений: 8,255
13.01.2013, 18:17 6
на листке нарисовано где она должна быть - в функциях передачи/приема. я так понял исходное сообщение режется на куски размером не более 51 байта (например, сообщение размером 250 байт будет порезано на 4 полных сообщения размером 51 байт и одно неполное с размером 46 байт) и уже эти куски пересылаются, а на другой стороне собираются в исходное сообщение. собирать нужно вам. функции приема/передачи отвечают за прием/передачу кусков. при этом UDP не обеспечивает доставки в той очередности в которой вы отправляли эти куски. поэтому по-хорошему нужно снабжать куски кроме размера и собственно данных еще и полем "номер" для того что бы на принимающей стороне все корректно собрать. для того что бы различать два идущих подряд сообщения с номерами придется мудрить. например, начинать каждое новое сообщение "рукопожатием": клиент отправляет пакет "сейчас начну передавать", а сервер обязательно отвечает "жду" и знает, что сейчас пойдут куски одного сообщения. завершение передачи то же по идее надо аналогичным образом оформить. если вероятностью изменения порядка приема/передачи пренебречь, то можно конечно и просто собирать. а то со сборкой как-то наворочено получается.
1
1 / 1 / 1
Регистрация: 12.04.2012
Сообщений: 34
13.01.2013, 18:53  [ТС] 7
Да 51 байт - данные, 4 байта - заголовок, что-бы не округлялось добавили #pragma pack

C++
1
2
3
4
5
6
7
8
9
#pragma pack (1)
    struct msg_t;
    {
       long len;
       char buf[51];
    }
    #pragma pack (0)
 
msg_t msg;
На строке msg_t msg; подчёркивается msg и выдаётся ошибка "Недопустимый неполный тип". Что я опять не так объявил.

Знаком с C++ недели 3, и кроме этого и ещё одного чата ничего не писал, поэтому мои вопросы такие тупые.
0
Модератор
3338 / 2117 / 345
Регистрация: 13.01.2012
Сообщений: 8,255
13.01.2013, 18:57 8
C++
1
2
3
4
5
    struct msg_t;
    {
       long len;
       char buf[51];
    }; //ОБРАТИТЕ ВНИМАНИЕ НА ТОЧКУ С ЗАПЯТОЙ
0
1 / 1 / 1
Регистрация: 12.04.2012
Сообщений: 34
13.01.2013, 19:08  [ТС] 9
Спасибо, её в упор не видел, а что он означает? Правда ошибка попрежнему на месте.
0
Модератор
3338 / 2117 / 345
Регистрация: 13.01.2012
Сообщений: 8,255
13.01.2013, 19:10 10
а вы уберите точку за запятой после struct msg_t. она означает конец определения структуры.

Добавлено через 33 секунды
...любопытно что на промакашке все верно...
1
1 / 1 / 1
Регистрация: 12.04.2012
Сообщений: 34
13.01.2013, 19:38  [ТС] 11
Спасибо Вам огромное, я всё что можно на этой бумаге проглядел. Сейчас попробую доделать, недеюсь получиться.

Добавлено через 16 минут
Вобщем что-то сделал, оправляются сообщения размером msg_t.

Клиент
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Обработка сообщений
    while(1)
    {
    #pragma pack (1)
    struct msg_t
    {
       long len;
       char buf[51];
    };
    #pragma pack (0)
 
    msg_t msg;
 
 
      // чтение сообщения с клавиатуры
      printf("C=>S:");fgets(buff,sizeof(msg_t)-1,stdin);
 
      // Передача сообщений на сервер
      sendto(my_sock,buff,strlen(buff),0, (sockaddr *) &dest_addr,sizeof(msg_t));

Сервер
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Обработка присланных пакетов
    while(1)                    
    {#pragma pack (1)
    struct msg_t
    {
       long len;
       char buf[51];
    };
    #pragma pack (0)
 
    msg_t msg;
 
        sockaddr_in client_addr;            
        int client_addr_size = sizeof(client_addr);             
        int bsize= recvfrom(my_sock,buff,sizeof(msg_t)-1,0, (sockaddr *) &client_addr, &client_addr_size);
        if (bsize==SOCKET_ERROR)                        
        printf("recvfrom() error: %d\n",WSAGetLastError());
Я не пойму, я отсылаю меченные фрагменты, или нет?
0
Модератор
3338 / 2117 / 345
Регистрация: 13.01.2012
Сообщений: 8,255
13.01.2013, 20:20 12
Цитата Сообщение от Bassist Посмотреть сообщение
я отсылаю меченные фрагменты, или нет
понятия не имею. вы видите какие-нибудь метки? я нет.
хотелось бы обратить ваше внимание на следующее:
1 не нужно определять структуру внутри цикла
2 не нужно читать прямо в структуру - вы затираете поле "длина"
3 вы читаете функцией fgets с клавиатуры? впервые такое вижу.
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
13.01.2013, 20:20

Работаю над контрольной - разработка чата. Нужна небольшая подсказка.
Привет всем. В настоящее время работаю над домашней контрольной по разработке чата. Вообщем-то все...

Выход из чата UDP по нажатию на ESC
Как реализовать выход из чата протоколом UDP в консоли, по нажатию клавиши? using System; using...

Необходима небольшая доработка готовой программы.
Необходима небольшая доработка готовой программы! Програмисты, отзовитесь!

Небольшая доработка кода шифрования XOR
Пожалуйста помогите!!!%-) голова кругом вот этот код работает: void __fastcall...


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

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.