A complete example based on the file transfer over the Java socket protocol, based on TCP communication completion.
In addition to TCP based binary file transfer, it also demonstrates some of the programming techniques of Java Swing, the demo program
The following are some of the key features to implement:
- 1. binary file transfer based on Java socket (including pictures, binaries, various documents work,pdf)
- 2.SwingWorker Collection JProgressBar shows the percentage of live transmit/accept completion
- 3. Some other swing multithreaded programming tips
First look at the diagram of the entire dome class:
The following diagram explains the functions and code implementations of each class in detail:
Server side:
The function of the Filetransferserver class is first to create a server socket in port 9999 and
Start listening for connections. The relevant code is as follows:
private void StartServer (int port) {
try {
serversocket = new ServerSocket (port);
System.out.println ("Server started at Port:" + port);
while (true) {
socket client = serversocket.accept ();//Blocked & waiting for income Socket
System.out.printl N ("Just connected to" + client.getremotesocketaddress ());
Filereceivetask task = new Filereceivetask (client);
Bar.setvalue (0); Reset it now
Task.addpropertychangelistener (new PropertyChangeListener () {public
void PropertyChange ( Propertychangeevent evt) {
if ("Progress". Equals (Evt.getpropertyname ()) {
Bar.setvalue (Integer) Evt.getnewvalue ();}
}
);
Task.execute ();
}
catch (IOException e) {
e.printstacktrace ();
}
}
With regard to PropertyChangeListener, Java provides a very powerful tool class to
Monitor the data changes in any bean model by adding the listener to the
SwingWorker the Progress property value changes the event capture, and then updates the JProgressBar
Instance object, which implements a refresh of the UI. The complete source code for the Filetransferserver class is as follows:
Package com.gloomyfish.socket.tutorial.filetransfer;
Import Java.awt.BorderLayout;
Import Java.awt.FlowLayout;
Import java.awt.event.ActionEvent;
Import Java.awt.event.ActionListener;
Import java.beans.PropertyChangeEvent;
Import Java.beans.PropertyChangeListener;
Import java.io.IOException;
Import Java.net.ServerSocket;
Import Java.net.Socket;
Import Javax.swing.BoxLayout;
Import Javax.swing.JButton;
Import Javax.swing.JFrame;
Import Javax.swing.JOptionPane;
Import Javax.swing.JPanel;
Import Javax.swing.JProgressBar; public class Filetransferserver extends JFrame implements ActionListener {/** * */public final static String S
Tart_svr = "Start";
Public final static String shut_down_svr = "Shut down";
Public final static String End_flag = "EOF";
Private static final long serialversionuid = 1L;
Private ServerSocket ServerSocket;
Private JButton startbtn;
Private JProgressBar Bar;
Public Filetransferserver () {super ("File Server"); InItcomponent ();
Setuplistener ();
private void Setuplistener () {Startbtn.addactionlistener (this);
private void InitComponent () {startbtn = new JButton (START_SVR);
JPanel ProgressPanel = new JPanel ();
Progresspanel.setlayout (New BoxLayout (ProgressPanel, Boxlayout.y_axis));
bar = new JProgressBar ();
Bar.setminimum (0);
Bar.setmaximum (100);
Progresspanel.add (bar);
Getcontentpane (). setlayout (New BorderLayout ());
JPanel Btnpanel = new JPanel (new FlowLayout (flowlayout.right));
Btnpanel.add (STARTBTN);
Getcontentpane (). Add (Btnpanel, Borderlayout.south);
Getcontentpane (). Add (ProgressPanel, borderlayout.center);
private void StartServer (int port) {try {serversocket = new ServerSocket (port);
System.out.println ("Server started at Port:" + port); while (true) {Socket client = serversocket.accept ();//Blocked & waiting for income Socket System.out.print ln ("Just connected to" + Client.getremotesocketadDress ());
Filereceivetask task = new Filereceivetask (client); Bar.setvalue (0); Reset it now Task.addpropertychangelistener (new PropertyChangeListener () {public void PropertyChange (Proper Tychangeevent evt) {if ("Progress". Equals (Evt.getpropertyname ()) {Bar.setvalue ((Integer) Evt.getnewvalue
());
}
}
});
Task.execute ();
} catch (IOException e) {e.printstacktrace ();
} public void Showsuccess () {bar.setvalue (100);
Joptionpane.showmessagedialog (This, "File received successfully!"); @Override public void actionperformed (ActionEvent e) {if (Start_svr.equals (E.getactioncommand ())) {Thread
Startthread = new Thread (new Runnable () {public void run () {startserver (9999);
}
});
Startthread.start ();
Startbtn.setenabled (FALSE);
else if (Shut_down_svr.equals (E.getactioncommand ())) {} else {//do nothing ...} } public static VoID Main (string[] args) {filetransferserver server = new Filetransferserver ();
Server.setdefaultcloseoperation (Jframe.exit_on_close);
Server.setsize (400, 400);
Server.setresizable (FALSE);
Server.setvisible (TRUE);
}
}
Filereceivetask is a server-side file acceptance class:
First, get the file name and file size from the established TCP stream, and then start accepting the content bytes
And writes to the created file object stream, and finally verifies that the file size is equal to the byte stream being written
Finally send a message to the file sender, tell the other party file transfer completed, you can shut down the TCP stream.
The complete source code for the class is as follows:
Package com.gloomyfish.socket.tutorial.filetransfer;
Import Java.io.BufferedOutputStream;
Import Java.io.BufferedWriter;
Import Java.io.DataInputStream;
Import Java.io.File;
Import Java.io.FileOutputStream;
Import Java.io.OutputStreamWriter;
Import Java.net.Socket;
Import Javax.swing.SwingWorker;
public class Filereceivetask extends Swingworker<integer, object> {private Socket _msocket;
Public Filereceivetask (Socket client) {this._msocket = client; @Override protected Integer Doinbackground () throws Exception {//Get file meta information DataInputStream
input = new DataInputStream (_msocket.getinputstream ());
String fileName = Input.readutf (); int filelength = (int) input.readlong ();
Number of total Bytes file = new File ("C:\\users\\fish\\downloads" + File.separator + fileName);
Bufferedoutputstream output = new Bufferedoutputstream (new FileOutputStream (file)); System.out.println ("Received File Name =" + FileName);
System.out.println ("Received File size =" + filelength/1024 + "KB");
Start to receive the content of the "file and write them byte[] content = new byte[2048];
int offset = 0;
int numreadbytes = 0; while (Offset < filelength && (numreadbytes = input.read (content) > 0) {output.write (content, 0, Numrea
Dbytes);
float precent = 100.0f * (float) offset)/((float) filelength);
Setprogress ((int) precent);
Offset + + numreadbytes;
} System.out.println ("numreadbytes =" + numreadbytes);
if (offset < filelength) {numreadbytes = Input.read (content);
System.out.println ("numreadbytes =" + numreadbytes);
System.out.println ("File content error at server side");
else {System.out.println ("File Receive Task has done correctly");
} setprogress (100);
Tell-client to close the socket now, we already receive the file successfully!! BufferedWriter bufferedwriter = new BufferedWriter (New OutputStreamWriter (_msocket.getoutputstream ()));
Bufferedwriter.write ("done\r\n");
Bufferedwriter.flush ();
Close the file and socket Output.close ();
_msocket.close ();
return 100;
}
}
Client:
Filetransferclient is the client UI class that implements the connection to the server and then selects
Files to transfer (Pictures, Pdf,word documents, etc.). If there is no
Enter the server information, pop-up prompts to request input. The port has been specified as: 9999
The Send File button opens the File selection box, and after the user chooses to transfer the file, create
Filetransfertask the thread and starts performing file transfer. The client UI code is as follows:
Package com.gloomyfish.socket.tutorial.filetransfer;
Import Java.awt.BorderLayout;
Import Java.awt.FlowLayout;
Import Java.awt.GridLayout;
Import java.awt.event.ActionEvent;
Import Java.awt.event.ActionListener;
Import java.beans.PropertyChangeEvent;
Import Java.beans.PropertyChangeListener;
Import Java.io.File;
Import java.net.InetSocketAddress;
Import java.net.SocketAddress;
Import Javax.swing.BorderFactory;
Import Javax.swing.BoxLayout;
Import Javax.swing.JButton;
Import Javax.swing.JFileChooser;
Import Javax.swing.JFrame;
Import Javax.swing.JLabel;
Import Javax.swing.JOptionPane;
Import Javax.swing.JPanel;
Import Javax.swing.JProgressBar;
Import Javax.swing.JTextField;
/** * I usually write English notes, occasionally I will also write Chinese notes, just feel write English * comments and code more unified, without him. * * public class Filetransferclient extends JFrame implements ActionListener {/** * */private static Final Lon
G Serialversionuid = 1L;
Public final static String Send_cmd = "SEND File"; Public final static int MINIMUM =0;
Public final static int MAXIMUM = 100;
Public final static String connect_cmd = "CONNECT";
Private JButton sendfilebtn;
Private JTextField Serverfield;
Private JTextField Portfield;
Private JProgressBar Bar;
Public Filetransferclient () {super ("File Transfer Client");
Initcomponents ();
private void Initcomponents () {Getcontentpane (). setlayout (New BorderLayout ());
JPanel ProgressPanel = new JPanel ();
Progresspanel.setlayout (New BoxLayout (ProgressPanel, Boxlayout.y_axis));
bar = new JProgressBar ();
Progresspanel.add (bar);
Bar.setminimum (MINIMUM);
Bar.setmaximum (MAXIMUM);
JPanel Serversettingpanel = new JPanel ();
Serversettingpanel.setlayout (New GridLayout (2,2,5,5));
Serversettingpanel.setborder (Borderfactory.createtitledborder ("Server Setting"));
Serverfield = new JTextField ();
Portfield = new JTextField ();
Serversettingpanel.add (New JLabel ("Server ip/host:"));
Serversettingpanel.add (Serverfield); ServerseTtingpanel.add (New JLabel ("Server Port:");
Serversettingpanel.add (Portfield);
SENDFILEBTN = new JButton (send_cmd);
JPanel Btnpanel = new JPanel ();
Btnpanel.setlayout (New FlowLayout (flowlayout.right));
Btnpanel.add (SENDFILEBTN);
Getcontentpane (). Add (Serversettingpanel, Borderlayout.north);
Getcontentpane (). Add (Btnpanel, Borderlayout.south);
Getcontentpane (). Add (ProgressPanel, borderlayout.center);
Sendfilebtn.addactionlistener (this);
@Override public void actionperformed (ActionEvent e) {String command = E.getactioncommand (); if (Command.equals (send_cmd)) {if (Checknull ()) {Joptionpane.showmessagedialog (this, "to enter server host an
D port in order to set up the connection! ");
Return
} JFileChooser chooser = new JFileChooser ();
int status = Chooser.showopendialog (null);
if (status = = Jfilechooser.approve_option) {File f = chooser.getselectedfile (); SocketAddress address = new Inetsocketaddress (Getserver (), Getport ());
Filetransfertask task = new Filetransfertask (f, address, this);
Bar.setvalue (0);
Task.addpropertychangelistener (New PropertyChangeListener () {public void PropertyChange (Propertychangeevent evt) {
if ("Progress". Equals (Evt.getpropertyname ())) {Bar.setvalue ((Integer) evt.getnewvalue ());
}
}
}); Task.execute ();
Async task Execution}} else {//Do no}} public void Showsuccess () {bar.setvalue (100);
Joptionpane.showmessagedialog (This, "File Send successfully!");
Public String Getserver () {return Serverfield.gettext (). Trim ();
public int Getport () {return integer.parseint (Portfield.gettext (). Trim ());
}/** * Make sure the UI already have some correct input information here!!!
* @return/private Boolean checknull () {String serverName = Serverfield.gettext ();
String port = Portfield.gettext (); if (ServerName = null | | servername.leNgth () = = 0 | | Port = = NULL | |
Port.length () = = 0) {return true;
try {integer.parseint (port);//try to parse it as server port number, validation code.
catch (NumberFormatException ne) {ne.printstacktrace ();
return true;
return false;
public static void Main (string[] args) {filetransferclient client = new Filetransferclient ();
Client.setdefaultcloseoperation (Jframe.exit_on_close);
Client.setsize (400, 400);
Client.setresizable (FALSE);
Client.pack ();
Client.setvisible (TRUE);
}
}
Filetransfertask implementation of the main features are:
- 1. Send file meta information to receiver (filename and file size)
- 2. Read the contents of the file bytes write to the socket byte stream, sent to the receiver
- 3. From the socket byte stream read the other side accept the completion of notification information, call pop-up file transmission success information
The complete source code for this class is as follows:
Package com.gloomyfish.socket.tutorial.filetransfer;
Import Java.io.BufferedInputStream;
Import Java.io.BufferedReader;
Import Java.io.DataInputStream;
Import Java.io.DataOutputStream;
Import Java.io.File;
Import Java.io.FileInputStream;
Import java.io.IOException;
Import Java.io.InputStreamReader;
Import Java.net.Socket;
Import java.net.SocketAddress;
Import Javax.swing.SwingWorker;
public class Filetransfertask extends Swingworker<integer, object> {private File selectedfile;
Private Socket Msocket;
Private socketaddress address;
Private filetransferclient parent; Public filetransfertask (file file, socketaddress address, filetransferclient owner/*, JProgressBar progress*/) {this.
address = address;
This.selectedfile = file;
Msocket = new Socket ();
This.parent = owner; @Override protected Integer Doinbackground () throws Exception {//Get the size of the file long length = s
Electedfile.length (); if (Length > IntEger. Max_value) {throw new IOException ("Could not completely read file" + selectedfile.getname () + "as it is too long ("
+ length + "bytes, max supported" + Integer.max_value + ")";
Msocket.connect (address);
Create the byte array to hold the file data Msocket.setsolinger (true, 60);
DataOutputStream dout = new DataOutputStream (Msocket.getoutputstream ());
Now we start to send the file meta info.
Dout.writeutf (Selectedfile.getname ());
Dout.writelong (length);
Dout.flush ();
End comment Filedatapackage pData = new Filedatapackage ();
DataInputStream is = new DataInputStream (new FileInputStream (selectedfile));
byte[] bytes = new byte[2048];
Read in the bytes int offset = 0;
int numread = 0;
int fsize = (int) length; while (Offset < fsize && (numread=is.read (bytes, 0, bytes.length)) >= 0) {pdata.setdata (bytes, numread)
; Dout.write (Pdata.getpackagedata (), 0, Pdata.getpackagedata (). length);
Dout.flush ();
Offset + + Numread;
float precent = 100.0f * (float) offset)/((float) fsize);
Setprogress ((int) precent);
SYSTEM.OUT.PRINTLN ("total Send bytes =" + offset); Ensure the bytes have been read in if (offset < fsize) {throw new IOException ("could not completely tran
Sfer file "+ selectedfile.getname ());
} msocket.shutdownoutput (); Receive the file transfer successfully message from connection Bufferedinputstream StreamReader = new Bufferedin
Putstream (Msocket.getinputstream ());
BufferedReader BufferedReader = new BufferedReader (new InputStreamReader (StreamReader));
String donemsg = Bufferedreader.readline ();
if ("Done". Equals (Donemsg)) {parent.showsuccess ();
}//Close the file input stream setprogress (100);
Dout.close ();
Msocket.close ();
Is.close ();
SYSTEM.OUT.PRINTLN ("Close it now ...");
return 100;
}
}
The packet class is below, not explained!
Package com.gloomyfish.socket.tutorial.filetransfer;
/**
* This are very simple File Transfer Protocol over TCP socket
*/public
class Filedatapackage {
private int datalength; Data length in packet, two bytes
private byte[] Databuff//packet data, Meici Max no more than 2048 bytes public
final static byte[] EOF = new byte[]{' E ', ' O ', ' F '};
Public Filedatapackage () {
datalength = 0;
Databuff = new byte[2048];
}
Public byte[] Getpackagedata () {
byte[] pData = new Byte[datalength];
End Comment
system.arraycopy (databuff, 0, pData, 0, datalength);
return pData;
}
public void SetData (byte[] data, int bsize) {
datalength = bsize;
for (int i=0; i<databuff.length; i++) {
if (i<bsize) {
databuff[i] = Data[i];
} else {
Databuff [I] = ';
}}
}
The maximum number of bytes sent each time is 2048 bytes. The result of the program's final operation is as follows (Win7 + jdk6u30):
The above is the entire content of this article, I hope to help you learn.