![]() |
Re: Winsock , send/recv, wie?
Zitat:
|
Re: Winsock , send/recv, wie?
Jo, war ne Verwechslung - sorry.
|
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? |
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);
|
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. |
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:
Egal wie viele Zeichen Du dem String zuweist, es wird immer 8 Byte ausgegeben.
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; Mein Vorschlag: Du musst die Länge aller nicht-primitiven Typen selbst zu der Größe des records addieren. Jute Nacht, Nogge |
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... |
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:
(ja ich weiss der quelltext ist redundant und könnte viel kürzer sein :-))
unit buffer_record;
interface type buffer = record proto_cmd : integer; str : string; end; implementation end. hoffe jemand findet einen fehler :-) |
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: ![]() |
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:
=> 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.
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); 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 |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:19 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz