Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> разные типы данных в сокет, как передать в одном сообщении 
V
    Опции темы
bsa
Дата 18.11.2008, 17:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



knopka, если пишешь на С++, то можно сделать примерно так:
Код
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>

struct Header
{
    int field1;
    int field2;
    int field3;
//...
    std::string text;
    void send(int socket) const {
        send(socket, reinterpret_cast<const char*>(&field1), sizeof(field1), NULL);
        send(socket, reinterpret_cast<const char*>(&field2), sizeof(field2), NULL);
        send(socket, reinterpret_cast<const char*>(&field3), sizeof(field3), NULL);
//...
        unsigned textSize = text.size();
        send(socket, reinterpret_cast<const char*>(&textSize), sizeof(textSize), NULL);
        send(socket, text.data(), textSize, NULL);
    }
    void recv(int socket) const {
        recv(socket, reinterpret_cast<char*>(&field1), sizeof(field1), NULL);
        recv(socket, reinterpret_cast<char*>(&field2), sizeof(field2), NULL);
        recv(socket, reinterpret_cast<char*>(&field3), sizeof(field3), NULL);
//...
        unsigned textSize;
        recv(socket, reinterpret_cast<char*>(&textSize), sizeof(textSize), NULL);
        std::vector<char> tmp(textSize);
        recv(socket, &*tmp.begin(), textSize, NULL);
        text.clean();
        std::copy(tmp.begin(), tmp.end(), std::back_inserter(text));
    }
};

PM   Вверх
knopka
Дата 18.11.2008, 19:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 187
Регистрация: 17.1.2006
Где: Россия: Петербург

Репутация: нет
Всего: 1



to REZiaMIX

Цитата

Чё -то сообщение пустое 


от сервера 

на сервере обработка эхом
Код

a mess;

new_sock >> mess;//получили
new_sock << mess;//отослали 


стандартное построение классов Socket - ClientSocket - SimpleClientMain 

 а в клиенте  после приема ответ все поля у структуры а пустые
PM MAIL ICQ   Вверх
knopka
Дата 18.11.2008, 19:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 187
Регистрация: 17.1.2006
Где: Россия: Петербург

Репутация: нет
Всего: 1



to bsa

не нашёл описания 
Цитата

reinterpret_cast

я так понимаю преобразует тип поля в <char*>?

а нельзя как то посимвольно перечитать структуру в вектор? (в смысле конвертировать)

буду пробовать и этот вариант
PM MAIL ICQ   Вверх
REZiaMIX
Дата 18.11.2008, 20:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 346
Регистрация: 3.11.2007

Репутация: 1
Всего: 4



Цитата(bsa @ 18.11.2008,  17:32)
knopka, если пишешь на С++, то можно сделать примерно так:

А зачем посылать 3 инта отдельно?)


--------------------
user posted image
PM MAIL   Вверх
REZiaMIX
Дата 18.11.2008, 21:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 346
Регистрация: 3.11.2007

Репутация: 1
Всего: 4



Дабы закончить эту тему:
Сервер:
Код

#include <windows.h>
#include <stdio.h>
#include <conio.h>

#pragma comment(lib,"ws2_32.lib")

SOCKET my_sock;
#pragma pack(push, 1)
struct packet
{
    int val1;
    int val2;
    int val3;
    unsigned int len;
    char *string;
    void pcsend(SOCKET to)
    {
        printf("Send:\nval1=%i\nval2=%i\nval3=%i\nlen=%i\nstring=%s\n",val1,val2,val3,len,string);
        send(to,(char*)this,sizeof(int)*3 + sizeof(unsigned int),NULL);
        send(to,string,len,NULL);
        delete [] string;
    }
    void pcrecv(SOCKET from)
    {
        recv(from,(char*)this,sizeof(int)*3 + sizeof(unsigned int),NULL);
        string = new char[len+1];
        recv(from,string,len,NULL);
        string[len] = '\0';
        printf("Recv:\nval1=%i\nval2=%i\nval3=%i\nlen=%i\nstring=%s\n",val1,val2,val3,len,string);
        val1++;
        val2++;
        val3++;
        delete [] string;
    }
};

#pragma pack(pop)
#pragma pack(pop)

#define SERVERADDR "127.0.0.1"

int main(int argc,char*argv[])
{
    unsigned int port = 5432;
    SOCKADDR_IN serverSockAddr;
    SOCKADDR_IN clientSockAddr;
    SOCKET serverSocket;
    SOCKET clientSocket;
    int addrLen=sizeof(SOCKADDR_IN);
    WSAData wd;
    WSAStartup(0x202,&wd);
    serverSocket=socket(AF_INET, SOCK_STREAM, 0);
    memset(&serverSockAddr, 0, sizeof(serverSockAddr));
    serverSockAddr.sin_port=htons(port);
    serverSockAddr.sin_family=AF_INET;
    serverSockAddr.sin_addr.s_addr=htonl(INADDR_ANY);
    bind(serverSocket,
        (LPSOCKADDR) &serverSockAddr,
        sizeof(serverSockAddr));

    listen(serverSocket, 1);

    clientSocket=accept(serverSocket,
        (LPSOCKADDR) &clientSockAddr,
        &addrLen);
    char string[] = "Hello client!!!";
    packet tosend;
    tosend.pcrecv(clientSocket);
    tosend.len = strlen(string);
    tosend.string = new char[tosend.len+1];
    strcpy(tosend.string,string);
    tosend.pcsend(clientSocket); 
    _getch();
}


Клиент:
Код

#include <windows.h>
#include <stdio.h>
#include <conio.h>

#pragma comment(lib,"ws2_32.lib")
SOCKET my_sock;
#pragma pack(push, 1)
struct packet
{
    int val1;
    int val2;
    int val3;
    unsigned int len;
    char *string;
    void pcsend(SOCKET to)
    {
        printf("Send:\nval1=%i\nval2=%i\nval3=%i\nlen=%i\nstring=%s\n",val1,val2,val3,len,string);
        send(to,(char*)this,sizeof(int)*3 + sizeof(unsigned int),NULL);
        send(to,string,len,NULL);
        delete [] string;
    }
    void pcrecv(SOCKET from)
    {
        recv(from,(char*)this,sizeof(int)*3 + sizeof(unsigned int),NULL);
        string = new char[len+1];
        recv(from,string,len,NULL);
        string[len] = '\0';
        printf("Recv:\nval1=%i\nval2=%i\nval3=%i\nlen=%i\nstring=%s\n",val1,val2,val3,len,string);
        val1++;
        val2++;
        val3++;
        delete [] string;
    }
};

#pragma pack(pop)

#define SERVERADDR "127.0.0.1"

int main(int argc,char*argv[])
{
    unsigned int port = 5432;

    WSAData wd;
    WSAStartup(0x202,&wd);
    my_sock=socket(AF_INET,SOCK_STREAM,0);
    sockaddr_in dest_addr;
    dest_addr.sin_family=AF_INET;
    dest_addr.sin_port=htons(port);
    HOSTENT *hst;


    if (inet_addr(SERVERADDR)!=INADDR_NONE)
      dest_addr.sin_addr.s_addr=inet_addr(SERVERADDR);
    else
      if (hst=gethostbyname(SERVERADDR))
          ((unsigned long *)&dest_addr.sin_addr)[0]=
            ((unsigned long **)hst->h_addr_list)[0][0];

    connect(my_sock,(sockaddr *)&dest_addr,
                    sizeof(dest_addr));

    char string [] = "Hello Server!!!";        
    packet tosend;
    tosend.val1 = 666;
    tosend.val2 = 1;
    tosend.val3 = -1;
    tosend.len = strlen(string);
    tosend.string = new char[tosend.len+1];
    strcpy(tosend.string,string);
    tosend.string[tosend.len] = '\0';
    
    tosend.pcsend(my_sock);
    tosend.pcrecv(my_sock); 
    _getch();
}



Писал на коленках , но компилируется и работает 100%. Клиент посылает 3 числа и строчку. Сервер увеличивает числа на 1 , меняет строчку и отвечает.


--------------------
user posted image
PM MAIL   Вверх
knopka
Дата 19.11.2008, 00:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 187
Регистрация: 17.1.2006
Где: Россия: Петербург

Репутация: нет
Всего: 1



to REZiaMIX

спасибо только не пойму где компилить 

судя по 
Цитата

#include <conio.h>

 в винде, попробовал в CodeBlocks и в VisualStudio ошибки

и ещё вопрос
Цитата

Код

send(to,(char*)this,sizeof(int)*3 + sizeof(unsigned int),NULL);
        send(to,string,len,NULL);


почему два раза посылаем, сначала цифры а потом строку?

Добавлено через 14 минут и 17 секунд
to REZiaMIX

Я Вас наверно уже достал ну ещё вопрос

А в Linux есть альтернатива
Код

WSAData 


PM MAIL ICQ   Вверх
REZiaMIX
Дата 19.11.2008, 12:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 346
Регистрация: 3.11.2007

Репутация: 1
Всего: 4



Цитата

судя по 
Цитата

#include <conio.h>

 в винде, попробовал в CodeBlocks и в VisualStudio ошибки

conio.h используется для _getch();
можно заменить чемнить другим и избавиться от заголовка.

Цитата

и ещё вопрос
Цитата

Код

send(to,(char*)this,sizeof(int)*3 + sizeof(unsigned int),NULL);
        send(to,string,len,NULL);


почему два раза посылаем, сначала цифры а потом строку?

Т.к. string в данном случае в структуре - указатель на 0 символ строки.
Если послать структуры целиком , то вместо строки пошлем указатель на нее , что не верно.
Сначала посылаем 3 инта структуры(val1,val2,val3) + uint(len)
Код

sizeof(int)*3 + sizeof(unsigned int)

потом посылаем строку.
Цитата


А в Linux есть альтернатива
Код

WSAData 



Наверное не правильный выход , но прокатит это:
Код


    char buff[1024];
    WSAStartup(0x202,(WSADATA *) &buff[0]);

Вообще в никсах посмотри описание WSAStartup и подгони тип данных.

Это сообщение отредактировал(а) REZiaMIX - 19.11.2008, 12:10


--------------------
user posted image
PM MAIL   Вверх
bsa
Дата 20.11.2008, 11:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Цитата(knopka @ 18.11.2008,  19:56)
to bsa

не нашёл описания 
Цитата

reinterpret_cast

я так понимаю преобразует тип поля в <char*>?
reinterpret_cast это преобразование одного типа в другой. Используется, когда не работают static_cast и dynamic_cast. Это стандартные "преобразователи" C++. В принципе, можно написать и (const char*)&field1, но это устаревшая (для С++) форма записи.
Цитата(knopka @ 18.11.2008,  19:56)
а нельзя как то посимвольно перечитать структуру в вектор? (в смысле конвертировать)
Можно и структуру "конвертировать" в вектор, а нужно ли? Но мне показалось это лишним в данном месте...

Цитата(REZiaMIX)
А зачем посылать 3 инта отдельно?)
А ты уверен, что выравнивание у структуры будет на обеих сторонах (клиент-сервер) одинаковым?  smile 
PM   Вверх
knopka
Дата 20.11.2008, 18:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 187
Регистрация: 17.1.2006
Где: Россия: Петербург

Репутация: нет
Всего: 1



Большое спасибо to REZiaMIX и bsa очень помогли вопрос закрыт
PM MAIL ICQ   Вверх
REZiaMIX
Дата 20.11.2008, 19:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 346
Регистрация: 3.11.2007

Репутация: 1
Всего: 4



Цитата(bsa @ 20.11.2008,  11:54)
ты уверен, что выравнивание у структуры будет на обеих сторонах (клиент-сервер) одинаковым?  smile

Хм , ну если здесь пишем клиент  , то выравнивание задать можем , значит можем быть уверенны)
Вообще , нужно знать что нужно знать протокол клиент<->сервер , чтобы таких вопросов не возникало)
Думаю в данном случае оба решения подойдут)


--------------------
user posted image
PM MAIL   Вверх
knopka
Дата 20.11.2008, 19:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 187
Регистрация: 17.1.2006
Где: Россия: Петербург

Репутация: нет
Всего: 1



ДА оба подходят
PM MAIL ICQ   Вверх
J0ker
Дата 20.11.2008, 20:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 9
Всего: 14



все вышенаписанное для TCP соединения на прием работать НЕ БУДЕТ
т.к. фрагментация


--------------------
user posted image
PM MAIL   Вверх
REZiaMIX
Дата 21.11.2008, 08:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 346
Регистрация: 3.11.2007

Репутация: 1
Всего: 4



Цитата(J0ker @ 20.11.2008,  20:26)
все вышенаписанное для TCP соединения на прием работать НЕ БУДЕТ
т.к. фрагментация

Хм , поясни , у меня все работает как ни крути


--------------------
user posted image
PM MAIL   Вверх
bsa
Дата 21.11.2008, 10:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Кстати, мой вариант работать точно не должен - в описании recv написано, что в случае если полученные данные не помещаются в буфер - излишек теряется. Таким образом действительно надо делать все через вектор...
PM   Вверх
J0ker
Дата 21.11.2008, 18:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 9
Всего: 14



Цитата(REZiaMIX @ 21.11.2008,  08:25)
Цитата(J0ker @ 20.11.2008,  20:26)
все вышенаписанное для TCP соединения на прием работать НЕ БУДЕТ
т.к. фрагментация

Хм , поясни , у меня все работает как ни крути

ну просто пока везет  smile 
данные, отправленные через TCP могут приходить как угодно фрагментированные, даже если были отправлены через send одним куском
recv заполняет буфер только тем, что пришло на данный момент

Добавлено через 1 минуту и 33 секунды
Цитата(bsa @  21.11.2008,  10:23 Найти цитируемый пост)
Кстати, мой вариант работать точно не должен - в описании recv написано, что в случае если полученные данные не помещаются в буфер - излишек теряется.

это верно только для UDP пакетов
для TCP ничего не теряется

Это сообщение отредактировал(а) J0ker - 21.11.2008, 18:50


--------------------
user posted image
PM MAIL   Вверх
Страницы: (3) Все 1 [2] 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0582 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.