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

Winsock, работа с полученным ответом

22.05.2014, 23:38. Показов 1595. Ответов 12
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Передачу данных клиенту на сервере делает следующая строка:
C++
1
this->iSendResult = send( this->ClientSocket, ArpTable::getArpTable(), this->iResult, 0 );
ArpTable::getArpTable() возвращает двумерный массив.
Клиент принимает данные так:
C++
1
this->iResult = recv(this->ConnectSocket, this->recvbuf, this->recvbuflen, 0);
Вроде какие-то данные приходят, но как мне с ними правильно работать дальше не знаю. Надо их как-то преобразовать обратно в двумерный массив. Помогите пожалуйста.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
22.05.2014, 23:38
Ответы с готовыми решениями:

Работа с ответом из БД (MySQL)
Есть таблица примерно такого вида: В ней пользователи и их статистические данные (не важно какого рода) Задача сформировать...

Работа с ответом API
доброго времени суток! есть API ( http://134.0.113.128/index.php?r=api%2Fproviders ), он возращает ответ одну строку. в этой строке...

Работа с полученным через $.get() обьектом/данными
Господа! 3й день бьюсь с одной функцией! var userIdD = $.get('http://someurl.com/options.php', function(abc) { var abc = $(abc);...

12
Эксперт С++
 Аватар для schdub
3073 / 1411 / 425
Регистрация: 19.01.2009
Сообщений: 3,894
23.05.2014, 00:20
Цитата Сообщение от SerjInsane Посмотреть сообщение
ArpTable::getArpTable()
покажите прототип функции
0
0 / 0 / 0
Регистрация: 18.10.2012
Сообщений: 30
23.05.2014, 08:24  [ТС]
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
static char* getArpTable()
    {
         
        ULONG nSize = ARP_TABLE_SIZE;
    
        PMIB_IPNETTABLE pMib = (PMIB_IPNETTABLE)malloc(sizeof(MIB_IPNETTABLE)+sizeof(MIB_IPNETROW)*nSize);
 
        DWORD dwRet = GetIpNetTable(pMib,&nSize,TRUE);     
 
        if (nSize>ARP_TABLE_SIZE) {
             nSize = ARP_TABLE_SIZE;
        } else {
             nSize = (int)pMib->dwNumEntries ;
        }
    
        char *arpArray[ARP_TABLE_SIZE][3];
 
        for (int i=0; i<nSize; i++) 
        {
            char ipaddr[20], macaddr[20], type[20];
 
            sprintf_s(ipaddr,"%d.%d.%d.%d",
                    ( pMib->table[i].dwAddr&0x0000ff),    ((pMib->table[i].dwAddr&0xff00)>>8),
                    ((pMib->table[i].dwAddr&0xff0000)>>16),(pMib->table[i].dwAddr>>24)
            );
 
            sprintf_s(macaddr, "%02x-%02x-%02x-%02x-%02x-%02x",
                   pMib->table[i].bPhysAddr[0],pMib->table[i].bPhysAddr[1],
                   pMib->table[i].bPhysAddr[2],pMib->table[i].bPhysAddr[3],
                   pMib->table[i].bPhysAddr[4],pMib->table[i].bPhysAddr[5]
            );
 
            if      (pMib->table[i].dwType == 3) strcpy_s(type, "Dynamic"); 
            else if (pMib->table[i].dwType == 4) strcpy_s(type, "Static");
 
            arpArray[i][0] = ipaddr;
            arpArray[i][1] = macaddr;
            arpArray[i][2] = type;
        }
         
        return **arpArray;
    }
0
Модератор
 Аватар для vxg
3407 / 2178 / 354
Регистрация: 13.01.2012
Сообщений: 8,448
23.05.2014, 09:13
1 массив возвращаемый вашей функцией находится в стеке - после завершения функции его не существует
2 что в this->iResult? по идее там размер массива, но я не видел где бы внутри функции он вычислялся
3 при посылке строк не нужно слать указатели на эти строки - шлите содержимое этих строк
4 ну а на той стороне просто положите полученные данные в соответствующее место - в чем прикол?
1
0 / 0 / 0
Регистрация: 18.10.2012
Сообщений: 30
23.05.2014, 19:56  [ТС]
vxg, омг! тогда прошу помощи у знающих людей. я сам php изучаю, там с объявлением динамических многомерных массивов и их возвратом из функции вообще заморачиваться не надо. а тут я в ужасе за голову берусь. помогите исправить мою функцию, дабы она возвращала массив так, как необходимо было бы его в последствии передать в send(). заранее благодарен.
0
Эксперт С++
 Аватар для schdub
3073 / 1411 / 425
Регистрация: 19.01.2009
Сообщений: 3,894
23.05.2014, 22:24
SerjInsane, в этой функции есть утечка памяти (pMib).

Может все таки не преобразовывать в строки на отсылащей стороне, а слать бинарными данными, a уже на принимающе стороне преобразовывать в строки если вам это нужно. Так же нужно передавать размер данных перед посылкой, чтобы принимающая сторона знала сколько ей нужно прочитать из сокета. Вот приблизительный набросок:
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
//...
 
struct ARP_MESSAGE_ROW {
    DWORD dwAddr;
    UCHAR bPhysAddr[MAXLEN_PHYSADDR];
    DWORD dwType;
};
 
//...
 
static int getArpTable(struct ARP_MESSAGE_ROW ** arpRows) {
    struct ARP_MESSAGE_ROW * prows = NULL;
    int rowsCount = 0, done = 0;
 
    // TODO: выделяем сколько нужно памяти под prows, заполняем ее
 
    if (!done) {
        free(prows);
        *arpRows = 0;
        return 0;
    }
 
    *arpRows = prows;
    return rowsCount;
}
 
//...
 
void foo() {
    struct ARP_MESSAGE_ROW * arpRows = NULL;
    int count = getArpTable(&arpRows), rc, len;
    if (count > 0) {
        // шлем размер данных, чтобы принимающая сторона знала
        // сколько данных ей нужно прочитать
        len = count * sizeof(struct ARP_MESSAGE_ROW);
        rc = send(this->ClientSocket, (char*)&len, sizeof(int), 0);
        // шлем данные
        rc = send(this->ClientSocket, (char*) arpRows, len, 0);
        free(arpRows);
    }
}
 
//...
PS: проверка ошибок опущена
1
0 / 0 / 0
Регистрация: 18.10.2012
Сообщений: 30
24.05.2014, 00:53  [ТС]
schdub,
// шлем размер данных, чтобы принимающая сторона знала
// сколько данных ей нужно прочитать
а как принимающая сторона прочитает переданные размеры данных?
0
Эксперт С++
 Аватар для schdub
3073 / 1411 / 425
Регистрация: 19.01.2009
Сообщений: 3,894
24.05.2014, 01:11
Цитата Сообщение от SerjInsane Посмотреть сообщение
а как принимающая сторона узнает сколько ей принять информации о размере данных?
прочитает int непосредственно перед порцией данных.

И еще работая с сокетами нужно убеждатся все ли данные были записаны/прочитаны (см реализации write_all, read_all):

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
// пишем в @sd сокет @count байт из буффера @buff
 
static int write_all(SOCKET sd, const char * buff, int count) {
    int total = 0;
    for (int iret = 0; total < count;) {
        iret = send(sd, buff + total, count - total, 0);
        if (iret <= 0) {
//            WARN("send() err='%s'", get_lasterror());
            total = iret;
            break;
        }
        total += iret;
    }
    return total;
}
 
// читаем из @sd сокета @count байт в буффер @buff
 
static int read_all(SOCKET sd, char * buff, int count) {
    int total = 0;
    for (int iret = 0; total < count;) {
        iret = recv(sd, buff + total, count - total, 0);
        if (iret <= 0) {
//            WARN("recv() sd=%d err='%s'", sd, get_lasterror());
            total = iret;
            break;
        }
        total += iret;
    }
    return total;
}
 
void foo() {
    int len;
    ARP_MESSAGE_ROW * prows = NULL;
    SOCKET sock;
 
    // HIXME: проверить ошибки
 
    // читаем размер данных
    read_all(sock, (char*) &len, sizeof(int));
 
    // TODO: проверяем валидность len здесь
 
    // проверим хватает ли у нас памяти для чтения
    prows = (ARP_MESSAGE_ROW*) realloc(prows, len);
    read_all(sock, (char*) prows, len);
 
    // TODO: делаем что-то с данными
}
1
0 / 0 / 0
Регистрация: 18.10.2012
Сообщений: 30
24.05.2014, 13:09  [ТС]
schdub, и все же остались еще некоторые неясности для меня. правильно распоряжаться памятью я не умею, привык что php это все делает за меня.
1)
struct ARP_MESSAGE_ROW {
DWORD dwAddr;
UCHAR bPhysAddr[MAXLEN_PHYSADDR];
DWORD dwType;
};
не совсем понимаю почему мак адресу мы присваиваем макс длину, а IP адресу скажем нет. у маков ведь будет одинаковая длинна.
2)
// TODO: выделяем сколько нужно памяти под prows, заполняем ее
как правильно посчитать сколько нужно памяти?
C++
1
nSize = (int)pMib->dwNumEntries;
возвращает количество вхождений, как я понимаю отталкиваться нужно от этого? или как? блин, пожалуйста опишите подробней этот кусок кода и как правильно заполнить структуру получаемыми данными, очень прошу.
3)
int count = getArpTable(&arpRows), rc, len;
я понимаю, что мы передаем ссылку на структуру и в нее запишутся необходимые данные, а результат вернет количество так сказать найденных вхождений. а вот как понимать то, что идет дальше через запятую, куда это запишется и как это работает?
0
Эксперт С++
 Аватар для schdub
3073 / 1411 / 425
Регистрация: 19.01.2009
Сообщений: 3,894
24.05.2014, 14:12
Лучший ответ Сообщение было отмечено Eva Rosalene как решение

Решение

SerjInsane,
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
#include <windows.h>
#include <iphlpapi.h>
 
#pragma comment (lib, "iphlpapi.lib")
 
__declspec(align(1)) struct ARP_MESSAGE_ROW {
    DWORD dwAddr;
    DWORD dwType;
    UCHAR bPhysAddr[MAXLEN_PHYSADDR];
};
 
static int getArpTable(ARP_MESSAGE_ROW ** arpRows) {
    ARP_MESSAGE_ROW * prows = NULL;
    int rowsCount = 0, done = 0;
    MIB_IPNETTABLE * pTable = 0;
    DWORD i, dwSize = 0;
 
    // первый вызов, проверяем сколько нужно выделить памяти
    // в dwSize вернется количество байт необходимое GetIpNetTable()
    if (GetIpNetTable(pTable, &dwSize, 1) == ERROR_INSUFFICIENT_BUFFER) {
        // выделяем необходимую память для вызова функции GetIpNetTable()
        pTable = (MIB_IPNETTABLE  *) malloc(dwSize);
        // получаем данные
        if (pTable && GetIpNetTable(pTable, &dwSize, 1) == NO_ERROR) {
            // выделяем память для возврата из текущей функции
            prows  = (ARP_MESSAGE_ROW *) malloc(pTable->dwNumEntries * sizeof(ARP_MESSAGE_ROW));
            // заполняем структуру для возврата
            if (prows) {
                rowsCount = pTable->dwNumEntries;
                for (i = 0; i < pTable->dwNumEntries; ++i) {
                    prows[i].dwType    = pTable->table[i].dwType;
                    prows[i].dwAddr    = pTable->table[i].dwAddr;
                    memcpy(prows[i].bPhysAddr, pTable->table[i].bPhysAddr, MAXLEN_PHYSADDR);
                }
                done = 1;
            }
        }
    }
 
    // очищаем память, выделенную для вызова GetIpNetTable()
 
    free(pTable);
 
    if (!done) {
        free(prows);
        *arpRows = 0;
        return 0;
    }
 
    *arpRows = prows;
    return rowsCount;
}
 
void foo() {
    struct ARP_MESSAGE_ROW * arpRows = NULL;
    int count = getArpTable(&arpRows);
    if (count > 0) {
        // TODO: работаем с arpRows
        free(arpRows);
    }
}
1
0 / 0 / 0
Регистрация: 18.10.2012
Сообщений: 30
24.05.2014, 22:24  [ТС]
schdub, с меня пиво! шлю размер данных которые надо считать, отсылаю сами данные, вроде все ок. и все же я туплю дальше. теперь уже на стороне клиента. и как можно было бы наверное догадаться теперь я не знаю как правильно эти данные распихать. прошу помощи и в этом вопросе. думаю осталось только в этом разобраться, а дальше все пойдет как по маслу.
0
Эксперт С++
 Аватар для schdub
3073 / 1411 / 425
Регистрация: 19.01.2009
Сообщений: 3,894
25.05.2014, 01:28
Лучший ответ Сообщение было отмечено SerjInsane как решение

Решение

SerjInsane,

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
static void processArpTable(ARP_MESSAGE_ROW * arpRows, int count) {
    for (int i = 0; i < count; ++i) {
        char ipaddr[20], macaddr[20], type[20];
 
        sprintf_s(ipaddr, "%d.%d.%d.%d",
            ( arpRows[i].dwAddr & 0x0000ff),
            ((arpRows[i].dwAddr & 0xff00  ) >>  8),
            ((arpRows[i].dwAddr & 0xff0000) >> 16),
            ( arpRows[i].dwAddr             >> 24)
        );
 
        sprintf_s(macaddr, "%02x-%02x-%02x-%02x-%02x-%02x",
            arpRows[i].bPhysAddr[0], arpRows[i].bPhysAddr[1],
            arpRows[i].bPhysAddr[2], arpRows[i].bPhysAddr[3],
            arpRows[i].bPhysAddr[4], arpRows[i].bPhysAddr[5]
        );
 
        if      (arpRows[i].dwType == 3) strcpy_s(type, "Dynamic"); 
        else if (arpRows[i].dwType == 4) strcpy_s(type, "Static");
 
        // TODO: делаем что-то со строками
    }
}

C
1
2
3
4
5
6
7
8
9
10
11
    // ...
    // ОТСЫЛАЮЩАЯ СТОРОНА
    // ...
 
    len = getArpTable(&prows);
    if (len > 0) {
        len *= sizeof(ARP_MESSAGE_ROW);
        rc = write_all(sock, (char*) &len, sizeof(int));
        rc = write_all(sock, (char*) prows, len);
        free(prows);
    }
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    // ...
    // ПРИНИМАЮЩАЯ СТОРОНА
    // ...
 
    // читаем размер данных
    rc = read_all(sock, (char*) &len, sizeof(int));
 
    // TODO: проверяем валидность len здесь
 
    // проверим хватает ли у нас памяти для чтения
    prows = (ARP_MESSAGE_ROW*) realloc(prows, len);
    rc = read_all(sock, (char*) prows, len);
    if (rc == len) {
        processArpTable(prows, len / sizeof(ARP_MESSAGE_ROW));
    }
1
0 / 0 / 0
Регистрация: 18.10.2012
Сообщений: 30
25.05.2014, 13:40  [ТС]
schdub, огромное спасибо за неоценимую помощь.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
25.05.2014, 13:40
Помогаю со студенческими работами здесь

Работа с полученным двумерным массивом Excel в VBA
Приветствую вас, уважаемые знатоки! Я долго пытаюсь что-то сделать с этой проблемой, но, все мои попытки &quot;обламываются&quot; на пол...

Работа с массивом, полученным при запросе mysql_fetch_array($result)
Здравствуйте! Подскажите пожалуйста, как работать с такими массивами ( найти максимум, минимум, количество членов массива). До этого...

Работа с winsock
Доброго времени суток. Запилил клиент-серверное приложение по примеру отсюда:...

Работа с WinSock.dll напрямую
Подскажите, кто знает, ссылку - как работать с WinSock.dll напрямую, без всяких компонентов.

Работа с winsock: accept возвращает INVALID_SOCKET
есть два проекта server и client, объединенные в один declare.h (один на оба проекта) #pragma once #include &lt;iostream&gt; ...


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

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
Влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru