Форум: "Сети";
Текущий архив: 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