Модераторы: Snowy, Poseidon, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Переслать структуру, на Winsock 
V
    Опции темы
MaXL
Дата 28.1.2008, 15:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Developer
**


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

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



Всем привет.
Есть структура:
Код

  TPacket = record
    u_Magic:  WORD;   //магическое поле, должно быть равно в $0D
    u_Type:   WORD;   //тип пакета, константы начинаются с PT_***
    u_Hor:    WORD;   //если ходит, то это вертикальный номер ячейки
    u_Vert:   WORD;   //а это её горизонтальный
    u_Answer: WORD;   //ответ на сделанный ход, константы на AW_***
    c_Text:   array[0..245] of char; //если чат, то тут сообщение
  end; //общий размер структуры $100 байт.

Её нужно переслать использую средства WinSock, ну и потом ессно получить, пользуясь теме же средствами.
Пытался делать так:
Код

  ZeroMemory(@sendPacket, SizeOf(sendPacket));
  sendPacket.u_Magic:= $0D;
  sendPacket.u_Type:= PT_HELO;
  send(clientSocket, sendPacket, SizeOf(sendPacket), 0);

Функция send возвращает _не_ INVALID_SOCKET. Т.е. данные ушли, но потом я пытаюсь читать так:
Код

recv(serverSocket, inPacket, PACKET_SIZE, 0);

Ну и там приходят всякая муть.
Почитал форум, вроде бы как из слов понял, что так делать нельзя.
Был совет пересылать частично, так вот частично это как ? кто может посоветовать алгоритм ?
Просто у  меня программа может быть либо сервером либо клиентом, и код для них(именно код обработки входящих пакетов) один.
И ещё, пишу используя не блокирующий режим сокетом, т.е. сообщения посылаются моему приложению, а он уже обрабатывает.
Кто что посоветует ?


--------------------
MaXL
PM MAIL   Вверх
MaXL
Дата 23.2.2008, 03:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Developer
**


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

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



Вопрос всё ещё актуален.


--------------------
MaXL
PM MAIL   Вверх
SneG0K
Дата 23.2.2008, 06:09 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Max Mara
***


Профиль
Группа: Завсегдатай
Сообщений: 1887
Регистрация: 1.12.2007
Где: Wis Dells

Репутация: 2
Всего: 54



Код

send(Sock, TPacket.u_Magic, sizeof(TPacket.u_Magic));


И так далее... береш элемент из структуры и отсылаеш его... Береш следующий и отсылаеш следующий и так далее...
PM WWW Skype   Вверх
MetalFan
Дата 23.2.2008, 14:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

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



SneG0K, а нафиг так? ошибка явно не в этом.

Добавлено через 2 минуты и 21 секунду
автор, чтобы нормально ответили, выложи тестовое приложение...
а то у тебя все на словах, а кода нет. 


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
vovksextra
Дата 23.2.2008, 15:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Должно все работать

не видно в каком режиме сокет работает. нужен полный код .
PM MAIL   Вверх
MaXL
Дата 23.2.2008, 16:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Developer
**


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

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



Всё, что касается сервера.
Вот функция, которая запускает сервер:
Код

//почти все переменные глобальные
function TPlayForm.StartServer: boolean;
var
  errId: DWORD;
begin
  Result:= false;
  serverSocket:= socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
  if serverSocket = INVALID_SOCKET then
    begin
      MessageBoxExA(Handle, 'Couldn`t create socket', 'Error', MB_ICONERROR, 0);
      exit;
    end;

  ZeroMemory(@servAddr, SizeOf(servAddr));
  servAddr.sin_port:= htons(serverPort);
  servAddr.sin_family:= AF_INET;
  servAddr.sin_addr.S_addr:= INADDR_ANY;

  if bind(serverSocket, @servAddr, SizeOf(servAddr)) = SOCKET_ERROR then
    begin
      MessageBoxExA(Handle, PChar('Couldn`t bind port ' + IntToStr(serverPort)),
        'Error', MB_ICONERROR, 0);
      exit;
    end;

  if listen(serverSocket, 1) = SOCKET_ERROR then
    begin
      MessageBoxExA(Handle, PChar('Couldn`t listen on port ' + IntToStr(serverPort)),
        'Error', MB_ICONERROR, 0);
      exit;
    end;

  WSAAsyncSelect(serverSocket, PlayForm.Handle, WM_NETWORK,
    FD_ACCEPT or FD_WRITE or FD_READ or FD_CLOSE);
  Result:= true;
end;

Вот процедура, которая выполняется, когда окно приходит сообщение WM_NETWORK:
Код

procedure TPlayForm.DispatchSocketEvent(var Msg: TMessage);
var
  inPacket: TPacket;
  addrLen: integer;
begin
  ZeroMemory(@inPacket, PACKET_SIZE);
  case WSAGetSelectEvent(Msg.LParam) of
    FD_ACCEPT:
      begin
        clientSocket:= TSocket(Msg.WParam);
        addrLen:= SizeOf(clientAddr);
        clientSocket:= Accept(clientSocket, clientAddr, addrLen);
      end;
    FD_WRITE:
      begin
      end;
    FD_READ:
      begin
        recv(serverSocket, inPacket, PACKET_SIZE, 0);
        DispatchPacket(d);
      end;
    FD_CLOSE:
      begin
      end;      
  end;
end;

Вот код процедуры DispatchPacket:
Код

procedure TPlayForm.DispatchPacket(Packet: TPacket);
var
  newPacket: TPacket;
begin
  if Packet.u_Magic <> $0D then exit;
  ZeroMemory(@newPacket, SizeOf(newPacket));
  newPacket.u_Magic:= $0D;
  //обработка пакета
  case Packet.u_Type of
    PT_HELO:
      begin
        playing:= true;
        if serverStarted then
          begin
            newPacket.u_Type:= PT_HELO;
            send(clientSocket, newPacket, SizeOf(newPacket), 0);
          end;  
      end;
    PT_CHAT:
      begin
        ChatMemo.Lines.Add(Packet.c_Text);
      end;
    PT_PING:
      begin
        newPacket.u_Type:= PT_PONG;
        send(clientSocket, newPacket, SizeOf(newPacket), 0);
      end;
    PT_PONG:
      begin
      end;
   //ну и тут обработчик для этих констант, пока всё пусто 
   //...
  end;
end;     

Теперь всё, что касается по поводу клиента.
Подключение к серверу:
Код

function TPlayForm.ConnectToServ: boolean;
begin
  Result:= false;
  ZeroMemory(@servAddr, sizeof(servAddr));
  clientSocket:= socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

  servAddr.sin_family:= AF_INET;
  servAddr.sin_port:= htons(serverPort);
  servAddr.sin_addr.S_addr:= inet_addr(PChar(serverIP));

  WSAAsyncSelect(clientSocket, Handle, WM_NETWORK,
    FD_ACCEPT or FD_WRITE or FD_READ or FD_CLOSE);//т.е. используем одну процедуру и для сервера и для клиента.

  connect(clientSocket, @servAddr, sizeof(servAddr));
  Result:= true;
end;

А вот код, с помощью которого я посылаю:
Код

var
  sendPacket: TPacket;
  msg: String;
begin
  //...
  ZeroMemory(@sendpacket, SizeOf(sendPacket));
  sendPacket.u_Magic:= $0D;
  sendPacket.u_Type:= PT_CHAT;
  msg:= MessageEdit.Text;
  if Length(msg) = 0 then exit;
  lstrcpy(sendPacket.c_Text, PChar(msg));
  if send(clientSocket, sendPacket, SizeOf(sendPacket), 0) = SOCKET_ERROR then
    //...
  //...
end;

Ну вот так..=)


--------------------
MaXL
PM MAIL   Вверх
MetalFan
Дата 23.2.2008, 20:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

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



Цитата(MaXL @  28.1.2008,  15:41 Найти цитируемый пост)
  TPacket = record
    u_Magic:  WORD;   //магическое поле, должно быть равно в $0D
    u_Type:   WORD;   //тип пакета, константы начинаются с PT_***
    u_Hor:    WORD;   //если ходит, то это вертикальный номер ячейки
    u_Vert:   WORD;   //а это её горизонтальный
    u_Answer: WORD;   //ответ на сделанный ход, константы на AW_***
    c_Text:   array[0..245] of char; //если чат, то тут сообщение
  end; //общий размер структуры $100 байт.

забавно...
последний элемент записи 246 байт... то каким образом вся структура 100 байт??

Добавлено через 1 минуту и 6 секунд
и еще, автор, если ты не можешь выложить пример проекта, то кури его сам...
те куски кода, что ты привел, не воссоздают полную картину.


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
MaXL
Дата 24.2.2008, 04:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Developer
**


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

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



MetalFan, да, правильно последний массив 246, потом ещё пять вордов, и получается 256, а в шестнадцатиричной 0x100(или $100).
Вроде бы именно эти куски кода за всё и отвечают, ну да ладно вот выкладываю полностью этот проджект, пока там всё криво, но это только пока, но надеюсь, что разобраться будет не сложно.

Присоединённый файл ( Кол-во скачиваний: 15 )
Присоединённый файл  seawar.rar 36,72 Kb


--------------------
MaXL
PM MAIL   Вверх
MetalFan
Дата 24.2.2008, 11:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

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



MaXL, а, сорь, не заметил знак бакса %)
гляну на досуге проект)


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
dumb
Дата 24.2.2008, 13:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 5
Всего: 158



особо не всматривался, но налицо самая распространенная ошибка - "пакетный tcp".
tcp - поточный протокол. для простоты, представь, что recv вычитывает данные порциями от 1 до 3 байт(и неважно, что send послал сразу всю структуру). будет твоя программа работать?
PM MAIL   Вверх
MetalFan
Дата 24.2.2008, 14:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

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



ага, ну так ясно...
ты в момент получения события FD_READ пытаешься читать данные из сокета сервера...
замени
Код

procedure TPlayForm.DispatchSocketEvent(var Msg: TMessage);
var
  inPacket: TPacket;
  addrLen: integer;
  lSz: Integer;
begin
...
    FD_READ:
      begin
        lSz := recv(TSocket(Msg.wParam), inPacket, PACKET_SIZE, 0); //было ServerSocket. можно или так или ClientSocket
        DispatchPacket(inPacket);
      end;
...
end;

и все, сообщения приходят норм

Добавлено через 42 секунды
ах да, lSz ввел для контроля за размером принятых данных


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
MaXL
Дата 24.2.2008, 15:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Developer
**


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

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



dumb, спасибо.
MetalFan, спасибо. +1  smile 

Это сообщение отредактировал(а) MaXL - 24.2.2008, 15:02


--------------------
MaXL
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Сети"
Snowy
Poseidon
MetalFan

Запрещено:

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

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

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи

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

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


 




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


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

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