Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Winsock , send/recv, wie? (https://www.delphipraxis.net/71649-winsock-send-recv-wie.html)

xxl1 18. Jun 2006 23:26


Winsock , send/recv, wie?
 
Hallo mitnander!
Ich möchte eine schlanken server und client programmieren die daten austauschen.
Kommuniziert wird über TCP also:
Delphi-Quellcode:
 S := socket (AF_INET, SOCK_STREAM , 0);
Es funktioniert alles bis auf die send/recv finktionen. Die Verbindung zwischen client und server steht(State= established),
dann will ich vom client zum server etwas senden:
Delphi-Quellcode:
function TNet_client.Winsock_sendTCP;
var bytecount:integer;
begin
  buffer:='Ein wichtiges Datenpaket';
  bytecount:=send(S, buffer, strlen(buffer), 0);
hier gibt mir WSAGetLastError 5 aus.
Delphi-Quellcode:
function TNet.Winsock_reciveTCP;
var datacount: integer;
begin
datacount:=recv(S, buffer, sizeof(buffer),0);
end;
hier wird mir für datacount -1 ausgegeben (Socket error)
und natürlich ist der buffer leer.
Weiss jemand wieso? Wenn ja, dann postet mal fleißig!
Danke schonmal!

Basilikum 19. Jun 2006 06:17

Re: Winsock , send/recv, wie?
 
ich nehme an, buffer ist bei dir PChar !?
Code:
function TNet_client.Winsock_sendTCP;
var bytecount:integer;
begin
  buffer:='Ein wichtiges Datenpaket';
  bytecount:=send(S, buffer[color=#ff001f]^[/color], strlen(buffer), 0);
(send() erwartet keinen Pointer, sondern eine untypiserte Variable)

zum 2. Problem: verrate uns doch noch, von welchem Type buffer ist... aller Pointer-ähnlichen Dinge scheiden aus, da du sizeof() verwendest...

xxl1 19. Jun 2006 17:11

Re: Winsock , send/recv, wie?
 
also wie du bereits vermutet hast, ist buffer : PChar in 1) und 2)
Daher jetzt die Frage: kann man bei einer Pchar Variable die funktion sizeof() nicht verwenden? Wenn ja , was kann man dann verwenden um die länge von Pchar zu ermitteln?

Basilikum 19. Jun 2006 17:55

Re: Winsock , send/recv, wie?
 
Zitat:

Zitat von xxl1
also wie du bereits vermutet hast, ist buffer : PChar in 1) und 2)
Daher jetzt die Frage: kann man bei einer Pchar Variable die funktion sizeof() nicht verwenden? Wenn ja , was kann man dann verwenden um die länge von Pchar zu ermitteln?

SizeOf() wird dir bei einem Pointer (PChar ist ein solcher) auf einer 32-Bit-Maschine immer 4 zurückgeben...
eine Möglichkeit ist StrLen(), dann ist es jedoch unmöglich, ein 0-Byte als Bestandteil der Daten zu haben, da dies als Kennzeichnung für das Ende dient... => kommt auf die Daten an - für "Nur-Text" funktioniert StrLen problemlos...

xxl1 19. Jun 2006 22:28

Re: Winsock , send/recv, wie?
 
ok danke für die Info ,hat leider nicht zum gewünschtrn Effekt geführt.

Nogge 20. Jun 2006 00:46

Re: Winsock , send/recv, wie?
 
Hallo xxl1,
Du musst nach dem Erstellen des Sockets natürlich erst mal zum Server connecten:
Delphi-Quellcode:
function TClient.Connect(const IP: string; Port: Word): Boolean;
var
  sa: SOCKADDR_IN;
  HostInfos : PHostEnt;
begin
  ZeroMemory(@sa, SizeOf(sa));
  sa.sin_family      := AF_INET;
  sa.sin_port        := htons(Port);
  sa.sin_addr.S_addr := inet_addr(PChar(IP));
  { nicht notwendig zum connecten
  HostInfos := gethostbyaddr(@sa.sin_addr.S_addr, SizeOf(sa.sin_addr.S_addr), AF_INET);
  if (HostInfos <> nil) then
    Hostname := HostInfos^.h_name;
  }
  Result := (WinSock.connect(FAccSock, sa, SizeOf(sa)) <> SOCKET_ERROR);
end;
Falls du das bereits getan hast, solltest du mithilfe der folgenden Funktion einen string übermitteln können:
Delphi-Quellcode:
// string
function TClient.Send(Data: string): Boolean;
begin
  Result := (WinSock.send(FAccSock, Data[1], Length(Data), 0) > 0); // SOCKET_ERROR = -1
end;
// PChar
function TClient.Send(Data: PChar): Boolean;
begin
  Result := (WinSock.send(FAccSock, Data[0], Length(Data), 0) > 0); // SOCKET_ERROR = -1
end;

xxl1 20. Jun 2006 02:49

Re: Winsock , send/recv, wie?
 
ok danke für den tipp!
das mit der send() funktion scheint bei mir schon vorher nach ausprobieren geklappt zu haben. Leider werden die Daten scheinbar vom "Server" nicht empfangen.
Daher poste ich nun einmal den abstrahierten quellcode für den "server" in der reihenfolge wie ich die funktionen aufrufe:
Delphi-Quellcode:
function TNet.WinSock_startup;
  var wsa: TWSAData;
begin
  WSAStartup(MAKEWORD(2, 0), wsa);
end;
 
function TNet.Winsock_sockTCP;
begin
  S := socket (AF_INET , SOCK_STREAM , 0); // S : tSocket;
end;

function TNet.Winsock_setoptTCP;
begin
  s_addr.sin_family :=AF_INET;         // s_addr : sockaddr_in;
  s_addr.sin_port := htons(10000);
  s_addr.sin_addr.s_addr := htonl(INADDR_ANY);
  s_addr.sin_zero:='0';
end;

function TNet.WinSock_bindTCP;
begin
  bind ( S , s_addr , sizeof(s_addr));
end;

function TNet.Winsock_listenTCP;
begin
  listen(S , SOMAXCONN);
end;

function TNet.Winsock_acceptTCP;
begin
  S_accepting:= accept(S, nil, nil); // S_accepting : tSocket; {Socket der verbindungen akzeptiert durch accept() }
end;

function TNet.Winsock_reciveTCP;
begin
  result:=recv(S_accepting, buffer, strlen(buffer),0); // buffer : PChar;
end;
Dies sind also meine Funktionsaufrufe. Natürlich bleibt der "server" bei der funktion accept hängen solange keine verbindung duch den "client" mit connect() erstellt wurde. Danch führt der "client" die bereit erwähnte send() funktion durch und der "server" soll dies "nurnoch" mit dem der oben geposteten funtion recv() auslesen. Leider geschiet dies nicht.

Hoffe jemand erkennt die Fehler in meinem Quellcode und kann mir helfen.

Basilikum 20. Jun 2006 06:38

Re: Winsock , send/recv, wie?
 
Zitat:

Zitat von xxl1
Dies sind also meine Funktionsaufrufe. Natürlich bleibt der "server" bei der funktion accept hängen solange keine verbindung duch den "client" mit connect() erstellt wurde. Danch führt der "client" die bereit erwähnte send() funktion durch und der "server" soll dies "nurnoch" mit dem der oben geposteten funtion recv() auslesen. Leider geschiet dies nicht.

versuch es mal mit folgender Receive-Function:
Delphi-Quellcode:
function TNet.Winsock_reciveTCP;
Var
  Buffer : String;
  R : Integer;
begin
  SetLength(Buffer,1024);
  R:=recv(S_accepting, buffer[1], Length(buffer),0);
  If (R < 0) Then --fehler--

  SetLength(Buffer,R); // Empfangene Daten stehen nun im Buffer (String)
  OutputDebugString(PChar(Buffer)); // Sichtbar im Eventlog - Ctrl-Alt-V
end;

Nogge 20. Jun 2006 08:54

Re: Winsock , send/recv, wie?
 
accept reagiert auf
- Connecten eines neuen Clients
- Empfangen von Daten durch einen verbundenen Client (= Buffer hat neuen Inhalt)
d.h. wenn sich ein Client mit deinem Server verbunden hat, wurde der accept-Befehl einmal erfolgreich abgearbeitet. Somit musst du diesen in eine Schleife schreiben, damit nach dem Verbinden eines neuen Clients Daten von diesem empfangen werden können.

xxl1 20. Jun 2006 16:03

Re: Winsock , send/recv, wie?
 
Hi,

ERSTMAL ein dickes DANKE an Basilikum ,da ich jetzt schonmal strings übertragen kann!

Nogge , mir war klar das ich die accept() funktion in eine schleife einbauen muss ,aber es ging ja darum wie man send() ,recv() benutzt. Trotzdem danke.

Basilikum 20. Jun 2006 18:55

Re: Winsock , send/recv, wie?
 
Zitat:

Zitat von Nogge
accept reagiert auf
- Empfangen von Daten durch einen verbundenen Client (= Buffer hat neuen Inhalt)

also das wäre mir absolut neu... verwechselst du allenfalls select() mit accept() ?

Nogge 21. Jun 2006 00:45

Re: Winsock , send/recv, wie?
 
Jo, war ne Verwechslung - sorry.

xxl1 21. Jun 2006 15:58

Re: Winsock , send/recv, wie?
 
Ok ,dan nwar mir das doch nich so klar mit accept(), :-)
---
aber zu was anderem : man kann doch sicher records mit send()/recv() übertragen oder?
wenn ja, wie geht das, oder anders: wie bekommt man die länge des records mit daten und namen?

Nogge 21. Jun 2006 17:16

Re: Winsock , send/recv, wie?
 
Die Byte-Länge eines Records kann man mithilfe von SizeOf() bestimmen. Dein Code müsste also ungefähr so aussehen:
Delphi-Quellcode:
WinSock.send(FAccSock, ARecord, SizeOf(ARecord), 0);

xxl1 19. Apr 2007 18:37

Re: Winsock , send/recv, wie?
 
Hab das Programm mal wieder aufgegriffen und wollte weitermachen...

das Problem mit den Records besteht leider immernoch.

Das Record enthält erstmal eine Integer Variable und einen String.

Dies wird nun versendet. Es kommt leider nur der Integer an ,der string ist nach dem empfangen leer.
Die länge des Records wird wie von Nogge beschreiben mit SizeOf() bestimmt.

Nogge 19. Apr 2007 22:21

Re: Winsock , send/recv, wie?
 
Dein Problem liegt an SizeOf(): Ein Integer ist ein primitiver Datentyp, d.h. er stellt keine Referenz auf ein anderes Objekt dar. Er belegt auf einer 32-bit Architektur 4 Byte. Ein String ist jedoch kein solch ein primitiver Datentyp. Du kannst einen String eher als eine class ansehen, die auf eine Zeichenkette zeigt, d.h. auf ein array of char (in Java ist ein String sogar genau so definiert). Eine Referenz ist also ein Pointer, d.h. auf einer 32-bit Architektur belegt er ebenfalls 4 Byte. SizeOf() bestimmt also nur die Größe des direkten Typs, nicht aber das Objekt, was hinter einer Referenz "verborgen" ist.
Du kannst dies wunderbar an einem Beispiel testen:
Delphi-Quellcode:
type
  TData = record
    int : Integer;
    s  : String;
  end;
[...]
var
  d: TData;
begin
  d.s := 'ebhfgoaehfab'; // Größe des Strings wirkt sich nicht auf die Größe des records aus
  ShowMsg(SizeOf(d)); // z.B. MessageBox() o.Ä.
end;
Egal wie viele Zeichen Du dem String zuweist, es wird immer 8 Byte ausgegeben.
Mein Vorschlag:
Du musst die Länge aller nicht-primitiven Typen selbst zu der Größe des records addieren.

Jute Nacht, Nogge

xxl1 20. Apr 2007 09:38

Re: Winsock , send/recv, wie?
 
ich dank dir schonmal für den tipp!

hab die berechnung des Records nun selbst übernommen, diese stimmt nach rechnung per hand (^^) auch! Die Datenmenge wird übertragen ,jedoch wird immernoch nichts in den string geschreiben... muss ich diesen mit setlength() auf die länge des strings bringen, bevor ich die daten dann schreiben kann? Dies wäre jedoch sehr seltsam ,da man dies ja bei lokalen zuweisungen von strings nicht tun muss...

xxl1 20. Apr 2007 09:48

Re: Winsock , send/recv, wie?
 
so ich poste mal die ganze unit ,vllt hilfts ja

Delphi-Quellcode:
unit Winsock_TCP_S_C;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, buffer_record , WinSock;

type net_structure = record

  S : tSocket;
  S_server_accepting : tSocket;

  s_port : u_short;
  c_port : u_short;

  s_addr : sockaddr_in;            
  c_addr : sockaddr_in;

  buffer_rcv : buffer;
  buffer_snd : buffer;

  server_address_string : PChar;
  client_address_string : PChar;
 
  Error : DWORD;



  data_send: integer;
  data_recived : integer;
end;


type TNet = class(TObject)

  private
//<---------------------------------------------------------------------------->
  net_s_client : net_structure;
  net_s_server : net_structure;

//<---------------------------------------------------------------------------->


  function WinSock_bind_server_socket_TCP :boolean;
  function Winsock_setopt_TCP(is_server: boolean) :boolean;
  function WinSock_startup(is_server: boolean) :boolean;
  function Winsock_openTCP(is_server: boolean) :boolean;
  function Winsock_accept_server_socket_TCP :boolean;
  function Winsock_listen_server_socket_TCP :boolean;

  function Winsock_ioctlsocket(sock:tSocket;argp:u_long;is_server:boolean) : boolean;

  function Winsock_client_connectTCP : boolean;
  function Winsock_reciveTCP(is_server: boolean) :integer;
  function Winsock_sendTCP(is_server: boolean) : integer;
  function Winsock_closeTCP(is_server: boolean) :boolean;
  function Winsock_cleanup(is_server: boolean) : boolean;

  function transfer_length(Data_to_compute:buffer):integer;

  public
//<---------------------------------------------------------------------------->

//<---------------------------------------------------------------------------->
  constructor create;
  function StartNetwork(is_server: boolean) : boolean;
  function StopNetwork(is_server: boolean) : boolean;
  function Winsock_load(is_server: boolean) : boolean;
  function Winsock_unload(is_server: boolean) : boolean;
  function Server_Change_Port(new_port: u_short) :boolean;
  function Server_Listen : boolean;
  function Server_Accepting : boolean;
  function Server_NonBlocking: Boolean;
  function Client_NonBlocking: Boolean;
  function Client_Fill_ServerAddrPort(server_addr:PChar; server_port: u_short) :boolean;
  function Client_ConnectToServer : boolean;
  function FillBufferToSend(is_server : boolean ;BufferToSend: buffer): boolean;
  function GetRecivedBuffer(is_server : boolean):buffer;
  function Recive(is_server : boolean) : integer;
  function Snd(is_server : boolean) : integer;
  function GetSocketError(is_server : boolean):DWORD;
  function GetServerPort(is_server : boolean) : u_short;
  function GetClientPort(is_server : boolean) : u_short;
  function GetServerIP (is_server : boolean) : PChar;
  function GetClientIP (is_server : boolean) : PChar;
 

  protected
//<---------------------------------------------------------------------------->


//<---------------------------------------------------------------------------->
end;



implementation


//<---------------------------------------------------------------------------->
//  TNet: private
//<---------------------------------------------------------------------------->


function TNet.WinSock_startup(is_server:boolean):boolean;
var wsa: TWSAData;
    c : integer;
begin
  if is_server = true then
    begin
     c:= WSAStartup(MAKEWORD(2, 2), wsa);
      if c <> 0 then
        begin
          net_s_server.Error:= WSAGetLastError;
          result :=false;
        end
    else result:=true;
  end
  else
    begin
     c:= WSAStartup(MAKEWORD(2, 2), wsa);
      if c <> 0 then
        begin
          net_s_client.Error:= WSAGetLastError;
          result:= false;
        end
      else result:= true;
    end
end;


function TNet.Winsock_openTCP(is_server: boolean):boolean;
begin
 if is_server = true then
   begin
     net_s_server.S:= socket (AF_INET {TCP/UDP INTERNETWORK Protokolle}, SOCK_STREAM {SOCK_STREM: Voraussetzung für TCP}, 0{TCP});
     if net_s_server.S = INVALID_SOCKET then
       begin
         net_s_server.Error:= WSAGetLastError;
         result :=false;
       end
     else result := true;
   end
 else
   begin
   net_s_client.S := socket (AF_INET {TCP/UDP INTERNETWORK Protokolle},
    SOCK_STREAM {SOCK_STREM: Voraussetzung für TCP}, 0{TCP});
   if net_s_client.S = INVALID_SOCKET then
     begin
       net_s_client.Error:= WSAGetLastError;
       result :=false;
     end
   else result := true;
   end
end;


function TNet.Winsock_setopt_TCP(is_server: boolean):boolean;
begin
  if is_server = true then
    begin
      result := true;
      try
        net_s_server.s_addr.sin_family := AF_INET;
        net_s_server.s_addr.sin_port := htons(net_s_server.s_port);
        net_s_server.s_addr.sin_addr.S_addr := htonl(INADDR_ANY);
        net_s_server.s_addr.sin_zero:='0';
      except
        begin
          result:= false;
        end
      end

    end
  else
    begin
      result:= true;
      try
        net_s_client.c_addr.sin_family := AF_INET;
        net_s_client.c_addr.sin_addr.S_addr:= htonl(INADDR_ANY);
        net_s_client.c_addr.sin_zero:='0';
      except
        begin
          result:=false;
        end
      end
    end
end;


function TNet.WinSock_bind_server_socket_TCP:boolean;
var c : integer;
begin
  c:= bind (net_s_server.S , net_s_server.s_addr , sizeof(net_s_server.s_addr));
  if c <> 0 then
    begin
      net_s_server.Error:=WSAGetLastError;
      result := false;
    end
  else result := true;
end;


function TNet.Winsock_listen_server_socket_TCP:boolean;
var c : integer;
begin
  c:= listen(net_s_server.S , SOMAXCONN);
  if c <> 0 then
    begin
      net_s_server.Error:=WSAGetLastError;
      result:= false;
    end
  else result := true;
end;

function TNet.Winsock_client_connectTCP:boolean;
var c: integer;
begin
  net_s_client.s_addr.sin_family := AF_INET;
  net_s_client.s_addr.sin_port := htons(net_s_client.s_port);
  net_s_client.s_addr.sin_addr.S_addr:= inet_addr(net_s_client.server_address_string);
  c:= connect(net_s_client.S, net_s_client.s_addr, sizeof(net_s_client.s_addr));
  if c <> 0 then
    begin
      net_s_client.Error:=WSAGetLastError;
      result:= false;
    end
  else result := true;
end;

function TNet.Winsock_accept_server_socket_TCP:boolean;
begin
  net_s_server.S_server_accepting:= accept(net_s_server.S, nil , nil);
  if net_s_server.S_server_accepting = INVALID_SOCKET then
    begin
      net_s_server.Error:=WSAGetLastError;
      result:= false;
    end
  else result:= true;
end;

function TNet.Winsock_reciveTCP(is_server: boolean) :integer;
begin
  if is_server = true then
    begin
      net_s_server.data_recived:= recv( net_s_server.S_server_accepting ,
       net_s_server.buffer_rcv , transfer_length(net_s_server.buffer_rcv) , 0);
      if net_s_server.data_recived > 0 then
        begin
          result:=net_s_server.data_recived;
        end
      else if net_s_server.data_recived <= 0 then
        begin
          net_s_server.Error:=WSAGetLastError;
          result:= -1 ;
        end
      end
  else
    begin
       net_s_client.data_recived:= recv( net_s_client.s ,
       net_s_client.buffer_rcv , transfer_length(net_s_client.buffer_rcv) , 0);
      if net_s_client.data_recived > 0 then
        begin
          result:=net_s_client.data_recived;
        end
      else if net_s_client.data_recived <= 0 then
        begin
          net_s_client.Error:=WSAGetLastError;
          result:= -1 ;
        end
      end
end;


function TNet.Winsock_sendTCP(is_server: boolean) : integer;
begin
  if is_server = true then
    begin

      net_s_server.data_send:= send(net_s_server.S_server_accepting,
       net_s_server.buffer_snd, transfer_length(net_s_server.buffer_snd) , 0 );

      if net_s_server.data_send > 0 then
        begin
          result:=net_s_server.data_send;
        end
      else if net_s_server.data_send <= 0 then
        begin
          net_s_server.Error:= WSAGetLastError;
          result:= -1 ;
        end
      end
    else
      begin
        net_s_client.data_send:= send( net_s_client.S ,
         net_s_client.buffer_snd , transfer_length(net_s_client.buffer_snd) , 0 );
        if net_s_client.data_send > 0 then
          begin
            result:= net_s_client.data_send;
          end
        else if net_s_server.data_send <= 0 then
          begin
            net_s_server.Error:= WSAGetLastError;
            result:= -1 ;
          end
        end
end;


function TNet.Winsock_closeTCP(is_server: boolean):boolean;
var c,d : integer;
begin
  if is_server = true then
    begin
      c := closesocket( net_s_server.S_server_accepting );
      d := closesocket( net_s_server.S );
      if c <> -1 then
        begin
          net_s_server.Error:=WSAGetLastError;
          result := false;
        end
      else if d <> 0 then
        begin
          net_s_server.Error:=WSAGetLastError;
          result := false;
        end
      else result := true;
    end
  else
    c := closesocket ( net_s_client.S );
      if c <> -1 then
        begin
          net_s_client.Error:=WSAGetLastError;
          result:= false;
        end
      else result := true;
end;


function TNet.Winsock_cleanup(is_server: boolean) : boolean;
var c : integer;
begin
  if is_server = true then
    begin
      c:=WSACleanup;
      if c <> 0 then
        begin
          net_s_server.Error:= WSAGetLastError;
          result := false;
        end
      else
        begin
          c:=WSACleanup;
          if c <> 0 then
            begin
              net_s_client.Error:= WSAGetLastError;
              result:= false;
            end
          else result := true;
        end
      end
end;


function TNet.Winsock_ioctlsocket(sock:tSocket;argp:u_long;is_server:boolean) : boolean;
var c : integer;
begin
  if is_server = true then
    begin
      c:=ioctlsocket(sock,FIONBIO,argp);
      if c <> 0 then
        begin
          net_s_server.Error:= WSAGetLastError;
          result := false;
        end
      else
        begin
          c:=ioctlsocket(sock,FIONBIO,argp);
          if c <> 0 then
            begin
              net_s_client.Error:= WSAGetLastError;
              result:= false;
            end
          else result := true;
        end
      end
end;

function Tnet.transfer_length(Data_to_compute:buffer):integer;
  var length_off:integer;
  begin
    length_off:=sizeof(data_to_compute.proto_cmd);
    length_off:=length_off+length(data_to_compute.str);
    result:=length_off;
  end;
//<---------------------------------------------------------------------------->


//<---------------------------------------------------------------------------->
//  TNet: public
//<---------------------------------------------------------------------------->


constructor TNet.create;
begin
  inherited create;
  net_s_client.s_port:=10000;
  net_s_client.c_port:=10000;
  net_s_client.server_address_string:='127.0.0.1';
  net_s_client.client_address_string:='127.0.0.1';
  net_s_server.s_port:=10000;
  net_s_client.c_port:=10000;
  net_s_server.server_address_string:='127.0.0.1';
  net_s_server.client_address_string:='127.0.0.1';
end;


function TNet.Winsock_load(is_server : boolean): boolean;
begin
  result := Winsock_startup(is_server);
end;


function TNet.Winsock_unload(is_server : boolean): boolean;
begin
  result := Winsock_cleanup(is_server);
end;

function TNet.StartNetwork(is_server: boolean): boolean;
begin

  if Winsock_openTCP(is_server) = true then
  if Winsock_setopt_TCP(is_server) = true then
    begin
      if is_server = true then
      if WinSock_bind_server_socket_TCP = true then result := true;
    end
  else result:= true;
end;


function TNet.StopNetwork(is_server:boolean):boolean;
begin
  result := Winsock_closeTCP(is_server);
end;

function TNet.Server_Change_Port(new_port: u_short):boolean;
var t : boolean;
begin
  t:= false;
  if StopNetwork(true) = true then
    begin
      t:= true;
      try
        net_s_server.s_port := new_port;
      except t:= false;
      end
    end;
  if t = true then
    begin
      result:= StartNetwork(true)
    end
  else result := false;
end;


function TNet.Server_Listen: boolean;
begin
  Winsock_listen_server_socket_TCP;
  result := Winsock_listen_server_socket_TCP;
end;


function TNet.Server_Accepting: boolean;
begin
  result:= Winsock_accept_server_socket_TCP;
end;



function TNet.Client_Fill_ServerAddrPort(server_addr : PChar; server_port: u_short):boolean;
begin
  result:= true;
  try
    net_s_client.server_address_string := server_addr;
    net_s_client.s_port := server_port;
  except result := false;
  end;

end;


function TNet.Client_ConnectToServer:boolean;
begin
  result := Winsock_client_connectTCP;
end;


function TNet.FillBufferToSend(is_server : boolean ; BufferToSend: buffer): boolean;
begin
  if is_server = true then
    begin
      result:= true;
      try
        net_s_server.buffer_snd := BufferToSend;
      except result := false;
      end
    end
  else
   begin
     result:=true;
     try
       net_s_client.buffer_snd := BufferToSend;
     except result := false;
     end
   end
end;


function TNet.GetRecivedBuffer(is_server : boolean):buffer;
begin
  if is_server = true then
    begin
      result := net_s_server.buffer_rcv;
    end
  else
    begin
      result := net_s_client.buffer_rcv;
    end
end;


function TNet.Recive(is_server : boolean) : integer;
begin
  result:=Winsock_reciveTCP(is_server);
end;


function TNet.Snd(is_server : boolean) : integer;
begin
  result:=Winsock_sendTCP(is_server);
end;


function TNet.GetSocketError(is_server : boolean):DWORD;
begin
  if is_server = true then
    begin
      result:=net_s_server.Error;
    end
  else
    begin
      result:=net_s_client.Error;
    end
end;


function TNet.GetServerPort(is_server : boolean): u_short;
begin
  if is_server = true then
    begin
      result := ntohs(net_s_server.s_addr.sin_port);
    end
  else
    begin
      result := ntohs(net_s_client.s_addr.sin_port);
    end
end;


function TNet.GetClientPort(is_server : boolean): u_short;
begin
  if is_server = true then
    begin
      result := ntohs(net_s_server.c_addr.sin_port);
    end
  else
    begin
      result := ntohs(net_s_client.c_addr.sin_port);
    end
end;

function TNet.GetServerIP(is_server : boolean) : PChar;
begin
 if is_server = true then
   begin
     result:=net_s_server.server_address_string;
   end
 else
   begin
     result:=net_s_client.server_address_string;
   end
end;

function TNet.GetClientIP(is_server: boolean): PChar;
begin
  if is_server = true then
    begin
      result:=net_s_server.server_address_string;
    end
  else
    begin
      result:=net_s_client.client_address_string;
    end
end;

function TNet.Server_NonBlocking: Boolean;
var argp: u_long;
begin
  argp:=1;
  result:=Winsock_ioctlsocket(net_s_server.S_server_accepting,argp,true);
end;

function TNet.Client_NonBlocking: Boolean;
var argp: u_long;
begin
  argp:=1;
  result:=Winsock_ioctlsocket(net_s_client.S,argp,true);
end;

//<---------------------------------------------------------------------------->
end.
Delphi-Quellcode:
unit buffer_record;

interface



type buffer = record
   proto_cmd : integer;
   str : string;
end;

implementation

end.
(ja ich weiss der quelltext ist redundant und könnte viel kürzer sein :-))

hoffe jemand findet einen fehler :-)

shmia 20. Apr 2007 15:18

Re: Winsock , send/recv, wie?
 
Wieso entwickelst du deine eigene Kapselung für WinSock????
Man muss doch das Rad nicht neu erfinden.
Sockets und WinSock sind kompliziert und sehr low-level orientiert.
Man sollte das Ganze in einer oder mehreren Klassen kapseln oder man verzettelt sich
beim direkten Aufruf ohne Ende.
Fehlersuche beim Netzwerkverkehr ist sehr schwierig; also sollte man auf einem ganz festen Fundament stehen.

Das gäbe es z.B. Indy. Vielen Programmierern ist dieses Paket zu umfangreich. Für kleine Anwendungen wäre das overkill.
Dann gäbe es noch die Unit ScktComp. Damit kann man recht gut TCP-Verbindungen aufbauen. Leider ist UDP damit nicht möglich.
Weitere Komponenten gibt es hier: http://www.torry.net/pages.php?id=220

Nogge 20. Apr 2007 16:05

Re: Winsock , send/recv, wie?
 
Vllt möchte xxl1 ja einfach auf dieser Ebene arbeiten, um diese besser kennenzulernen oder performance-orientiert zu programmieren.
Zum Problem:
Delphi-Quellcode:
net_s_server.data_recived:= recv( net_s_server.S_server_accepting ,
       net_s_server.buffer_rcv , transfer_length(net_s_server.buffer_rcv) , 0);
=> Hier bestimmst Du die Länge des allgemeinen Record-Typs, nicht aber die des gefüllten. Da die Länge des empfangenden Puffers beim Empfang unbekannt ist, kannst Du so nicht weiterarbeiten. Beim Empfang von nicht-primitiven Typen musste daher ein statisches array deklarieren, das die Länge der max. Eingabe hat.
Mein Vorschlag:
Du veränderst den string-Typ aus Deinem record in ein array[0..x] of char/byte. So kannste dann beim Empfang auch ganz einfach mit SizeOf() die statische Länge des Records angeben, da es jetzt ja keine dynamischen, d.h. nicht-primitiven Datentypen mehr gibt. Die Länge des tatsächlichen Strings bzw. array of char kannste ja einfach mit Length() bestimmen, da diese Funktion nach dem Null-Byte sucht, d.h. dem standardisiertem Ende eines Strings und daraus die Länge ermittelt. Wenn du andere nicht-primitive Datentypen versenden möchtest, würde ich an Deiner Stelle eine zweite Integer-Variable in deinem Record deklarieren, die die tatsächliche Länge des Datentyps beinhaltet.

Gruß Nogge

xxl1 20. Apr 2007 18:11

Re: Winsock , send/recv, wie?
 
danke für die schnellen antworten nogge!

werd das mal ausprobieren


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:52 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz