Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2006.04.16;
Скачать: [xml.tar.bz2];

Вниз

проблема с сообщениями в 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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.043 c
4-1138498463
einstein
2006-01-29 04:34
2006.04.16
Функция shellexecute()


5-1129211071
Saraseko Maksim
2005-10-13 17:44
2006.04.16
Наследовать TCollectionEditor


15-1143011380
Бугага
2006-03-22 10:09
2006.04.16
Все голы сборной России по хоккею на Олимпиаде


8-1131566457
[dvs]digiman
2005-11-09 23:00
2006.04.16
Aero Glass эффект


1-1141989695
Александр Б.
2006-03-10 14:21
2006.04.16
Интерфейс, и потоки





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский