Problem z przerwaniem połączenia.

0

Mam taką oto klasę:

unit connections;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, blcksock, Ships, Fields, Worlds;

Type
  TConnection = class
    private
      server      : TTCPBlockSocket;
      server_cl   : TTCPBlockSocket;
      client      : TTCPBlockSocket;
      IP, PortNr  : String;
      IsServer    : Boolean;

    public
      constructor Create(IPc, portc : string; p : byte);
      function Connect : boolean;
      procedure SendData(var World : TWorld);
      procedure RecvData(var World : TWorld);
      procedure SendCheck(check : Byte);
      function RecvCheck : Byte;
      function Waiting : Boolean;
      procedure Ready;
      destructor ShutDown;
  end;

implementation

{=== Klasa TConnection ========================================================}

constructor TConnection.Create(IPc,portc : string; p : byte);
begin
  case p of
    1 : IsServer := true;
    2 : IsServer := false;
  end;
  IP := IPc;
  PortNr := portc;
  if IsServer Then
  Begin
    Server := TTCPBlockSocket.Create;
    Server.Bind (IP,PortNr);
    Server.Listen;
    Server_cl := TTCPBlockSocket.Create;
  end
  else
    client := TTCPBlockSocket.Create;
end;

{------------------------------------------------------------------------------}

function TConnection.Connect : boolean;
var
  Error : Integer;
begin
  Error := 100;
  If IsServer Then
  begin
    If Server.CanRead (1) Then
    begin
      Server_cl.Socket := Server.Accept;
      Server.CloseSocket;
      Error := Server.LastError;
    end;
  end
  else
  begin
    Client.Connect (IP,PortNr);
    Error := Client.LastError;
  end;
  If Error = 0 Then result := true
  else result := false;
end;

{------------------------------------------------------------------------------}

procedure TConnection.SendData(var World : TWorld);
begin
{*** Kod nieistotny ***}
end;

{------------------------------------------------------------------------------}

procedure TConnection.RecvData(var World : TWorld);
begin
{*** Kod nieistotny ***}
end;

{------------------------------------------------------------------------------}

procedure TConnection.SendCheck(check : Byte);
begin
{*** Kod nieistotny ***}
end;

{------------------------------------------------------------------------------}

function TConnection.RecvCheck : Byte;
begin
{*** Kod nieistotny ***}
end;

{------------------------------------------------------------------------------}

function TConnection.Waiting : Boolean;
begin
{*** Kod nieistotny ***}
end;

{------------------------------------------------------------------------------}

procedure TConnection.Ready;
begin
{*** Kod nieistotny ***}
end;

{------------------------------------------------------------------------------}

destructor TConnection.ShutDown;
begin
  If IsServer then server_cl.CloseSocket
  else client.CloseSocket;
end;

{==============================================================================}

end.

Używam jej w swojej grze by dwóch graczy mogło grać ze sobą. Testowałem sobie jak działa połączenie i przerywanie oczekiwania na połączenie. I samo przerwanie oczekiwania działa bez zarzutu. Jednak gdy tworzę nową grę jako serwer (patrz konstruktor) następnie przerwę oczekiwanie na połączenie (patrz destruktor) to klient i tak się podłączy i wystartuje. Nie wiem czemu tak się dzieje. Może mi to ktoś wyjaśnić?

Poniżej podaję 2 procedury w których pokazane jest jak wykorzystuję klasę:


procedure TForm1.FormKeyPress(Sender: TObject; var Key: char);
var
  maxy : Byte;
begin
  If not EndTurn Then
  begin
    if MoveMode or AttackMode or PutMine or DestroyMine then
    begin
      case Key of
        'w' : if y2 > 0 then Dec(y2);
        's' : if y2 < 17 then Inc(y2);
        'a' : if x2 > 0 then Dec(x2);
        'd' : if x2 < 11 then Inc(x2);
        #27 : begin
                MoveMode := false;
                AttackMode := false;
                PutMine := false;
                DestroyMine := false;
              end;
        #13 : begin
                If MoveMode Then
                begin
                  If World.Move(x1, y1, x2, y2) Then
                  begin
                    MoveMode := False;
                    MoveDone := True;
                  end;
                end
                else If AttackMode Then
                begin
                  if World.Attack (x1, y1, x2, y2) Then
                  Begin
                    AttackMode := False;
                    AttackDone := True;
                  end;
                end
                else If PutMine Then
                begin
                  If World.PutMine(x1, y1, x2, y2) then PutMine := False
                end
                else If DestroyMine Then
                begin
                  If World.DestroyMine(x1, y1, x2, y2) then DestroyMine := False
                end;
              end;
      end;
    end
    else if PutMode Then
    begin
      case Key of
        'w' : if y1 > 0 then Dec(y1);
        's' : if y1 < 17 then Inc(y1);
        'a' : if x1 > 0 then Dec(x1);
        'd' : if x1 < 11 then Inc(x1);
        #13 : begin
                case World.GetPlayer of
                  1 : begin
                        If y1 <= 3 then
                          If World.PutShip (x1, y1, ShipPut) Then Inc(ShipPut);
                      end;
                  2 : begin
                        If y1 >= 14 then
                          If World.PutShip (x1, y1, ShipPut) Then Inc(ShipPut);
                      end;
                end;
              end;
      end;
    end
    else If MainMenu Then
    begin
      case Key of
        '1' : my := 0;
        '2' : my := 1;
        '3' : my := 2;
        'w' : If my > 0 then Dec(my);
        's' : If my < 2 then Inc(my);
        #13 : begin
                case my of
                  0 : begin
                        MainMenu := False;
                        GameMenu := True;
                      end;
                  1 : begin
                        OptionsMenu := True;
                        MainMenu := False;
                      end;
                  2 : begin
                        Form1.Close;
                      end;
                end;
              end;
      end;
    end
    else if OptionsMenu then
    begin
      case Key of
        '1' : my := 0;
        '2' : my := 1;
        'w' : If my > 0 then Dec(my);
        's' : If my < 1 then Inc(my);
        #13 : begin
                case my of
                  0 : begin
                        OptionsMenu := False;
                        IPChange := True;
                      end;
                  1 : begin
                        OptionsMenu := False;
                        MainMenu := True;
                      end;
                end;
              end;
      end;
    end
    else if IPChange Then
    begin
      case Key of
        '0' : IP := IP + Key;
        '1' : IP := IP + Key;
        '2' : IP := IP + Key;
        '3' : IP := IP + Key;
        '4' : IP := IP + Key;
        '5' : IP := IP + Key;
        '6' : IP := IP + Key;
        '7' : IP := IP + Key;
        '8' : IP := IP + Key;
        '9' : IP := IP + Key;
        '.' : IP := IP + Key;
        'c' : IP := '';
      end;
      If Key = #13 Then
      begin
        IPChange := False;
        OptionsMenu := False;
        PortChange := True;
      end;
    end
    else if PortChange Then
    begin
      case Key of
        '0' : Port := Port + Key;
        '1' : Port := Port + Key;
        '2' : Port := Port + Key;
        '3' : Port := Port + Key;
        '4' : Port := Port + Key;
        '5' : Port := Port + Key;
        '6' : Port := Port + Key;
        '7' : Port := Port + Key;
        '8' : Port := Port + Key;
        '9' : Port := Port + Key;
        'c' : Port := '';
      end;
      If Key = #13 Then
      begin
        IPChange := False;
        OptionsMenu := False;
        PortChange := False;
        MainMenu := True;
      end;
    end
    else If GameMenu Then
    begin
      case Key of
        '1' : my := 0;
        '2' : my := 1;
        '3' : my := 2;
        'w' : If my > 0 then Dec(my);
        's' : If my < 2 then Inc(my);
        #13 : begin
                case my of
                  0 : begin
                        World := TWorld.Create(1);
                        Connection := TConnection.Create (IP, Port, 1);
                        Connect := 1;
                        EndTurn := False;
                        GameMenu := False;
                      end;
                  1 : begin
                        World := TWorld.Create(2);
                        Connection := TConnection.Create (IP, Port, 2);
                        Connect := 1;
                        EndTurn := False;;
                        GameMenu := False;
                      end;
                  2 : begin
                        GameMenu := False;
                        MainMenu := True;
                      end;
                end;
              end;
      end;
    end
    else If ShipMenu Then
    begin
      case World.ShipType(x1, y1) of
        Pancernik   : maxy := 2;
        Rakietowy   : maxy := 2;
        Krazownik   : maxy := 2;
        Niszczyciel : maxy := 2;
        Podwodny    : maxy := 2;
        Eskortowiec : maxy := 2;
        Tralowiec   : maxy := 4;
        Desantowy   : maxy := 1;
        Bateria     : maxy := 1;
        Mina        : maxy := 0;
      end;
      case Key of
        '1' : If 0 <= maxy Then my := 0;
        '2' : If 1 <= maxy Then my := 1;
        '3' : If 2 <= maxy Then my := 2;
        '4' : If 3 <= maxy Then my := 3;
        '5' : If 4 <= maxy Then my := 4;
        'w' : If my > 0 then Dec(my);
        's' : If my < maxy then Inc(my);
        #27 : ShipMenu := False;
        #13 : Begin
                If (my = 0) and
                   (World.ShipType(x1, y1) <> Desantowy) and
                   (World.ShipType(x1, y1) <> Mina) and
                   (not AttackDone) Then
                   begin
                     AttackMode := True;
                     ShipMenu := False;
                     x2 := x1;
                     y2 := y1;
                   end
                else if (my = 1) and
                        (World.ShipType(x1, y1) <> Desantowy) and
                        (World.ShipType(x1, y1) <> Bateria) and
                        (World.ShipType(x1, y1) <> Mina) and
                        (not MoveDone) Then
                begin
                  MoveMode := True;
                  ShipMenu := False;
                  x2 := x1;
                  y2 := y1;
                end
                else if (my = 0) and (World.ShipType(x1, y1) = Desantowy) and (not MoveDone) Then
                begin
                  MoveMode := True;
                  ShipMenu := False;
                  x2 := x1;
                  y2 := y1;
                end
                else if (my = 0) and (World.ShipType(x1, y1) = Bateria) and (not AttackDone) Then
                begin
                  AttackMode := True;
                  ShipMenu := False;
                  x2 := x1;
                  y2 := y1;
                end
                else if (my = 0) and (World.ShipType(x1, y1) = Mina) Then
                ShipMenu := False
                else if (my = 1) and
                        (World.ShipType(x1, y1) = Desantowy) and
                        (World.ShipType(x1, y1) = Bateria) Then
                ShipMenu := False
                else if (my = 2) and (World.ShipType(x1, y1) = Tralowiec) Then
                Begin
                  ShipMenu := False;
                  PutMine := True;
                  x2 := x1;
                  y2 := y1;
                end
                else if (my = 3) and (World.ShipType(x1, y1) = Tralowiec) Then
                Begin
                  ShipMenu := False;
                  DestroyMine := True;
                  x2 := x1;
                  y2 := y1;
                end
                else if (my = 4) and (World.ShipType(x1, y1) = Tralowiec) Then
                ShipMenu := False;
              end;
      end;
    end
    else If connect = 1 Then
    begin
      If Key = #27 Then
      Begin
        PutMode := False;
        AttackMode := False;
        MoveMode := False;
        PutMine  := False;
        DestroyMine := False;
        AttackDone := False;
        MoveDone := False;
        ShipMenu := False;
        Win := False;
        Loose := false;
        Connect := 0;

        GameRunning := False;

        MainMenu := True;
        OptionsMenu := False;
        IPChange := False;
        PortChange := False;
        GameMenu := False;

        ShipPut := 0;

        World.Destroy;
        Connection.Shutdown;
      end;
    end
    else
    begin
      case Key of
        'w' : if y1 > 0 then Dec(y1);
        's' : if y1 < 17 then Inc(y1);
        'a' : if x1 > 0 then Dec(x1);
        'd' : if x1 < 11 then Inc(x1);
        'k' : begin
                check := World.Check;
                Connection.Ready;
                Connection.SendCheck(check);
                Connection.SendData(World);
                EndTurn := true;
                If Check = World.GetPlayer Then
                begin
                  Win := True;
                  Loose := False;
                end
                else If (Check <> World.GetPlayer) and (check <> 0) then
                begin
                  Win := False;
                  Loose := True;
                end;
              end;
        #13 : Begin
                If (World.ShipType(x1, y1) <> Nothing) and
                   (World.GetShipPlayer(x1, y1) = World.GetPlayer) and
                   (not PutMode) Then ShipMenu := True;
              end;
      end;
    end;
    If ShipPut = 30 Then PutMode := False;
  end;
  If Loose or win Then
  begin
    PutMode := False;
    AttackMode := False;
    MoveMode := False;
    PutMine  := False;
    DestroyMine := False;
    AttackDone := False;
    MoveDone := False;
    ShipMenu := False;
    Win := False;
    Loose := False;
    Connect := 0;

    GameRunning := False;

    MainMenu := True;
    OptionsMenu := False;
    IPChange := False;
    PortChange := False;
    GameMenu := False;
    EndTurn := False;
    World.Destroy;
    Connection.ShutDown;
    ShipPut := 0;
  end;
end;  

oraz

procedure TForm1.OpenGLControl1Paint(Sender: TObject);
begin
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0, Width, Height, 0, 0, 0);
  glMatrixMode(GL_MODELVIEW);
  glDisable(GL_DEPTH_TEST);
  glClear(GL_COLOR_BUFFER_BIT);

  If not GEngine.TextureGen then GEngine.InitTxt;
  If (GameRunning) and (Connect = 2) then
  Begin
    GEngine.DrawGame(World);
    GEngine.DrawRect(x1, y1);
    GEngine.DrawInfo(x1, y1, World);
    If AttackMode or PutMine Then
    Begin
      GEngine.DrawAttackRect(x2, y2);
      GEngine.DrawInfo(x2, y2, World);
    end;
    If MoveMode or DestroyMine Then
    Begin
      GEngine.DrawMoveRect(x2, y2);
      GEngine.DrawInfo(x2, y2, World);
    end;
  end;
  If MainMenu Then
  begin
    GEngine.DrawMainMenu;
    GEngine.DrawMenuRect(my);
  end;
  If OptionsMenu Then
  begin
    GEngine.DrawOptions;
    GEngine.DrawMenuRect(my);
  end;
  If IPChange Then
  begin
    GEngine.DrawIPChange(IP);
  end;
  If PortChange Then
  begin
    GEngine.DrawPortChange(Port);
  end;
  If GameMenu Then
  begin
    GEngine.DrawGameMenu;
    GEngine.DrawMenuRect(my);
  end;
  If ShipMenu Then
  begin
    GEngine.DrawShipMenu(World.ShipType(x1, y1));
    GEngine.DrawShipMenuRect(my);
  end;
  If EndTurn Then
  Begin
    GEngine.DrawMessage('Tura drugiego gracza');
    If Connection.Waiting then
    Begin
      Check := Connection.RecvCheck;
      If Check = 0 then
      Begin
        Connection.RecvData(World);
        EndTurn := false;
        AttackDone := False;
        MoveDone := False;
      end
      else If Check = World.GetPlayer Then
      begin
        Win := True;
        Loose := False;
      end
      else If (Check <> World.GetPlayer) and (check <> 0) then
      begin
        Win := False;
        Loose := True;
      end;
    end;
  end;
  If Win then GEngine.DrawMessage('WYGRALES!!!');
  If Loose then GEngine.DrawMessage('PRZEGRALES!!!');
  If Connect = 1 Then
  Begin
    GEngine.DrawMessage('Oczekiwanie na polaczenie...');
    If Connection.Connect Then
    Begin
      Connect := 2;
      GameMenu := False;
      GameRunning := True;
      PutMode := True;
      If World.GetPlayer = 2 Then EndTurn := True;
    end;
  end;

  OpenGLControl1.SwapBuffers;
end; 

Co niektórzy stwierdzą, że kod woła o pomstę do nieba. Ale jest on w fazie testów i optymalizacji więc to nie jest jego końcowa forma :)

1

If IsServer then server_cl.CloseSocket
else client.CloseSocket;

To się samo zwolni? U siebie używam FreeAndNil i raczej przerywa czekanie. No ale zwalnianie jest dla cieniasów.

TConnection = class
server : TTCPBlockSocket;
server_cl : TTCPBlockSocket;
client : TTCPBlockSocket;

Nie wiem czemu robisz coś co na raz może być serwerem i klientem. Ja u siebie mam serwer który wspiera wiele połączeń na raz, i samemu zarządza rzeczami jak ping itp. poprzez klasę nad każdym socketem (tj. klient może sobie pobrać Ping, serwer dla każdego połączenia i można dać automatyczny timeout). Ja nie mówię że od razu masz tak samo robić ale mógłbyś podzielić to na TSerwer i TKlient, dodatkowo dodając klasę bazową która by dodawała abstrakcyjne metody Wyślij i Odbierz i na niej operować w różnego rodzaju rzeczach które są takie same dla klienta i serwera.
Generalnie to masz tutaj kod trochę bez sensu. Serwer po utworzeniu samemu oczekuje połaczeń, a klient sam się nie łączy tylko trzeba wykonać Connect (w serwerze to usiłuje połączyć nowego klienta, to takie oczywiste).

Server.CanRead (1)

1 chyba ci wątek przełączy (tak jak Sleep(0);) - czemu nie 0?

Error := Server.LastError;

Takie zgłaszanie błędów nie jest za dobre... Nie można jako result funkcji?

procedure TConnection.SendData(var World : TWorld);

I pewnie jak zrobisz nową grę to będziesz od nowa robić system połączeń? Czemu nie możesz zrobić systemu serwer-klient i potem w kodzie gry oprogramować już wysyłanie/odbieranie. Byłoby bardziej elastycznie.

procedure TConnection.Ready;

Zakładamy się co to robi? Nie widzę pojęcia Ready dla połączenia... A ty na tym robisz logikę wysyłania danych.

procedure TForm1.FormKeyPress(Sender: TObject; var Key: char);
var
maxy : Byte;
begin
[długi kod]
end;

Nie no serio, bez procedur?

case p of
1 : IsServer := true;
2 : IsServer := false;
end;

Czemu tak, nie może być boolean do procedury? Już nie mówiąc że wystarczy IsServer:=p=1;

'0' : IP := IP + Key;
'1' : IP := IP + Key;
'2' : IP := IP + Key;
'3' : IP := IP + Key;
'4' : IP := IP + Key;
'5' : IP := IP + Key;
'6' : IP := IP + Key;
'7' : IP := IP + Key;
'8' : IP := IP + Key;
'9' : IP := IP + Key;

`0'..'9'=Ip+Key;'' było za prosto?

Pancernik : maxy := 2;
Rakietowy : maxy := 2;
Krazownik : maxy := 2;
Niszczyciel : maxy := 2;
Podwodny : maxy := 2;
Eskortowiec : maxy := 2;
Tralowiec : maxy := 4;
Desantowy : maxy := 1;
Bateria : maxy := 1;

Tablice są dla lamerów!

Co niektórzy stwierdzą, że kod woła o pomstę do nieba. Ale jest on w fazie testów i optymalizacji więc to nie jest jego końcowa forma

Robisz to już od jakiegoś czasu i taplasz się w niezłym gównie ;) . Ale widzę że są postępy, wolne, ale są. I nie martw się, twój kod nawet przypomina moje wczesne kody kiedy nie potrafiłem jeszcze aż tak formatować kodu, nauczysz się tego jak twoje większe projekty będą masakrą. Stosuj więcej klas i je dziel na fabrykaty które się przydadzą w przyszłości (można je dać do jakiegoś zbiorczego katalogu gdzie będzie zawsze najnowsza wersja i mieć domyślnie dodaną ścieżkę do tego więc nie trzeba kopiować) i na te które są stricte do gry (i te do gry powinny często korzystać z fabrykatów).
Np. u ciebie unity mogłyby wyglądać tak:
-W katalogu gry

  • main.lpr (główne, zbiera wszystko do kupy)
  • game_basics.pas - prymitywy: typy statków, ich rozmiary
  • world.pas - definicja świata (jeżeli jest mała to można dać do game_basics).
  • engine.pas - główny silnik gry, zarządza obiektem TWorld i obsługuje wszystko od mechaniki gry.
  • display.pas - wyświetla otrzymanym TWorld od engine
  • game_conn.pas - zarządzanie serwerem i klientem, zależny od connection.pas
  • menu.pas - zarządza menusami etc (może zrobić własny system który będzie wyświetlał naciskalne guziki, suwaki itd.?)

-W katalogu zbiorczym:

  • connection.pas - obsługa połączeń

No i w każdym unicie powinny być klasy związane tylko z daną rzeczą.

Oj się rozpisałem... Mam nadzieję że dużo głupot nie nawaliłem, nie mam siły tego sprawdzać :P

0

No to co napisałeś to mniej więcej o to mi chodzi :P Tylko jestem newbie :P może nie totalnym ale jeszcze świerzak. Jednak wracając do mojego pytania. Jak przejrzałeś kod to w tym miejscu

else If connect = 1 Then
    begin
      If Key = #27 Then
      Begin
        PutMode := False;
        AttackMode := False;
        MoveMode := False;
        PutMine  := False;
        DestroyMine := False;
        AttackDone := False;
        MoveDone := False;
        ShipMenu := False;
        Win := False;
        Loose := false;
        Connect := 0;
 
        GameRunning := False;
 
        MainMenu := True;
        OptionsMenu := False;
        IPChange := False;
        PortChange := False;
        GameMenu := False;
 
        ShipPut := 0;
 
        World.Destroy;
        Connection.Shutdown;
      end;
    end

Obiekt klasy TConnection przestaje istnieć. Więc teoretycznie jak coś by próbowało się do niego podłączyć to sypnęło by błedęm "connection refused" albo "connection timeout" A najśmieszniejsze jest to, że jak utworzę obiekt Connection (jako serwer) i następnie go zniszczę. To dopóki nie zamknę całego programu to ktoś inny może się połączyć i gra wystartuje. I to mnie zastanawia czemu tak jest. Nie umiem tego naprawić. A jak do tego doszedłem? Odpalałem 2 razy program po skompilowaniu i w jednym wybierałem "utwórz grę" przez co konstruktor TConnect był wywoływany mniej więcej tak

Connection := TConnection.Create (IP, Port`code> A potem naciskałem ESC co powodowało wykonanie tego fragmentu kodu. `If connect = 1 Then
    begin
      If Key = #27 Then
      Begin
        PutMode := False;
        AttackMode := False;
        MoveMode := False;
        PutMine  := False;
        DestroyMine := False;
        AttackDone := False;
        MoveDone := False;
        ShipMenu := False;
        Win := False;
        Loose := false;
        Connect := 0;
 
        GameRunning := False;
 
        MainMenu := True;
        OptionsMenu := False;
        IPChange := False;
        PortChange := False;
        GameMenu := False;
 
        ShipPut := 0;
 
        World.Destroy;
        Connection.Shutdown;
      end;
    end

Następnie w drugim programie wybierałem "dołącz do gry". co powodowało wywołanie konstruktora w ten sposób Connection := TConnection.Create (IP, Port, 2); A następnie w procedurze TForm1.OpenGLControl1Paint (podczepiłem pod tą procedurę bo dobrze imituje pętlę) w drugim odpalonym programie (próbującym się podłączyć do serwera jako klient) wywoływany jest kod

 If Connect = 1 Then
  Begin
    GEngine.DrawMessage('Oczekiwanie na polaczenie...');
    If Connection.Connect Then
    Begin
      Connect := 2;
      GameMenu := False;
      GameRunning := True;
      PutMode := True;
      If World.GetPlayer = 2 Then EndTurn := True;
    end;
  end;

I najlepsze jest to, że Connection.Connect zwraca wartość True czyli patrząc na procedurę connect w klasie, to Error przyjmuje wartość 0 czyli brak błędów. Co jest moim zdaniem dziwne bo po wywołaniu tego Client.Connect (IP,PortNr); powinno wywalić jakiś error bo przecież serwer nie istnieje.

Testowałem na localhost (127.0.01) i w sieci jak również testowałem na 2 komputerach połączonych w sieć. Zawsze występował ten sam problem. Port jaki używam to 1234. Ale myślę że to nie wina portu :P.

PS.
FreeAndNil też używałem i ciągle ten sam błąd.

0

Obiekt klasy TConnection przestaje istnieć.

Destruktor nazywaj Destroy, zawsze... I wywołuj Free.

Więc teoretycznie jak coś by próbowało się do niego podłączyć to sypnęło by błedęm "connection refused" albo "connection timeout"

TConnection to tylko nadbudówka odpowiadająca za obsługę socketów, a ty pewnie nie zwolniłeś socketów.

A najśmieszniejsze jest to, że jak utworzę obiekt Connection (jako serwer) i następnie go zniszczę. To dopóki nie zamknę całego programu to ktoś inny może się połączyć i gra wystartuje.

Niektórzy by to feature nazwali. Sprawdź czy masz port przypisany (netstat z jakimiś paramsami daj sobie).

powinno wywalić jakiś error bo przecież serwer nie istnieje.

Serwer istnieje jeżeli ma przypisany port.

Port jaki używam to 1234.

Bodaj trojany lubią ten port. Gry często używają 27XXX.

PS.
FreeAndNil też używałem i ciągle ten sam błąd.

FreeAndNil na czym, na TConnection czy na sockecie. Najlepiej używaj na obu.

BTW BTW.

Server := TTCPBlockSocket.Create;
Server.Bind (IP,PortNr);
Server.Listen;
Server_cl := TTCPBlockSocket.Create;

Ile tworzymy socketów? 2.

destructor TConnection.ShutDown;
begin
If IsServer then server_cl.CloseSocket
else client.CloseSocket;
end;

Ile socketów zamykamy? 1. Ile socketów niszczymy? 0.

Możesz dać np.
if IsServer then begin FreeAndNil(server);FreeAndNil(server_cl); end else FreeAndNil(client);

0

Dobra zrobiłem jak radziłeś i teraz 3 procedury odpowiedzialne za inicjowanie i przerwanie połączenia wyglądają tak:

constructor TConnection.Create(IPc,portc : string; p : byte);
begin
  case p of
    1 : IsServer := true;
    2 : IsServer := false;
  end;
  IP := IPc;
  PortNr := portc;
  if IsServer Then
  Begin
    Server := TTCPBlockSocket.Create;
    Server.Bind (IP,PortNr);
    Server.Listen;
    Server_cl := TTCPBlockSocket.Create;
  end
  else
    client := TTCPBlockSocket.Create;
end;

{---------------------------------------------------------------------}

function TConnection.Connect : boolean;
var
  Error : Integer;
begin
  Error := 100;
  If IsServer Then
  begin
    If Server.CanRead (1) Then
    begin
      Server_cl.Socket := Server.Accept;
      FreeAndNil(Server);
      Error := Server.LastError;
    end;
  end
  else
  begin
    Client.Connect (IP,PortNr);
    Error := Client.LastError;
  end;
  If Error = 0 Then result := true
  else result := false;
end;

{---------------------------------------------------------------------}

destructor TConnection.Destroy;
begin
  If IsServer then FreeAndNil(server_cl)
  else FreeAndNil(Client);
  inherited Destroy;
end;

Jednak problem nadal występuje O.o Nie mam zielonego pojęcia czemu serwer cały czas zostaje w pamięci...

0

Dobra zrobiłem jak radziłeś

Nie zrobiłeś tak jak radziłem i dlatego nie działa.

Jednak problem nadal występuje O.o Nie mam zielonego pojęcia czemu serwer cały czas zostaje w pamięci...

Podpowiem: Problem występuje tylko jeżeli nikt się nie połączył wcześniej do serwera. Myśl. Problem jest na tyle banalny że debugger/TBrain sobie dadzą radę...

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