• Dennis I. Komarov © (20.10.10 16:39) [0]
    Покажите (кому не жалко) грамотный код работы с TUDPSocket
  • Сергей М. © (21.10.10 09:21) [1]
    Ты скажи что тебе конкретно не понятно или какие проблемы возникли при использовании этого класса ..
  • Dennis I. Komarov © (21.10.10 11:38) [2]

    > Сергей М. ©   (21.10.10 09:21) [1]


    Да собственно проблем не возникало :)

    Нуна чтоб экземпляры приложения в сети знали друг о друге

    т.е. раз в n-мин шлем датаграмму BroadCast. Если софтина поймала ее, значит добавили (обновили) в список, если последний пакет приходил раньше чем 10*n - удаляем из списка как усопшего...

    Вообщем все тривиально, но велосипед писать не охота, т.к. UDP ни разу не юзал.
  • Сергей М. © (21.10.10 12:13) [3]

    > Dennis I. Komarov ©   (21.10.10 11:38) [2]


    Я бы не рекомендовал пользовать для этой цели TUDPSocket.
    Гораздо удобней, надежней и интуитивно понятней работать с TUDPBlockSocket в составе сторонней библиотеки Synapse.
  • Dennis I. Komarov © (21.10.10 12:34) [4]
    Да, шарился по помойке - кругом полно WinSock. TUDPSocket никто не любит. Synapse тяжелая? Для такой мелкой задачи не охота тащить что-то. Чую что путь лежит к WinSock...
  • Slym © (21.10.10 12:49) [5]
    unit Unit1;

    interface

    uses
     Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
     Dialogs, ExtCtrls, Sockets, StdCtrls, IdBaseComponent, IdComponent,
     IdUDPBase, IdUDPServer,Idglobal,IdSocketHandle;

    type
     TForm1 = class(TForm)
       ListBox1: TListBox;
       Timer1: TTimer;
       IdUDPServer1: TIdUDPServer;
       procedure Timer1Timer(Sender: TObject);
       procedure IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
         AData: TIdBytes; ABinding: TIdSocketHandle);
       procedure FormShow(Sender: TObject);
     private
       { Private declarations }
     public
       { Public declarations }
     end;

    var
     Form1: TForm1;

    implementation

    {$R *.dfm}
    const
     PS1='Ya tut';
     PS2='Gde vse';
     N=4;

    procedure TForm1.FormShow(Sender: TObject);
    begin
     IdUDPServer1.Broadcast(PS2,IdUDPServer1.DefaultPort);
    end;

    procedure TForm1.Timer1Timer(Sender: TObject);
    var i,t:integer;
    begin
     for i:=ListBox1.Items.Count-1 downto 0 do
     begin
       t:=StrToIntDef(ListBox1.Items.ValueFromIndex[i],0);
       dec(t,Timer1.Interval div 1000);
       if t<=0 then
         ListBox1.Items.Delete(i)
       else
         ListBox1.Items.ValueFromIndex[i]:=IntToStr(t);
     end;
     IdUDPServer1.Broadcast(PS1,IdUDPServer1.DefaultPort);
    end;

    procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
     AData: TIdBytes; ABinding: TIdSocketHandle);
    var SData:string;
    begin
     SetString(SData,PChar(@AData[0]),Length(AData));
     if SData=PS1 then
       ListBox1.Items.Values[ABinding.PeerIP]:=IntToStr(Timer1.Interval*N div 1000);
     if SData=PS2 then
     begin
       ListBox1.Items.Values[ABinding.PeerIP]:=IntToStr(Timer1.Interval*N div 1000);
       IdUDPServer1.Send(ABinding.PeerIP,IdUDPServer1.DefaultPort,PS1);
     end;
    end;

    end.

  • Dennis I. Komarov © (21.10.10 12:56) [6]

    > Slym ©   (21.10.10 12:49) [5]

    Индейцев религия не позволяет :) Только генофонд и API...
  • Dennis I. Komarov © (21.10.10 13:59) [7]
    Поправьте если не прав, но мысля в сторону:

    1. Создаем поток-нить.
    2. Инициализируем сокет а-ля WSAStartUp
    3. Пока поток жив пытаемся читать
    3.1 Если что-то смогли прочитать сообщаем основному о чуде
    4. Выйдя из "пока" чистим а-ля WSACleanUp
  • Slym © (21.10.10 14:26) [8]
    Dennis I. Komarov ©   (21.10.10 13:59) [7]
    да...
    вот консолька, консольке доп поток не нужен потому его и нет...
    program UDP;

    {$APPTYPE CONSOLE}

    uses
     SysUtils,WinSock,Windows;

    resourcestring
     sWindowsSocketError = 'Windows socket error: %s (%d), on API ''%s''';
    procedure RaiseSocketError(const Op: string);
    var Error:integer;
    begin
     Error := WSAGetLastError;
     raise Exception.CreateResFmt(@sWindowsSocketError, [SysErrorMessage(Error), Error, Op]);
    end;

    procedure WriteLnEx(const Text:string;color:byte=FOREGROUND_GREEN);
    var
     hStdOut:THandle;
     BufferInfo:TConsoleScreenBufferInfo;
     Result:DWORD;
     Attrs: array of word;
     i:integer;
    begin
     hStdOut:=GetStdHandle(STD_OUTPUT_HANDLE);
     Win32Check(GetConsoleScreenBufferInfo(hStdOut,BufferInfo));
     SetLength(Attrs, Length(Text));
     for I:=low(Attrs) to high(Attrs) do Attrs[I]:=color;
     Writeln(Text);
     Win32Check(WriteConsoleOutputAttribute(hStdOut, @Attrs[0], Length(Text), BufferInfo.dwCursorPosition, Result));
    end;

    procedure RecvLoop(sock: TSocket);
    const BufSize:integer=$ffff;
    var
     buf: PChar;
     from: TSockAddr;
     Size,fromlen: integer;
    begin
     fromlen:=SizeOf(TSockAddr);
     GetMem(buf, bufsize);
     try
       while true do
       begin
         Size:=recvfrom(sock, buf^, BufSize, 0, from, fromlen);
         if Size<> SOCKET_ERROR then
         begin
           WriteLnEx(inet_ntoa(from.sin_addr)+':'+inttostr(ntohs(from.sin_port))+' write:');
           WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), buf, dword(Size), dword(Size), nil);
         end else RaiseSocketError('recvfrom');
       end;
     finally
       FreeMem(buf);
     end;
    end;

    var
     WSAData: TWSAData;
     sock:TSocket;
     addr:TSockAddrIn;
    begin
     WSAStartup(MakeWord(1, 0), WSAData);
     sock:=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
     addr.sin_family:= AF_INET;
     addr.sin_addr.S_addr:= htonl(INADDR_ANY);
     addr.sin_port:= htons(3052);
     WriteLnEx('Listening '+inttostr(ntohs(addr.sin_port))+' port...',FOREGROUND_RED);
     bind(sock, addr, SizeOf(addr));
     RecvLoop(sock);
     closesocket(sock);
     WSACleanup;
    end.

  • Dennis I. Komarov © (21.10.10 15:04) [9]
    Мерси, сейчас подшаманю и ...
  • Сергей М. © (21.10.10 21:09) [10]

    > Synapse тяжелая?


    imho, в сравнении с индейским творчеством - легкое , довольно изящное перышко против большого тяжелого кривоватого бревна
  • Dennis I. Komarov © (18.11.10 13:16) [11]
    отправляем:
    в Create
    WSAStartup($101,Init);
    Sock:=Socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
    SockOpt:=TRUE;
    SetSockOpt(Sock,SOL_SOCKET,SO_BROADCAST,PChar(@SockOpt),SizeOf(SockOpt));
    Target.sin_port:=htons(5353);
    Target.sin_addr.S_addr:=INADDR_BROADCAST;
    Target.sa_family:=AF_INET;


    Таймер
    Data:='Any string';
    SendTo(Sock,Data,Length(Data),0,Target,SizeOf(Target));


    В Close
    CloseSocket(Sock);
    WSACleanup;



    Почему приходит не то?
    З.Ы. даже код [8] принимает не то
  • Сергей М. © (18.11.10 20:01) [12]

    > Почему приходит не то?


    Потому что отправил "не то".


    > SendTo(Sock,Data,Length(Data)


    Судя по оператору-фигуранту "Length", Data у тебя есть либо ларжстринг либо динам.массив. А раз так, то отправил ты партнеру не cfvb данные, а указательную галиматью
  • Slym © (19.11.10 10:24) [13]
    Dennis I. Komarov ©   (18.11.10 13:16) [11]
    SendTo(Sock,Data,Length(Data),0,Target,SizeOf(Target));

    навскидку
    SendTo(Sock,PChar(Data)^,Length(Data),0,Target,SizeOf(Target));

  • Dennis I. Komarov © (19.11.10 12:14) [14]
    Да, спасибо. Я уже разглядел. Черт не туда глянул просто.
Есть новые Нет новых   [134436   +25][b:0][p:0.003]