Текущий архив: 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.wParamfunction 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.47 MB
Время: 0.013 c