TClientSocket, problem przy łączeniu

0

Dlaczego TClientSocket (NonBlocking) nie chce się połączyć od razu po wywołaniu Active:=True? Przykładowo...

CS.Host:=xxx;
CS.Port:=xxx;
CS.Active:=true;
CS.Socket.SendBuf(bufz[0],147);

W tym wypadku klient nie wyśle danych bo jest jeszcze nie połączony...
Dodałem więc kod który ma sprawić by klient poczekał na połączenie...

CS.Host:=xxx;
CS.Port:=xxx;
CS.Active:=true;
a:=0;
repeat
  If clientsocket1.Active=true then Break;
  a:=a+100;
  sleep(100);
until a>5000;
CS.Socket.SendBuf(bufz[0],147);

Jednak nie załatwia to problemu bo klient zaczyna się łączyć dopiero po upłynięciu tych 5 sekund...
Dlaczego? Kombinuję nad tym już drugi dzień :|

0

Wykorzystaj zdarzenie OnConnect.
Jak byś miał blocking to by Ci zadziałało.

0

Mój program to serwer pośredniczący pomiędzy klientem i właściwym serwerem. Dla każdego połączenia przychodzącego tworzony jest wątek SockThread. SockThread tworzy TClientSocket do połączenia się z właściwym serwerem.
@b0bik: Przerzucenie danych do OnConnect nic mi nie dało. SockThread jest zamrożony (czeka na dane przez recv) a TClientSocket podejmuje próbę połączenia się dopiero po wykonaniu całej procedury SockThread. Jeśli ktoś ma jeszcze jakiś pomysł to byłbym wdzięczny :-) Jeśli jedynym jedynym wyjściem/lepszym wyjściem jest użycie TClientSocket-Blocking to prosiłbym o jakiś przykład użycia/tutorial bo nie mogę go doprowadzić do "używalności" (zamraża mi się i nie odczytuje danych przychodzących od serwera [???] )

type
  PInteger = ^Integer;
type
  TEventHandlers = class // create a dummy class
    procedure Odebranie(Sender: TObject; Socket: TCustomWinSocket);
    procedure Polaczenie(Sender: TObject; Socket: TCustomWinSocket);
    procedure Rozlaczenie(Sender: TObject; Socket: TCustomWinSocket);
  end;

TBuffStack=record
  Buff:array[0..1023] of byte;
  len:integer;
end;

TProx=record
  ServSock:TSocket;
  CS:TClientSocket;
  connStart:Cardinal;
  dataStos:array of TBuffStack;
end;
var
  Sock: TSocket;
  PInt: PInteger;
  Clnts: Array of TProx;


  EvHandler:TEventHandlers;
procedure SockThread(Pint: PInteger); stdcall;
var
  Size, I,k,a: Integer;
  Buff: Array[0..1023] of Byte;
  TMP:Dword;
begin
  Clnts[PInt^].CS:=TClientSocket.Create(form1);
  Clnts[PInt^].CS.OnConnect:=EvHandler.Polaczenie;
  Clnts[PInt^].CS.OnDisconnect:=EvHandler.Rozlaczenie;
  Clnts[PInt^].CS.OnRead:=EvHandler.Odebranie;
  //Clnts[PInt^].CS.ClientType:=ctBlocking;
  Clnts[PInt^].CS.Host:=LOGIN_IP1;
  Clnts[PInt^].CS.Port:=7171;
  Clnts[PInt^].CS.Active:=true;

  repeat
    Size:=recv(Clnts[PInt^].ServSock, Buff[0], 1024, 0);
    form1.logmem.Lines.Add('[S]Recived '+inttostr(size)+' from '+inttostr(Clnts[PInt^].ServSock));
    if Size < 1 then Begin
      if Clnts[PInt^].CS.Active=true then Clnts[PInt^].CS.Active:=false;
      Break;
    End;
    if Clnts[PInt^].CS.Active=true then Begin
      Clnts[PInt^].CS.Socket.SendBuf(Buff[0],Size);
      form1.logmem.Lines.Add('[S]Forwarded '+inttostr(size)+' to '+inttostr(Clnts[PInt^].CS.Socket.SocketHandle));
    end else begin
      SetLength(Clnts[PInt^].dataStos,High(Clnts[PInt^].dataStos)+2);
      for a:=0 to 1023 do
      Clnts[PInt^].dataStos[High(Clnts[PInt^].dataStos)].Buff[a]:=Buff[a];
      Clnts[PInt^].dataStos[High(Clnts[PInt^].dataStos)].len:=Size;
      form1.logmem.Lines.Add('Added '+inttostr(size)+' bytes on stack');
    end;
    //RecivePacket(Clnts[PInt^], NetMsg, PlayerID);
  until false;
  if Clnts[PInt^].CS.Active=true then Clnts[PInt^].CS.Active:=false;
  Clnts[PInt^].CS.Destroy;
  shutdown(Clnts[PInt^].ServSock, SD_BOTH);
  closesocket(Clnts[PInt^].ServSock);
  Clnts[PInt^].ServSock := INVALID_SOCKET;
  Dispose(PInt);
end;

procedure TEventHandlers.Odebranie(Sender: TObject; Socket: TCustomWinSocket);
var
size:integer;
Buff: Array[0..1023] of Byte;
begin
  Size:=Socket.ReceiveBuf(Buff[0], 1024);
  form1.logmem.Lines.Add('[C]Recived '+inttostr(size)+' from '+inttostr(Socket.SocketHandle));
//do zrobienia kod na przesylanie danych do klienta
end;

procedure TEventHandlers.Polaczenie(Sender: TObject; Socket: TCustomWinSocket);
var a,b:integer;
begin
  form1.logmem.Lines.Add('[S]Connected to login server in '+inttostr(Socket.SocketHandle));
  for a:=0 to high(Clnts) do begin
    if Clnts[a].CS.Socket.SocketHandle=Socket.SocketHandle then Break;
  end;
  for b:=0 to High(Clnts[a].dataStos) do Begin
    Socket.SendBuf(Clnts[a].dataStos[b].Buff,Clnts[a].dataStos[b].len);
  End;
  form1.logmem.Lines.Add('[S]Sent '+inttostr(High(Clnts[a].dataStos))+' stacked buffs');
end;

procedure TEventHandlers.Rozlaczenie(Sender: TObject; Socket: TCustomWinSocket);
begin
  form1.logmem.Lines.Add('[S]Disconnected from login server in '+inttostr(Socket.SocketHandle));
end;

Procedure MainSockThread;
var
i:integer;
Tmp: DWord;
AdrR: TSockAddrIn;
Begin
  repeat
    I := 0;
    while I < Length(Clnts) do begin
      if Clnts[I].ServSock = INVALID_SOCKET then Break;
      Inc(I);
    end;
    if I = Length(Clnts) then SetLength(Clnts, I + 1);
    Tmp := SizeOf(AdrR);
    Clnts[I].ServSock := accept(Sock, @AdrR, @Tmp);
    if Clnts[I].ServSock = INVALID_SOCKET then Break;
    New(PInt);
    PInt^ := I;
    CreateThread(nil, 0, @SockThread, PInt, 0, Tmp);
  until False;
  form1.logmem.Lines.Add('Serwer zatrzymany.');
  WSACleanUp();
End;
0
T3D napisał(a)

Dlaczego TClientSocket (NonBlocking) nie chce się połączyć od razu po wywołaniu Active:=True? Przykładowo...

CS.Host:=xxx;
CS.Port:=xxx;
CS.Active:=true;
CS.Socket.SendBuf(bufz[0],147);

W tym wypadku klient nie wyśle danych bo jest jeszcze nie połączony...

Nie chce mi się czytać kodu z ostatniego posta, ale odpowiedź na postawione na początku pytanie jest prosta. Ustawienie Active na True powoduje że socket łączy się asynchronicznie, jest więcej niż pewne że linijka poniże nie będziesz jeszcze połączony. Co do zastosowania Repeat to to nie działa bo blokujesz aplikacje czymś takim. Może ProcessMessages by pomogło w tej pętli ale to po prostu nie tak się robi. Przy asynchronicznym łączeniu, sygnałem że możesz coś wysyłać jest zdarzenie OnConnect.

0

witam,
miałem bardzo podobny problem i zajrzałem do nieco "przeterminowanego" tematu ;-)
dzięki @b0bik Twoja uwaga o komunikacji asynchronicznej i wykorzystaniu event'u OnConnect
ZADZIAŁAŁA :-)
dzięki

edit:
znaczy nie uwaga zadziałała tylko wykorzystanie event'u zadziałało [green]

1 użytkowników online, w tym zalogowanych: 0, gości: 1