The client and server have been connected through sockets, but how does one transmit files from the server to the client?Use stream or sendtext;
Use Delphi to write a point-to-point File Transfer Program (1)
Abstr:
Delphi has powerful functions. Using Delphi to write software can greatly shorten the software development cycle. This article describes how to use Delphi to compile point-to-point file transfer programs. Delphi has powerful functions. Using Delphi to write software can greatly shorten the software development cycle. The basic idea of transferring files from point to point is a server software, a client software, using the same port. After the connection is established, the client sends a request to the server, including the file name and size of the file to be uploaded. If the Server accepts the file, the file will be uploaded. Of course, there are two modes for file transmission: ASCII code and bin, but General bin can be used. Based on the above discussion, the nmstrm and nmstrmserv controls of delphi4 can be used, but I have tested them. The nmstrm control can be used for small files and is very convenient, however, if the file is large (1 MB), an error occurs. Therefore, we will use tserversocket and tclientsocket in Delphi to write this program due to the size limit of the Ethernet package and the Processing Mechanism of delphisocket (in Delphi, when you use a socket to send a large stream, the receiver will trigger multiple onread events. Delphi only guarantees the integrity of each data in multiple onread events, instead of collecting data and returning it to the user. So don't think that you can send the file to be uploaded once in one socket, and Recv in the other. You must collect data or define your own protocol .), Therefore, we use the custom protocol method. The standard way to define the protocol is to use record end. For example:
Tmyfileprotocol = record
Ssendtype = (st_query, st_refuse, st_data, st_abort ,...);
Ilength: integer;
Bufsend: buffer;
End;
I tried this method, but it failed. I always thought that my method was correct, but the program could not be compiled, it is estimated that there is a problem with Delphi :) so I will use another method in the following sample program. The socket class has two attributes: deleetext and receivebuf. In an onread event, the two attributes can only be used once. Therefore, we can use a full variable to save whether the read text or Buf is used, that is to say, when you read text and Buf again, tmyfileprotocol is simulated.
Start Program:
This is the simplest method to explain.
Definition protocol:
Const
Mp_query = '1 ';
Mp_refuse = '2 ';
Mp_accept = '3 ';
Mp_nextwillbedata = '4 ';
Mp_data = '5 ';
Mp_abort = '6 ';
Mp_over = '7 ';
Mp_chat = '8 ';
Protocol Introduction:
First, the client sends mp_query. After the server receives the request, it sends mp_accept or mp_fefuese;
The client accepts mp_accept and sends mp_fileproperty. The server sends mp_nextwillbedata after receiving it;
The client receives the sent mp_nextwillbedata, and the server sends the received mp_data;
The client receives the mp_data, sends the data, the server receives the data, and sends the mp_nextwillbedata;
Loop until the client sends mp_over;
Mp_chat + string can be sent to each other in the middle;
Server program:
Put the following controls: savedialog1, btnstartserver,
SS, (tserversocket)
Btnstartserver. onclick (Sender: tobject );
Begin
Ss.port: = 2000;
SS. open;
End;
SS. onclientread (Sender: tobject; socket: tcustomwinsocket );
VaR
Stemp: string;
Bufrecv: pointer;
Irecvlength: integer;
Begin
If breadtext then
Begin
Stemp: = socket. receivetext;
Case stemp [1]
Mp_query: Begin
// Reject it here
Savedialog1.filename: = copy (stemp, 2, length (stemp ));
If savedialog1.execute then
Begin
Socket. sendtext (mp_accept );
Fsrecv: = tfilestream. Create (savedialog1.filename, fmcreate );
End
Else socket. sendtext (mp_refuse + 'deletable ');
End;
Mp_fileproperty: Begin
// Send strtoint (copy (stemp, 2, length (stemp) times
// Display the time progress...
Socket. sendtext (mp_nextwillbedata );
End;
Mp_nextwillbedata: Begin
Socket. sendtext (mp_data );
Breadtext: = false;
End;
Mp_end: Begin
Fsrecv. Free
Breadtext: = true;
End;
Mp_abort: Begin
Fsrecv. Free;
Breadtext: = true;
End;
Mp_chat: Begin
// Chat msg
End;
End; {of case}
End
Else begin
Try
Getmem (bufrecv, 2000); // 2000 must> ibytesend
Socket. receivebuf (bufrecv ^, irecvlength );
Fsrecv. writebuffer (bufrecv ^, irecvlength );
Finally
Freemem (bufrecv, 2000 );
End; {of try}
Breadtext: = true;
Socket. sendtext (mp_nextwillbedata );
End;
End;
Client Program:
Put the following controls: edtipaddress, opendialog1, btnconnect, btnsendfile,
CS. (tclientsocket)
Btnconnect. onclick (Sender: tobject );
Begin
CS. Address: = edtipaddress. text;
CS. Port: = 2000;
CS. Connect;
End;
Btnsendfile. onclick (Sender: tobject );
Begin
If opendialog1.execute then
Begin
CS. Socket. sendtext (mp_query + opendialog1.filename); // filesize ???
End;
End;
CS. onread (Sender: tobject; socket: tcustomwinsocket );
VaR
Stemp: string;
Bufsend: pointer;
Begin
Srecv: = socket. receivetext;
Case srecv [1]
Mp_refuse: showmessage ('faint, be refused! ');
Mp_accept: Begin
Fssend: = tfilestream. Create (opendialog1.filename, fmopen );
// Ibytepersend is a constant. The size of each packet sent.
Socket. sendtext (mp_fileproperty + trunc (fssend. Size/ibytepersend) + 1 );
End;
Mp_nextwillbedata: Begin
Socket. sendtext (mp_nextwillbedata );
End;
Mp_data: Begin
Try
Getmem (bufsend, ibytepersend + 1 );
If (fssend. Position + 1 + ibytepersend) <fssend. Size then
Begin
Fssend. Read (bufsend ^, ibytepersend );
Socket. sendbuf (bufsend ^, ibytepersend );
Fssend. Free;
End // normal sending, the size is ibytepersend
Else begin
Fssend. Read (bufsend ^, fssend. Size-fsSend.Position-1 );
Socket. sendbuf (bufsend ^, fssend. Size-fsSend.Position-1 );
End; // The last time the message is sent, the remaining data is sent.
Finally
Freemem (bufsend, ibytepersend + 1 );
End; {of try}
End;
Mp_abort: Begin
// Canceled :(
Fssend. Free;
End;
End; {of case}
End;
Sorting program:
Add error judgment, optimize the program, combine the server and client, and add the remaining time progress display to make it possible to transfer multiple files at a time and add the chat function, it becomes a good program for transferring files point to point.
If the requirement is not high, it can be in the sender (not necessarily serversocket)
File to be sent
Myfile: = tfilestream (file name, fmopenread ...)
Then socket. sendstream (myfile );
Receiver
It can be received using socketstream. If you do not need to process in the thread, it is easy to use the event.
Under the clientsocket. onread event
Enable Buffer
Socket. receivebuffer (buffer)
Save to file (you can also use file Stream)
Release Buffer
However, it should be noted that the documentation of Delphi is written in this way.
Non-blocking sockets do not always receive an onread event for the last bit of data passed over the connection. when using a non-blocking socket, check for any unread data in the ondisconnect event to make sure that everything is handled.
Therefore, an onread operation is performed in the ondisconnect event. OK.
I suggest you spend some time studying it. After figuring out the principle, we are looking at people's code. If it is text, send sendtext () directly. Send a string instead of a text file ......
Sendstream/sendbuf is used.
How to add a tserversocket control?
1. Component
2. install packages
3. Add ---> dclsockets70.bpl in the bin directory
4. OK button
Tserversocket is in the Internet module.