[Zusammenfassung] Programmierer, die Winsock-Anwendungen geschrieben haben, wissen, dass das Schreiben von Winsock-Anwendungen keine leichte Aufgabe ist. Glücklicherweise vereinfachen Tclientsocket und Tserversocket in Delphi4 den Zugriff erheblich zu Winsock, wodurch wir sehr einfach Winsock-Anwendungen schreiben können. In diesem Artikel wird anhand eines Beispiels für das Lesen des Bildschirms eines anderen Computers im LAN erläutert, wie Sie Winsock-Anwendungen mit Delphi schreiben.
Jeder, der als Netzwerkadministrator an einem Arbeitsplatz gearbeitet hat, hat möglicherweise diese Erfahrung gemacht. Wie nervig es ist, andere über das Telefon mit der „Fernsteuerung“ zu beauftragen. Außerdem bin ich ein fauler Mensch und möchte nicht davonlaufen Jeden Tag für Kleinigkeiten von oben nach unten fahren, was tun? Wie wäre es, ein Programm zu schreiben, das den Bildschirm eines anderen Computers liest? Es ist viel intuitiver. Für die Kommunikation innerhalb eines lokalen Netzwerks ist die Verwendung von Winsock natürlich die beste Wahl. Programmierer, die Winsock-Anwendungen geschrieben haben, wissen, dass das Schreiben von Winsock-Anwendungen keineswegs eine einfache Aufgabe ist. Glücklicherweise müssen Sie sich nicht direkt mit den komplexen APIs befassen , Tclientsocket und Tserversocket in Delphi4 kapseln die relevanten APIs in Windows und vereinfachen so den Zugriff auf Winsock erheblich, sodass wir ganz einfach Winsock-Anwendungen schreiben können. Dennoch ist es am besten, ein gewisses Verständnis für Winsock zu haben. Ich werde hier nicht auf Details eingehen. Sie können einige Bücher finden und sie selbst lesen.
Um Daten über das Netzwerk zu übertragen, benötigen Sie mindestens ein Socket-Paar, einen auf der Client-Seite und einen auf der Server-Seite. Sobald die Sockets auf der Client- und Serverseite verbunden sind, können sie miteinander kommunizieren Socket basiert auf TCP/IP und unterstützt auch ipx/spx und andere verwandte Protokolle. In Delphi werden Tclientsocket und Tserversocket verwendet, um die Verbindung und Kommunikation zwischen dem Client und dem Server-Socket zu steuern. Es ist zu beachten, dass diese beiden Komponenten zur Verwaltung der Verbindung zwischen dem Server und dem Client verwendet werden. Sie sind selbst keine Socket-Objekte. Das Socket-Objekt wird von TcustomwinSocket gesteuert, z. B. Tclientwinsocket und Tserverwinsocket.
1. Tclientsocket-Komponente:
Durch das Hinzufügen eines Tclientsocket zum Formular wird die Anwendung zu einem Tcp/IP-Client und Tclientsocket kann zum Bearbeiten des Socket-Objekts des Clients verwendet werden.
Um eine Verbindung zu einem Server herzustellen, geben Sie zunächst den Server an, zu dem Sie eine Verbindung herstellen möchten. Es gibt zwei Möglichkeiten, den Server anzugeben. Eine besteht darin, das Host-Attribut so festzulegen, dass der Hostname des Servers angegeben wird, z. B. http://www.inPRise.com oder der Computername im LAN Es erfordert eine etwas schnellere Auflösung des Domänennamens. Eine andere Methode besteht darin, das Adressattribut so festzulegen, dass die IP-Adresse des Hosts angegeben wird, z. B. 130.0.1.1. Die beiden Methoden sind gleichwertig, aber wenn sowohl Host als auch Adresse festgelegt sind, verwendet Delphi nur die Host-Eigenschaft.
Dann müssen Sie die Portnummer angeben, um eine Verbindung zum Server herzustellen. Eine davon besteht darin, den Dienst so einzustellen, dass er die Standardportnummer verwendet. Die andere besteht darin, die Portnummer direkt festzulegen B. FTP, die Ports 20 und 21, der SMTP-Port ist 25, der WEB-Server-Port ist 80 usw. Um unbeabsichtigte Konflikte zu vermeiden, wird empfohlen, dies bei der Programmierung Ihrer eigenen Anwendung zu tun Stellen Sie den Port am besten auf 1024 oder höher ein. Wenn Service und Port gleichzeitig festgelegt sind, verwendet Delphi den Standardport von Service.
Rufen Sie nach Angabe des Servers und der Portnummer die Methode open auf oder setzen Sie das Active-Attribut auf True. Der Socket des Clients stellt eine Verbindungsanforderung an den Socket des Servers Anfrage zum Herstellen einer Verbindung. Wenn die Verbindung hergestellt ist, wird das Onconnet-Ereignis ausgelöst. Wenn Sie die Verbindung trennen müssen, müssen Sie nur die Methode close aufrufen oder das Active-Attribut auf False setzen. Zu diesem Zeitpunkt wird das Ereignis ondisconnet ausgelöst.
2. Tserversocket-Komponente:
Wie bei Tclientsocket müssen Sie zum Erstellen eines Servers nur eine Tserversock-Komponente im Formular platzieren.
Das serverseitige Socket-Objekt ist komplizierter zu verwalten. Wenn sich der Server im Überwachungsstatus befindet, wird das Socket-Objekt des Servers von Tserversocket manipuliert. Wenn der Client eine Anfrage stellt, antwortet der Server auf die Anfrage und stellt eine Verbindung her. Zu diesem Zeitpunkt wird Tserverclientwinsocket verwendet, um die Verbindung zwischen dem Server zu manipulieren Socket und der Socket des Clients.
Um den Server in den Überwachungszustand zu versetzen, müssen Sie zunächst die Portnummer angeben. Diese sollte natürlich mit der Portnummer des Clients übereinstimmen. Rufen Sie dann die Methode open auf oder setzen Sie die Active-Eigenschaft auf True.
3. Kommunikation:
Sobald die Verbindung zwischen Client und Server hergestellt ist, kann die Kommunikation untereinander beginnen. Delphi bietet mehrere Kommunikationsmethoden für Tserversocket und Tclientsocket wird zum Senden von Textinformationen verwendet, sendstream wird zum Senden von Streams verwendet und SendBuf wird zum Senden von Daten einer bestimmten Länge verwendet.
Da die Standardpuffergröße von Windows 4 KB beträgt, ist zu beachten, dass Sie beim Senden von Informationen, die länger als 4 KB sind, z. B. ein vom Server an den Client gesendeter Binärstream, nur Socket.SendStream() auf dem Server verwenden müssen. , aber auf dem Client ist es anders. Es löst das Onread-Ereignis mehrmals aus und Delphi definiert keine Ereignisse wie „onreadend“. Daher muss der Programmierer die Daten beim Empfang selbst zusammenstellen. Die in diesem Artikel verwendete Methode besteht darin, zuerst die Stream-Länge an den Client zu senden und dann den Stream in einen Stream zu schreiben, wenn die Stream-Länge der vom Server zurückgesendeten Länge entspricht dass der Kunde den Erhalt abgeschlossen hat. Für den Server ist der als Sendstream-Parameter verwendete Stream Eigentum des Sockets. Wenn das Socket-Objekt endet, wird es auch nicht selbst freigegeben, da sonst eine Ausnahme ausgelöst wird.
Ebenso, wenn der gesendete Text kleiner als 4K ist, beispielsweise beim folgenden Aufruf im Client-Programm
clientocket1.Socket.SendText('gets');
clientocket1.Socket.SendText('gets');
clientocket1.Socket.SendText('gets');
Wenn der Server empfängt, treten Phänomene wie getsgets auf. Dies kann daran liegen, dass neuer Text in den Puffer eingefügt wird und der Computer ihn als denselben Datenstapel zur Verarbeitung behandelt. . Um dieses Phänomen zu vermeiden, können Sie im Programm die Methode „Ball hin und her werfen“ verwenden:
Client-Server
clientocket1.Socket.SendText('data1') socket.ReceiveText;
socket.sendtext('ok');
socket.receivetext;
clientocket1.Socket.SendText('data2')
socket.ReceiveText;
socket.sendtext('end');
socket.receivetext;
Nachdem Sie das Serverprogramm auf einem anderen Computer ausgeführt haben, geben Sie den Computernamen in das Textfeld Ihres Clientprogramms ein, klicken Sie auf „Verbinden“ und klicken Sie auf „Bild abrufen“. Sie haben eine klare Sicht auf den Bildschirm des Computers der anderen Partei. Das Folgende ist der gesamte Quellcode des Programms. Dieses Programm kann unter NT4.0, Win95, Win98 und LAN ausgeführt werden. Natürlich muss Windows das TCP/IP-Protokoll installiert haben und eine dynamisch zugewiesene oder angegebene IP haben Adresse.
Wenn es für Sie schwierig ist, beim Ansehen „Befehle“ zu geben, können Sie auch die Tastatur- und Mausereignisse auf Bild 1 analysieren und sie dann an den Server senden Ich muss mir keine Sorgen machen. Mit Tclientsocket und Tserversocket von Delphi können Sie auch die Entwicklung von Anwendungen wie Dateikopie, Online-Chat, ICQ usw. abschließen. Die Implementierung ist sehr einfach. Sie können Ihrer Fantasie freien Lauf lassen, um attraktivere Programme zu schreiben.
Kundenprogramm:
Einheit cmain;
Schnittstelle
verwendet
Windows, Nachrichten, SysUtils, Klassen, Grafiken, Steuerelemente, Formulare, Dialoge,
ScktComp, StdCtrls, ExtCtrls,jpeg;
Typ
TForm1 = Klasse(TForm)
Panel1: TPanel;
ScrollBox1: TScrollBox;
Bild1: TImage;
Button1: TButton;
Edit1: TEdit;
Button2: TButton;
ClientSocket1: TClientSocket;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
Privat
{Private Erklärungen}
öffentlich
{Öffentliche Erklärungen}
Ende;
var
Form1: TForm1;
c:longint;
m:tmemorystream;
Durchführung
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
beginnen
versuchen
clientocket1.Close;
clientocket1.Host:=edit1.text;
clientocket1.Open; //Mit dem Server verbinden
außer
showmessage(edit1.text+#13#10+'Der Computer ist nicht eingeschaltet oder das Dienstprogramm ist nicht installiert');
Ende;
Ende;
procedure TForm1.Button2Click(Sender: TObject);
beginnen
clientocket1.Socket.SendText('gets'); //Eine Anfrage senden, um den Server darüber zu informieren, dass ein Bildschirmbild benötigt wird
Ende;
procedure TForm1.ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
beginnen
caption:='Verbinden mit'+edit1.text;
Ende;
procedure TForm1.ClientSocket1Error(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
varErrorCode: Integer);
beginnen
caption:='Verbindung'+edit1.text+'Fehlgeschlagen';
showmessage(edit1.text+#13#10+'Der Computer ist nicht eingeschaltet oder das Dienstprogramm ist nicht installiert');
Fehlercode:=0;
Ende;
procedure TForm1.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var
buffer:array [0..10000] of byte; //Setze den Empfangspuffer
len:integer;
ll:string;
b:tbitmap;
j:tjpegimage;
beginnen
Wenn c=0, dann ist //C die Anzahl der vom Server gesendeten Bytes. Wenn es 0 ist, bedeutet dies, dass der Bildempfang noch nicht begonnen hat.
beginnen
ll:=socket.ReceiveText;
c:=strtoint(ll); //Legen Sie die Anzahl der zu empfangenden Bytes fest
clientocket1.Socket.SendText('okok'); //Benachrichtigen Sie den Server, um mit dem Senden von Bildern zu beginnen
Ende sonst
begin // Das Folgende ist der Bilddaten-Empfangsteil
len:=socket.ReceiveLength; //Paketlänge lesen
socket.ReceiveBuf(buffer,len); //Empfangen Sie das Datenpaket und lesen Sie es in den Puffer
m.Write(buffer,len); //An Stream M anhängen
if m.Size>=c then //Wenn die Streamlänge größer als die Anzahl der zu empfangenden Bytes ist, ist der Empfang abgeschlossen
beginnen
m.Position:=0;
b:=tbitmap.Create;
j:=tjpegimage.Create;
versuchen
j.LoadFromStream(m); //Lesen Sie die Daten im Stream M in das JPG-Bildobjekt J
b.Assign(j); //JPG in BMP konvertieren
Image1.Picture.Bitmap.Assign(b); //Zu Bild1-Element zuweisen
endlich //Das Folgende ist die Aufräumarbeit
b.frei;
j.frei;
clientocket1.Active:=false;
clientocket1.Active:=true;
m.Klar;
c:=0;
Ende;
Ende;
Ende;
Ende;
procedure TForm1.FormCreate(Sender: TObject);
beginnen
m:=tmemorystream.Create;
Ende;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
beginnen
m.frei;
ClientSocket1.Close;
Ende;
Ende.
Serverprogramm:
Einheit smain;
Schnittstelle
verwendet
Windows, Nachrichten, SysUtils, Klassen, Grafiken, Steuerelemente, Formulare, Dialoge,
ScktComp,jpeg;
Typ
TForm1 = Klasse(TForm)
ServerSocket1: TServerSocket;
procedure ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure FormCreate(Sender: TObject);
Privat
{Private Erklärungen}
öffentlich
{Öffentliche Erklärungen}
Ende;
var
Form1: TForm1;
m1:tmemorystream;
Durchführung
{$R *.DFM}
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
s,s1:string;
Schreibtisch:tcanvas;
bitmap:tbitmap;
jpg:tjpegimage;
beginnen
s:=socket.ReceiveText;
if s='gets' then //Der Client gibt eine Anfrage aus
beginnen
bitmap:=tbitmap.Create;
jpg:=tjpegimage.Create;
schreibtisch:=tcanvas.Create; //Der folgende Code dient zum Abrufen des aktuellen Bildschirmbildes
schreibtisch.Handle:=getdc(hwnd_desktop);
m1:=tmemorystream.Create; // Stream m1 initialisieren, nachdem der Stream mit sendstream(m1) gesendet wurde,
//Es bleibt bestehen, bis die Socket-Konversation endet,
//Kann nicht manuell freigegeben werden, sonst wird eine Ausnahme ausgelöst
mit Bitmap tun
beginnen
width:=screen.Width;
height:=screen.Height;
canvas.CopyRect(canvas.cliprect,desk,desk.cliprect);
Ende;
jpg.Assign(bitmap); //Konvertieren Sie das Bild in das JPG-Format
jpg.SaveToStream(m1); //Schreibe das JPG-Bild in den Stream
jpg.free;
m1.Position:=0;
s1:=inttostr(m1.size);
Socket.sendtext(s1); //Bildgröße senden
Ende;
if s='okok' then //Der Client ist bereit, Bilder zu empfangen
beginnen
m1.Position:=0;
Socket.SendStream(m1); //JPG-Bild senden
Ende;
Ende;
procedure TForm1.FormCreate(Sender: TObject);
beginnen
ServerSocket1.open;
Ende;
Ende.