[Abstract] Programmers who have written Winsock applications know that writing Winsock applications is by no means an easy task. You must not directly deal with the complex APIs in Winsock. Fortunately, Tclientsocket and Tserversocket in Delphi4 encapsulate The relevant APIs in Windows greatly simplify access to Winsock, allowing us to write Winsock applications very easily. This article introduces how to write Winsock applications using Delphi through an example of reading the screen of another computer in the LAN.
Anyone who has worked as a network administrator in a workplace may have had this experience. How annoying it is to instruct others to operate by "remote control" over the phone. Moreover, I am a lazy person and don't want to run from the top of the building to the downstairs for trivial matters every day. , what to do? How about writing a program that reads the screen of another computer? It’s much more intuitive. To communicate within a LAN, the best choice is of course to use Winsock. Programmers who have written Winsock applications know that writing Winsock applications is by no means an easy task. You must not directly deal with the complex APIs in Winsock. Fortunately, Tclientsocket and Tserversocket in Delphi4 encapsulate the relevant APIs in Windows, which greatly simplifies access to Winsock and allows us to write Winsock applications very easily. Nevertheless, it is best to have some understanding of Winsock. I will not go into details here. You can find some books and read it yourself.
To transmit data through the network, you need at least a pair of Sockets, one on the client and the other on the server. Once the client and the server's socket establish a connection, they can communicate with each other. The connection established with Socket is established on Tcp/ Based on ip, it also supports ipx/spx and other related protocols. In Delphi, Tclientsocket and Tserversocket are used to control the connection and communication between the client and the server Socket. It should be noted that these two components are used to manage the connection between the server and the client. They are not Socket objects themselves. The Socket objects are manipulated by TcustomwinSocket, such as Tclientwinsocket, Tserverclientwinsocket, and Tserverwinsocket.
1. Tclientsocket component:
By adding a Tclientsocket to the Form, the application becomes a Tcp/ip client, and Tclientsocket can be used to manipulate the client's Socket object.
To establish a connection to a server, you first specify the server to which you want to connect. There are two ways to specify the server. One is to set the Host attribute to specify the host name of the server, such as http://www.inPRise.com or the machine name in the LAN. This method is intuitive, but it requires domain name resolution, which will be slightly faster. Slower; another method is to set the Adress attribute to specify the IP address of the host, such as 130.0.1.1. The two methods are equivalent, but if both Host and Adress are set, Delphi will only use the Host property.
Then you need to specify the port number to connect to the server. There are two ways here. One is to set the Service to use the default port number. The other is to directly set the Port port number. Among the port numbers below 1024, many have been allocated, such as FTP. The ports are 20 and 21, the SMTP port is 25, the WEB server port is 80, etc. In order to prevent unintentional conflicts, it is recommended that when programming your own application, it is best to set the Port to 1024 or above. If Service and port are set at the same time, Delphi will use the default port of Service.
After specifying the server and port number, call the open method or set the Active attribute to True. The client's Socket will make a connection request to the server's Socket. If the server is in the listening state at this time, it will automatically accept the request to establish a connection. When connected, its Onconnet event is triggered. When you need to disconnect, you only need to call the close method or set the Active attribute to False. At this time, the ondisconnet event will be triggered.
2. Tserversocket component:
Like Tclientsocket, to build a server, you only need to place a Tserversock component in the Form.
The server-side socket object is more complicated to manage. When the server is in the listening state, the server's socket object is manipulated by Tserversocket; when the client makes a request, the server responds to the request and establishes a connection. At this time, Tserverclientwinsocket is used to manipulate the connection between the server Socket and the client's Socket.
To put the server in the listening state, you must first specify the port number. Of course, it should be the same as the client's port number. Then call the open method or set the Active property to True.
3. Communication:
Once the connection between the client and the server is established, communication with each other can begin. Delphi provides several communication methods for Tserversocket and Tclientsocket. Sendtext is used to send text information, sendstream is used to send streams, and SendBuf is used to send data of specified length.
It should be noted that since the default buffer size of Windows is 4K, when sending information longer than 4K, for example, a binary stream sent from the server to the client, you only need to use Socket.SendStream() on the server. , but it is different on the client. It will trigger the onread event multiple times, and Delphi does not define events such as "onreadend". Therefore, the programmer must assemble the data himself when receiving. The method adopted in this article is to first send the stream length to the client, and then send the stream. The client writes the received data into a stream. When the stream length is equal to the length sent back by the server, it indicates that the client has completed receiving it. . For the server, the stream used as the sendstream parameter will be "owned" by the Socket. When the Socket object ends, it will also end. Do not release it yourself, otherwise, an exception will be triggered.
Likewise, when the text sent is less than 4K, for example when making the following call in the client program
clientsocket1.Socket.SendText('gets');
clientsocket1.Socket.SendText('gets');
clientsocket1.Socket.SendText('gets');
When the server receives, phenomena such as getsgets will appear. This may be because when the data in the buffer has not been sent yet, new text is put into the buffer, and the computer treats it as the same batch of data for processing. . In order to avoid this phenomenon from happening, you can use the method of "throwing the ball" back and forth in the program:
client server
clientsocket1.Socket.SendText('data1') socket.ReceiveText;
socket.sendtext('ok');
socket.receivetext;
clientsocket1.Socket.SendText('data2')
socket.ReceiveText;
socket.sendtext('end');
socket.receivetext;
After running the server program on another computer, enter the computer name in the text box on your client program, click "Connect", and click "Get Picture". You will have a clear view of the screen of the other party's computer. The following is the entire source code of the program. This program can run in NT4.0, Win95, Win98, and LAN. Of course, Windows must have the TCP/IP protocol installed, and it must have a dynamically assigned or specified IP address.
If you find it troublesome to "command" while watching, you can also analyze the keyboard and mouse events on image1, and then send them to the server. After the server receives it, it will perform the same operation again, so that you don't have to worry. Operator. Using Delphi's Tclientsocket and Tserversocket, you can also complete the development of applications such as file copying, online chat, ICQ, etc. It is very simple to implement. You can freely use your imagination to write more attractive programs.
Client program:
unit cmain;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ScktComp, StdCtrls, ExtCtrls,jpeg;
type
TForm1 = class(TForm)
Panel1: TPanel;
ScrollBox1: TScrollBox;
Image1: 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);
private
{Private declarations}
public
{Public declarations}
end;
var
Form1: TForm1;
c:longint;
m:tmemorystream;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
try
clientsocket1.Close;
clientsocket1.Host:=edit1.text;
clientsocket1.Open; //Connect to the server
except
showmessage(edit1.text+#13#10+'The computer is not powered on or the service program is not installed');
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
clientsocket1.Socket.SendText('gets'); //Send a request to notify the server that a screen image is needed
end;
procedure TForm1.ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
begin
caption:='Connect to'+edit1.text;
end;
procedure TForm1.ClientSocket1Error(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
varErrorCode: Integer);
begin
caption:='Connection'+edit1.text+'Failed';
showmessage(edit1.text+#13#10+'The computer is not powered on or the service program is not installed');
errorcode:=0;
end;
procedure TForm1.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var
buffer:array [0..10000] of byte; //Set the receive buffer
len:integer;
ll:string;
b:tbitmap;
j:tjpegimage;
begin
if c=0 then //C is the number of bytes sent by the server. If it is 0, it means that image reception has not yet started.
begin
ll:=socket.ReceiveText;
c:=strtoint(ll); //Set the number of bytes to be received
clientsocket1.Socket.SendText('okok'); //Notify the server to start sending images
end else
begin //The following is the image data receiving part
len:=socket.ReceiveLength; //Read the packet length
socket.ReceiveBuf(buffer,len); //Receive the data packet and read it into the buffer
m.Write(buffer,len); //Append to stream M
if m.Size>=c then //If the stream length is greater than the number of bytes to be received, the reception is completed
begin
m.Position:=0;
b:=tbitmap.Create;
j:=tjpegimage.Create;
try
j.LoadFromStream(m); //Read the data in stream M into JPG image object J
b.Assign(j); //Convert JPG to BMP
Image1.Picture.Bitmap.Assign(b); //Assign to image1 component
finally //The following is the cleanup work
b.free;
j.free;
clientsocket1.Active:=false;
clientsocket1.Active:=true;
m.Clear;
c:=0;
end;
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
m:=tmemorystream.Create;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
m.free;
ClientSocket1.Close;
end;
end.
Server program:
unit smain;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ScktComp,jpeg;
type
TForm1 = class(TForm)
ServerSocket1: TServerSocket;
procedure ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure FormCreate(Sender: TObject);
private
{Private declarations}
public
{Public declarations}
end;
var
Form1: TForm1;
m1:tmemorystream;
implementation
{$R *.DFM}
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
s,s1:string;
desk:tcanvas;
bitmap:tbitmap;
jpg:tjpegimage;
begin
s:=socket.ReceiveText;
if s='gets' then //The client issues a request
begin
bitmap:=tbitmap.Create;
jpg:=tjpegimage.Create;
desk:=tcanvas.Create; //The following code is to obtain the current screen image
desk.Handle:=getdc(hwnd_desktop);
m1:=tmemorystream.Create; //Initialize stream m1, after sending the stream with sendstream(m1),
//It will remain until the socket conversation ends,
//Cannot be freed manually, otherwise an exception will be triggered
with bitmap do
begin
width:=screen.Width;
height:=screen.Height;
canvas.CopyRect(canvas.cliprect,desk,desk.cliprect);
end;
jpg.Assign(bitmap); //Convert the image to JPG format
jpg.SaveToStream(m1); //Write the JPG image into the stream
jpg.free;
m1.Position:=0;
s1:=inttostr(m1.size);
Socket.sendtext(s1); //Send image size
end;
if s='okok' then //The client is ready to receive images
begin
m1.Position:=0;
Socket.SendStream(m1); //Send JPG image
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
ServerSocket1.open;
end;
end.