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

Вниз

idudpserver1   Найти похожие ветки 

 
ZDDR ©   (2004-05-11 00:09) [0]

почему после кода:

idudpserver1.Active:=false;
idudpserver1.DefaultPort:=strtoint("1005"); idudpserver1.Active:=true;
idudpserver1 перестает получать broadcast сообщения???  


 
Rouse_ ©   (2004-05-11 08:53) [1]

А ты проверь сначала, он вообще получает какие нибудь сообщения на 1005 порт? даже не броадкастом...


 
ZDDR ©   (2004-05-11 10:45) [2]

получает


 
ZDDR ©   (2004-05-11 10:48) [3]

все работает нормально сообщения принимаются по 1005 порту но стоит выполнить код:
idudpserver1.active:=false;
idudpserver1.defaultport:=strtoint("1005");
idudpserver1.active:=true;

перестают преходить сообщения


 
Rouse_ ©   (2004-05-11 12:42) [4]

Я имею ввиду после этого кода он получает обычные сообщения на этот порт? Не трогай пока броадкасты...


 
Zulus   (2004-05-11 20:57) [5]

У меня такой же вопрос. Необходимо в процессе работы программы менять UDP Port. Как это сделать??? Подскажите плиз.


 
Rouse_ ©   (2004-05-11 21:43) [6]

Так вот: даже если сделать ему Active False а потом True, даже без измения порта, наступает кирдык...

Вот для этого я и писал собственные реализации UDP, так как в Индийском - попросту немного запутался с ихней реализацией и не смог выяснить причины глюка... :(


 
Zulus   (2004-05-11 22:11) [7]

Уважаемый, Rouse_ ©, а Вы не могли бы поделиться своим опытом и помочь в решении момей проблемы. Очень надо...


 
Rouse_ ©   (2004-05-11 23:08) [8]

Ну вот как пример...
За проверками не следил, могут быть ошибки - но так проверил, вроде работает:

unit FWUDPSocket;

interface

uses
 Windows, Messages, Winsock, SysUtils, Classes, WSAErrors, Forms;

resourcestring
 ERR_ERROR   = "FWSocket error. ";
 ERR_CREATE  = "Can not initialize WSA. ";
 ERR_SOCKET  = "Can not create socket. ";
 ERR_SEND    = "Can not send data. ";
 ERR_BIND    = "Can not bind socket. ";
 ERR_SSO     = "Can not set socket option. ";

const
 HST_BROADCAST: String = "255.255.255.255";
 MAX_UDP_SIZE: Integer = 8192;
 WM_ASYNC = WM_USER + 1;

type

 TFWSocketErrorEvent = procedure(Sender: TObject; Error: String) of object;
 TFWSocketOnReadStringEvent = procedure(Sender: TObject; FromIP, Data: String) of object;
 TFWSocketOnReadStreamEvent = procedure(Sender: TObject; FromIP: String; Data: TMemoryStream) of object;

 TFWUDPSocket = class(TComponent)
 private
   FHandle: HWND;
   FServer, FClient: TSocket;
   FActive: Boolean;
   FWSAData: TWSAData;
   FSockAddr: TSockAddrIn;
   FOnError: TFWSocketErrorEvent;
   FOnReadString: TFWSocketOnReadStringEvent;
   FOnReadStream: TFWSocketOnReadStreamEvent;
   FPort: Integer;
   FWarning: String;
   function GetActive: Boolean;
   procedure SetActive(const Value: Boolean);
   procedure SetPort(const Value: Integer);
 protected
   procedure SockWND(var AMsg: TMessage); message WM_ASYNC;
   procedure Error(const Value: String);
   function Initialize(var FSocket: TSocket; const Host: String; const Port: Integer; Server: Boolean = False): Boolean;
   procedure DeInitialize(Server: Boolean = False);
   function GetIp: String;
 public
   procedure Broadcast(const Port: Integer; Data: String);
   constructor Create(AOwner: TComponent); override;
   destructor Destroy; override;
   procedure AfterConstruction; override;
   procedure Send(const Host: String; Port: Integer; Data: String); overload;
   procedure Send(const Host: String; Port: Integer; Data: TMemoryStream); overload;
 published
   property Port: Integer read FPort write SetPort;
   property Active: Boolean read GetActive write SetActive default False;
   property OnError: TFWSocketErrorEvent read FOnError write FOnError;
   property OnReadString: TFWSocketOnReadStringEvent read FOnReadString write FOnReadString;
   property OnReadStream: TFWSocketOnReadStreamEvent read FOnReadStream write FOnReadStream;
 end;

procedure Register;


 
Rouse_ ©   (2004-05-11 23:09) [9]

implementation

procedure Register;
begin
 RegisterComponents("Fangorn Wizards Lab", [TFWUDPSocket]);
end;

{ TFWUDPSocket }

procedure TFWUDPSocket.AfterConstruction;
begin
 inherited;
 if FWarning <> "" then
   if Assigned(FOnError) then
    FOnError(Self, FWarning);
end;

procedure TFWUDPSocket.Broadcast(const Port: Integer; Data: String);
var
 Result: Integer;
begin

 try

   if not Initialize(FClient, HST_BROADCAST, Port) then Exit;

   Result := SendTo(FClient, Data[1], Length(Data), 0, FSockAddr, SizeOf(FSockAddr));

   if Result = SOCKET_ERROR then
     Error(ERR_SEND + WSAErrorToString(WSAGetLastError));

 finally

   DeInitialize;

   if WSAGetLastError <> 0 then Error(WSAErrorToString(WSAGetLastError));

 end;

end;

constructor TFWUDPSocket.Create(AOwner: TComponent);
begin
 inherited Create(AOwner);
 FActive := False;
 FPort := 6767;
 FClient := 0;
 FServer := 0;
 if not (csDesigning in ComponentState) then
     FHandle := AllocateHWnd(SockWND);
end;

procedure TFWUDPSocket.DeInitialize(Server: Boolean = False);
begin

 if Server then
 begin

   if FServer <> 0 then
   begin

     WSAAsyncSelect(FServer, FHandle, 0, 0);

     closesocket(FServer);
     FServer := 0;

     WSACleanup;

   end;

 end
 else

   if FClient <> 0 then
   begin

     closesocket(FClient);
     FClient := 0;

     WSACleanup;

   end;

end;

destructor TFWUDPSocket.Destroy;
begin
 DeInitialize;
 DeInitialize(True);
 DeallocateHWnd(FHandle);
 inherited;
end;

procedure TFWUDPSocket.Error(const Value: String);
begin
 if Assigned(FOnError) then
  FOnError(Self, ERR_ERROR + Value)
 else
   FWarning := ERR_ERROR + Value;
end;


 
Rouse_ ©   (2004-05-11 23:09) [10]

function TFWUDPSocket.GetActive: Boolean;
begin
 if (csDesigning in ComponentState) then
   Result := FActive
 else
 begin
   Result := False;
   if (FHandle <> 0) and
      (FServer <> 0) and
      FActive
     then
       Result := True;
 end;
end;

function TFWUDPSocket.GetIp: String;
var
 WSAData: TWSAData;
 HostEnt: PHostEnt;
 Name: array [0..$FF] of Char;
begin
 WSAStartup($0101, WSAData);
 GetHostName(Name, $FF);
 HostEnt := GetHostByName(Name);
 if (HostEnt.h_addr_list^ <> nil) then
   Result := inet_ntoa(PInAddr(HostEnt.h_addr_list^)^);
 WSACleanup;
end;

function TFWUDPSocket.Initialize(var FSocket: TSocket; const Host: String;
 const Port: Integer; Server: Boolean = False): Boolean;
var
 Option: BOOL;
 SrvHost: String;
 Err: Integer;
begin

 Result := False;

 try

   Err := WSAStartup($0101, FWSAData);
   if Err <> 0 then
   begin
     Error(ERR_CREATE + WSAErrorToString(WSAGetLastError));
     Exit;
   end;

   FSocket := socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

   if FSocket = INVALID_SOCKET then
   begin
     Error(ERR_SOCKET + WSAErrorToString(WSAGetLastError));
     Exit;
   end;

   Option := True;

   with FSockAddr do
   begin

     if Host = HST_BROADCAST then
     begin

       if Server then
       begin
         SrvHost := GetIp;
         sin_addr.S_addr := inet_addr(PChar(SrvHost));
       end
       else
         sin_addr.S_addr := INADDR_BROADCAST;

       Err := SetSockOpt(FSocket, SOL_SOCKET, SO_BROADCAST, PChar(@Option), SizeOf(Option));
       if Err = SOCKET_ERROR then
       begin
         Error(ERR_SSO + WSAErrorToString(WSAGetLastError));
         Exit;
       end;

     end
     else
       sin_addr.S_addr := inet_addr(PChar(Host));

     sin_port := htons(Port);
     sin_family := AF_INET;
   end;

   if Server then
   begin

     Err := bind(FSocket, FSockAddr, SizeOf(FSockAddr));
     if Err = SOCKET_ERROR then
     begin
       Error(ERR_BIND + WSAErrorToString(WSAGetLastError));
       Exit;
     end;

   end;

   WSASetLastError(0);

   Result := True;

 except

   Error(WSAErrorToString(WSAGetLastError));

 end;

end;


 
Rouse_ ©   (2004-05-11 23:09) [11]

procedure TFWUDPSocket.Send(const Host: String; Port: Integer;
 Data: String);
var
 Result: Integer;
begin

 try

   if not Initialize(FClient, Host, Port) then Exit;

   Result := SendTo(FClient, Data[1], Length(Data), 0, FSockAddr, SizeOf(FSockAddr));

   if Result = SOCKET_ERROR then
     Error(ERR_SEND + WSAErrorToString(WSAGetLastError));

 finally

   DeInitialize;

   if WSAGetLastError <> 0 then Error(WSAErrorToString(WSAGetLastError));

 end;

end;

procedure TFWUDPSocket.Send(const Host: String; Port: Integer;
 Data: TMemoryStream);
var
 Buffer: array of Char;
 Result: Integer;
begin

 try

   if not Initialize(FClient, Host, Port) then Exit;

   SetLength(Buffer, Data.Size);
   Data.Position := 0;
   Data.ReadBuffer(Buffer[0], Data.Size);

   Result := SendTo(FClient, Buffer[0], Data.Size, 0, FSockAddr, SizeOf(FSockAddr));

   if Result = SOCKET_ERROR then
     Error(ERR_SEND + WSAErrorToString(WSAGetLastError));

 finally

   SetLength(Buffer, 0);
   DeInitialize;

   if WSAGetLastError <> 0 then Error(WSAErrorToString(WSAGetLastError));

 end;

end;


 
Rouse_ ©   (2004-05-11 23:10) [12]

procedure TFWUDPSocket.SetActive(const Value: Boolean);
var
 Err: Integer;
begin

 if FActive = Value then
   Exit
 else
   FActive := Value;

 if (csDesigning in ComponentState) then Exit;

 if FActive then
 begin

   if FServer <> 0 then DeInitialize(True);

   if Initialize(FServer, HST_BROADCAST, FPort, True) then
   begin
     Err := WSAAsyncSelect(FServer, FHandle, WM_ASYNC, FD_READ);
     if Err = SOCKET_ERROR then
     begin
       Error(WSAErrorToString(WSAGetLastError));
       DeInitialize(True);
       FActive := False;
       Exit;
     end;
   end
   else
   begin
     DeInitialize(True);
     FActive := False;
   end;
     
 end
 else
   DeInitialize(True);

 Sleep(100);

end;

procedure TFWUDPSocket.SetPort(const Value: Integer);
var
 Err: Integer;
begin

 if FPort = Value then
   Exit
 else
   FPort := Value;

 if (csDesigning in ComponentState) then Exit;

 if FServer <> 0 then DeInitialize(True);

 if FActive then
   if Initialize(FServer, HST_BROADCAST, FPort, True) then
   begin
     Err := WSAAsyncSelect(FServer, FHandle, WM_ASYNC, FD_READ);
     if Err = SOCKET_ERROR then
     begin
       Error(WSAErrorToString(WSAGetLastError));
       DeInitialize(True);
       FActive := False;
       Exit;
     end;
   end
   else
   begin
     DeInitialize(True);
     FActive := False;
   end;

 Sleep(100);

end;
     
procedure TFWUDPSocket.SockWND(var AMsg: TMessage);
var
 Err: Integer;
 SockAddr: TSockAddrIn;
 Size, RcvCount: Integer;
 Buffer: array [0..8191] of Char;
 ResultString, FromIP: String;
 MemoryStream: TMemoryStream;
begin

 with AMsg do
   case Msg of
   WM_ASYNC:
   begin

     Err := WSAGetSelectError(LParam);
     if Err <> 0 then
     begin
       Error(WSAErrorToString(Err));
       Exit;
     end;

     case WSAGetSelectEvent(LParam) of
       FD_READ:
       begin

         FillChar(Buffer, 8192, #0);

         Size := SizeOf(SockAddr);
         RcvCount := recvfrom(WParam, Buffer[0], MAX_UDP_SIZE, 0, SockAddr, Size);

         if RcvCount <> SOCKET_ERROR then
         begin

           FromIP := inet_ntoa(SockAddr.sin_addr);

           ResultString := StrPas(@Buffer);
           if Assigned(FOnReadString) then
             FOnReadString(Self, FromIP, ResultString);

           MemoryStream := TMemoryStream.Create;
           MemoryStream.Write(Buffer[0], SizeOf(Buffer));
           MemoryStream.Position := 0;
           if Assigned(FOnReadStream) then
             FOnReadStream(Self, FromIP, MemoryStream);
           MemoryStream.Free;

         end
         else
           Error(WSAErrorToString(WSAGetLastError));
         end;
         
       end;
     end;

   else
     DefWindowProc(FHandle, Msg, WParam, LParam);
   end;

end;

end.


Учитывай что это демка а никак не правило написания кода...


 
Rouse_ ©   (2004-05-11 23:38) [13]

Тут нужны небольшие пояснения...
Вся эта чтука работает одновременно и как клиент и как сервер...
т.е. Делаешь ей Active:= True; и сервер запущен, а после этого можешь из нее же делать Broadcast или Send...
времени не много свободного, поэтому слепил все в кучу :)


 
Zulus   (2004-05-11 23:58) [14]

Спасибо огромное и за это. Теперь буду разбираться. Может что и получится. Еще раз спасибо (просто долго искал совета).


 
Verg ©   (2004-05-12 01:23) [15]


> [6] Rouse_ ©   (11.05.04 21:43)


Странно это. По крайней мере на 9.014 версии Indy все работает без вопросов. Хоть с бродкастами, хоть без.


> [3] ZDDR ©   (11.05.04 10:48)
> все работает нормально сообщения принимаются по 1005 порту
> но стоит выполнить код:
> idudpserver1.active:=false;
> idudpserver1.defaultport:=strtoint("1005");
> idudpserver1.active:=true;
>
> перестают преходить сообщения


Как ведется прием датаграмм (где и как выполняется idudpserver1.Receive***)?
При каких обстоятельствах выполняется приведенный код "рестарта" сервера? Т.е. в результате каких событий он вызывается?


 
Rouse_ ©   (2004-05-12 14:47) [16]

> Verg ©   (12.05.04 01:23) [15]
Вполне вероятно - просто у меня шестерка была в то время, а реализовать нужно было все в сжатые сроки - поэтому пришлось ручками, это гораздо проще чем разбираться в чужом коде...



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

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

Наверх




Память: 0.53 MB
Время: 0.028 c
6-1083574468
zyx
2004-05-03 12:54
2004.07.04
Server.Сlose=error??


3-1086164001
nik
2004-06-02 12:13
2004.07.04
Работа с базой данный Access


4-1085210397
tytus
2004-05-22 11:19
2004.07.04
Как свернуть все окна?


14-1087374879
MeF88
2004-06-16 12:34
2004.07.04
GL_ARB_shader_objects or Detonator 60


4-1083574310
atruhin
2004-05-03 12:51
2004.07.04
Политика аудита