Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.04.16;
Скачать: CL | DM;

Вниз

проблема с сообщениями в WinSock   Найти похожие ветки 

 
syned ©   (2006-01-03 17:41) [0]

Добрый вечер!
Я пишу клиент-серверную прогу с помощью асинхронных сокетов.

объявляю константы
const
 WM_SOCKET_EVENT = WM_USER + 2; // константа сообщения
 MAXLEN = 8192; // размер буфера

Создаю сокет и перевожу в ассинхронный режим:

 aSock := socket(AF_INET,SOCK_DGRAM,0);
 // заполнение addr
 addr.sin_family := AF_INET;
 addr.sin_port := htons(55566);
 addr.sin_addr.S_addr := inet_addr("127.0.0.1");
 FillChar(addr.sin_zero,sizeof(addr.sin_zero),0);
 // привязываем слухающий сервер, и переводим в режим ожидания
 bind(aSock,addr,sizeOf(addr));
 listen(aSock,SOMAXCONN);
 // асинхронный селект, возникает событие WM_SOCKET_EVENT
 WSAAsyncSelect(aSock,Handle,WM_SOCKET_EVENT,FD_READ);
 Self.Caption := "Сервер запущен!";

Отправляю широковещательное сообщение:

 ListBox1.Clear;
 s := socket(AF_INET,SOCK_DGRAM,0);
 // Отправляем опрос серваков
 saddr.sin_family := AF_INET;
 saddr.sin_port := htons(55566);
 saddr.sin_addr.S_addr := inet_addr("192.168.1.255");
 FillChar(addr.sin_zero,sizeof(addr.sin_zero),0);

 ps[0] := $FF;

 len := sizeOf(TSockAddr);
 t := SendTo(s,ps,1,0,saddr,len);
 if t <> 1 then
   begin
     ShowMessage("Ошибка посылки");
     Exit;
   end
 else
   ListBox1.Items.Add("Послан опрос! Список запущенных серверов");

для получения таких же программ в сети...

ну и самое главное, обработка сообщения...

procedure TForm1.WMSocketEvent(var msg : TMessage);
var
 sock : TSocket;
 sockError : integer;
 sockAddrr : TSockAddr;
 len, lenAddr : integer;
 ps : array [0..MAXLEN-1] of byte;
 res : integer;
 s, slocal, sremote : string;
 bufComp : Cardinal;
 p : PHostEnt;
 i, t : integer;
 str : string;
begin
 len := 8192;
 lenAddr := 16;
 bufComp := 256;
 sock := TSocket(msg.WParam);
 sockError := WSAGetSelectError(msg.LParam);
 if sockError <> 0 then
   begin
     ShowMessage("Ошибка!");
     closesocket(sock);
     Exit;
   end;
 if WSAGetSelectEvent(msg.LParam) = FD_READ then
   begin
     res := recvfrom(sock,ps,len,0,sockAddrr,lenAddr);
     if res = -1 then
       ListBox1.Items.Add("Ошибка получения данных")
     else
       begin
         // получаем локальный IP
         SetLength(s,bufComp);
         GetComputerName(PAnsiChar(s),bufComp);
         p := gethostbyname(PAnsiChar(s));
         slocal := inet_ntoa(PInAddr(p.h_addr_list^)^);
         sremote := inet_ntoa(sockAddrr.sin_addr);
         if slocal <> sremote then // если не с локального адреса
           begin
             case ps[0] of
               // пришли данные
               0 : begin
                     str := "";
                     for i := 1 to len-1 do
                       str := str + Chr(ps[i]);
                     ListBox2.Items.Add("Получены данные от "+inet_ntoa(SockAddrr.sin_addr)+": "+str);
                   end;
               // пришел опрос
               $FF : begin
                       ps[0] := $FE;
                       t := SendTo(sock,ps,1,0,sockAddrr,lenAddr);
                       if t <> 1 then
                         ListBox2.Items.Add("Ошибка послания IP")
                       else
                         ListBox2.Items.Add("IP успешно послан");
                     end;
                // Пришло подтверждение о доставке
               $FA : ListBox2.Items.Add("Данные для " + inet_ntoa(SockAddrr.sin_addr) + " успешно доставлены");
               // Пришел IP
               $FE : ListBox1.Items.Add(inet_ntoa(SockAddrr.sin_addr));
             end;
           end;
       end;
   end;
end;

и у меня возникает проблемма, отсылаю широковещательную посылку, данные приходят, IP посылается и все второй раз сообщение FD_READ никогда не приходит.

Должно работать так программа отсылает широковещательную посылку а другие в ответ на этот запрос высылают ответ и в листбокс заносятся все IP программ запущенных в сети...

Подскажите где ошибка, а то я не могу разобратся...


 
Piter ©   (2006-01-03 18:07) [1]

syned ©   (03.01.06 17:41)
и у меня возникает проблемма, отсылаю широковещательную посылку


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


 
FrykT ©   (2006-01-03 18:11) [2]

А что это за хреновина в procedure WMSocketEvent напихана? Поставь брекпоинт в WMSocketEvent после BEGIN и смотри, возникает ли событие, далее по обстоятельствам


 
FrykT ©   (2006-01-03 18:14) [3]

да, кстати. Перед отправкой сообщения вот это надо.
SetSockOpt(sock,SOL_SOCKET,SO_BROADCAST,PChar(@SockOpt),SizeOf(SockOpt));


 
syned ©   (2006-01-03 18:22) [4]

Piter ©   (03.01.06 18:07) [1]

syned ©   (03.01.06 17:41)
и у меня возникает проблемма, отсылаю широковещательную посылку

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

Так я и посылаю по UDP

To FrykT
я смотрел в дебаггере, широковещательная приходит, и больше сообщение FD_READ не возникает


 
Piter ©   (2006-01-03 18:23) [5]

а перед этим еще неплохо было бы выставить работу по протоколу UDP:

... := Socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);


 
Piter ©   (2006-01-03 18:24) [6]

syned ©   (03.01.06 18:22) [4]
Так я и посылаю по UDP


ага, посылаешь ты по UDP, только вот Windows об этом ничего не знает. А так все путем.


 
syned ©   (2006-01-03 18:26) [7]

ок, спасибо


 
syned ©   (2006-01-03 18:34) [8]

А еще подскажите какое значение должен иметь параметр SockOpt
для функции
SetSockOpt(sock,SOL_SOCKET,SO_BROADCAST,PChar(@SockOpt),SizeOf(SockOpt));


 
syned ©   (2006-01-03 18:34) [9]

для разрешения широковещательной посылки


 
syned ©   (2006-01-03 18:41) [10]

Но всеравно решение не пришло еще раз повторяю, широковещательная рассылка приходит, но после этого куска кода сообщение FD_READ должно произойти еще раз так как посылаются данные:
              $FF : begin
                      ps[0] := $FE;
                      t := SendTo(sock,ps,1,0,sockAddrr,lenAddr);
                      if t <> 1 then
                        ListBox2.Items.Add("Ошибка послания IP")
                      else
                        ListBox2.Items.Add("IP успешно послан");
                    end;


 
FrykT ©   (2006-01-03 18:53) [11]

Посмотри что в t приходит в отладчике. Если  -1, то  это SOCKET_ERROR


 
syned ©   (2006-01-03 18:56) [12]

t = 1, данные посылаются...


 
syned ©   (2006-01-03 18:57) [13]

я рехнусь с этими сокетами... :(


 
syned ©   (2006-01-03 18:59) [14]

ладно, всем спасибо, я домой... буду мучатся завтра...


 
FrykT ©   (2006-01-03 19:00) [15]

Вот ПРИКОЛ твой :
addr.sin_addr.S_addr := inet_addr("127.0.0.1");

надо вот так:
addr.sin_addr.S_addr := htonl(INADDR_ANY);


 
FrykT ©   (2006-01-03 19:07) [16]

И сделай  процедуру отправки нормальную:

function UdpSend(AHost: string; APort: Integer; AStr: string): boolean;
var
 buf: array[0..7990] of char;
 Sock: TSocket;
 addr: TSockAddr;
 SockOPT: BOOL;
begin
 Result := false;
 Sock := Socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
 if Sock = INVALID_SOCKET then
   exit;
 addr.sin_family := AF_INET;
 addr.sin_port := htons(APort);
 addr.sin_addr.S_addr := Inet_Addr(Pchar(AHost));
 FillChar(addr.sin_zero,sizeof(addr.sin_zero),0);
 SockOPT := true;
 SetSockOpt(sock,SOL_SOCKET,SO_BROADCAST,PChar(@SockOpt),SizeOf(SockOpt));
 FillChar(buf, sizeof(buf), #0);
 Buf := AStr;
 SendTo(Sock, buf, sizeof(buf), 0, addr, sizeof(addr));
 Result := true;
end;


 
FrykT ©   (2006-01-03 19:09) [17]

closeSocket(Sock) забыл.



Страницы: 1 вся ветка

Текущий архив: 2006.04.16;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.041 c
2-1143811886
Svetlana_K
2006-03-31 17:31
2006.04.16
Закрыть программу через определённое время?


2-1144197538
Bratskiy
2006-04-05 04:38
2006.04.16
Аналог Application.ProcessMessages


2-1144076653
User_OKA
2006-04-03 19:04
2006.04.16
Последовательность чисел


2-1143534311
Sw
2006-03-28 12:25
2006.04.16
Путь к БД


3-1140417228
Os
2006-02-20 09:33
2006.04.16
Удаление дублирующих записей