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

Вниз

Не могу передать данные посредством idUDPClient/idUDPServer   Найти похожие ветки 

 
Nike   (2005-10-16 09:03) [0]

Здравствуйте! Пишу чат для локальной сети. Использую Indy-йские UDP-клиент и Udp-сервер. При отправке широковещательного сообщения возникает следующая проблема: если я отправляю данные методом idUdpClient.Send(Adata:string), то мне удается получить эту строку сервером в событии idUDPServer.onUDPRead, т.е. с доставкой строк проблем не возникает.
Но если я отправляю данные (к примеру, типа byte) методом idUdpClient.SendBuffer(var ABuffer, const ABytesCount: integer), то при получении сервером данных (событие onUDPRead) я получаю "неверные" данные в потоке AData: Stream.
Привожу код для "неверного" случая:


... var F: byte;
...

//Отправка данных
procedure TMainFrm.Button1Click(Sender: TObject);
var buf: TMemoryStream;
   s: string;
begin
buf:=Tmemorystream.Create;
F:=6;
Buf.WriteBuffer(F,1);
Buf.Position:=0;
IdUdpClient1.SendBuffer(Buf,Buf.size);
s:=IdUdpClient1.ReceiveString;
If s="" then ShowMessage("No answer")
else ShowMessage(s);

Buf.Free;
end;

//Прием сообщения
procedure TMainFrm.IdUDPServer1UDPRead(Sender: TObject; AData: TStream;  ABinding: TIdSocketHandle);
var
 buf: TMemoryStream;
 z: byte;
 s: string;
begin
 Buf:=TMemoryStream.Create;
 Buf.CopyFrom(Adata,Adata.Size);
 Buf.Seek(0,0);
 Buf.Read(z,1);

 If z=6 then ShowMessage("Ok12");
 s:="I got";
 With Abinding do
  SendTo(PeerIP,PeerPort,s[1],Length(s));
 Buf.Free;

end;


Может кто-нибудь мне объяснит в чем проблема?


 
Nike   (2005-10-18 09:03) [1]

Конечно, можно и в строку записать данные любого типа, но тогда придется сначала конвертировать данные в строку при отправке, отправлять методом Send(полученная строка), и производить обратную конвертацию (из строки в свой тип данных) при приеме. Мне такой подход как-то не по душе :).
Все же почему не работает метод SendBuffer? У меня руки кривые или это глюк INDY?


 
kami ©   (2005-10-18 14:41) [2]

Сейчас не стоит Indy, но попробую... Если в Индях в SendBuffer используется тоже нетипизированный буфер, то нужно :
IdUdpClient1.SendBuffer(Buf.Memory,Buf.size);
И необязательно тогда устанавливать Position в 0


 
Чапаев ©   (2005-10-18 15:21) [3]


> IdUdpClient1.SendBuffer(Buf,Buf.size);

Эхехе... А ты подумал, ЧТО ты таким образом отправляешь?


 
Чапаев ©   (2005-10-18 15:22) [4]


> У меня руки кривые или это глюк INDY?

Это не глюк Indy, а вот руки... Скорее не кривые, а неопытные. ;-)


 
megabyte-ceercop ©   (2005-12-21 13:51) [5]

Так что же Nike таким образом отправляет?


 
Digitman ©   (2005-12-22 11:12) [6]


> что же Nike таким образом отправляет?


он отправляет buf.size байт начиная с адреса переменной buf, в которой хранятся не данные, которыми управляет объект TMemoryStream и которые собственно и нужно передать, а адрес местонахождения в памяти этого объекта

IdUdpClient1.SendBuffer(Buf.Memory^,Buf.size);


 
Slym ©   (2005-12-22 12:15) [7]

var F:Byte;
begin
F:=6;
IdUdpClient1.SendBuffer(PChar(@F)^,sizeof(f));


 
tesseract ©   (2005-12-23 17:40) [8]


> PChar(@F)^

Зачем ? Можно и просто числа, и стуктуру, и статический массив передавать как нетипизированную переменную. С динамическими массивами сложнее.


 
Eraser ©   (2005-12-23 18:03) [9]


> Nike   (16.10.05 09:03)

При всём том, что тут уже сказали учти, что размер передаваемых данных не должен превышать максимального размера дэйтаграммы, иначе не видать тебе удачи.


 
FrykT ©   (2005-12-24 19:57) [10]

Передавайте всегда в виде строки в пакетах с фиксированным буфером. Продумайте протокол передачи, если данных больше, чем размер одного пакета. Возможно, Вам захочется сделать не на Инди, а на API.
Вот пример UDP сервера на АПИ:
перед закрытием сокета делайте WSAASynchSelect с последним параметром 0.
Событие сокета к окну привязывается с помощью сообщения, например
const WM_NETMESSAGE = WM_USER + 32;
ловится созданием процедуры типа procedure ProcNetMes(var m: TMessage); message WM_NETMESSAGE;
там тип сообщения извлекается из m.lParamLo , ошибка из m.lParamHi, сам сокет - m.wParam
function StartUDPSocket(h:hWnd; var S: Tsocket; var A: TSockAddr;
 Port: Integer): boolean;
begin
 Result := FALSE;
 S := socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
 if S = INVALID_SOCKET then
   exit;
 A.sin_family := AF_INET;
 A.sin_port := htons(Port);
 A.sin_addr.S_addr := htonl(INADDR_ANY);
 FillChar(A.sin_zero, sizeof(A.sin_zero), 0);
 if bind(S, A, sizeof(A)) = SOCKET_ERROR then
 begin
   closesocket(S);
   exit;
 end;
 if listen(S, SOMAXCONN) = SOCKET_ERROR then
 begin
   closesocket(S);
   exit;
 end;
 WSAAsyncSelect(S, h, WMNETMESSAGE, FD_READ);
 Result := true;
end;


 
FrykT ©   (2005-12-24 19:59) [11]

Сорьки за ошибки, на быструю руку накатал (=



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

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

Наверх




Память: 0.49 MB
Время: 0.048 c
6-1135720867
Гость13
2005-12-28 01:01
2006.04.09
Пишем почтовый ЧЕРВЬ на дельфи


1-1141628801
Leonid
2006-03-06 10:06
2006.04.09
Копирование директории с поддиректориями


4-1138094363
medvedenator
2006-01-24 12:19
2006.04.09
Помогите с реестром


15-1142573326
Геро
2006-03-17 08:28
2006.04.09
.NET — оболочка над Win32?


15-1142624192
TStas
2006-03-17 22:36
2006.04.09
КАк изменить свои детали