一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專(zhuān)注于服務(wù)器技術(shù)及軟件下載分享
分類(lèi)導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務(wù)器之家 - 編程語(yǔ)言 - JAVA教程 - Java基于TCP方式的二進(jìn)制文件傳輸

Java基于TCP方式的二進(jìn)制文件傳輸

2020-03-22 13:07gloomyfish JAVA教程

這篇文章主要為大家介紹了Java基于TCP方式的二進(jìn)制文件傳輸,一個(gè)基于Java Socket協(xié)議之上文件傳輸?shù)耐暾纠赥CP通信完成,感興趣的小伙伴們可以參考一下

一個(gè)基于Java Socket協(xié)議之上文件傳輸?shù)耐暾纠赥CP通信完成。

除了基于TCP的二進(jìn)制文件傳輸,還演示了JAVA Swing的一些編程技巧,Demo程序

實(shí)現(xiàn)主要功能有以下幾點(diǎn):

  • 1.基于Java Socket的二進(jìn)制文件傳輸(包括圖片,二進(jìn)制文件,各種文檔work,PDF)
  • 2.SwingWorker集合JProgressBar顯示實(shí)時(shí)傳輸/接受完成的百分比
  • 3.其它一些Swing多線程編程技巧

首先來(lái)看一下整個(gè)Dome的Class之間的關(guān)系圖:

Java基于TCP方式的二進(jìn)制文件傳輸

下面按照上圖來(lái)詳細(xì)解釋各個(gè)類(lèi)的功能與代碼實(shí)現(xiàn):

服務(wù)器端:

FileTransferServer類(lèi)的功能首先是在端口9999創(chuàng)建一個(gè)服務(wù)器套接字并

開(kāi)始監(jiān)聽(tīng)連接。相關(guān)代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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.println("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();
 }
}

關(guān)于PropertyChangeListener, Java提供了一個(gè)非常有力的工具類(lèi)來(lái)
監(jiān)控任意Bean Model的數(shù)據(jù)改變,程序通過(guò)添加該監(jiān)聽(tīng)器實(shí)現(xiàn)對(duì)

SwingWorker的progress屬性值改變的事件捕獲,然后更新JProgressBar

實(shí)例對(duì)象,實(shí)現(xiàn)了UI的刷新。FileTransferServer類(lèi)的完整源代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
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 START_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.println("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();
  }
 }
  
 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是服務(wù)器端的文件接受類(lèi):
首先從建立的TCP流中得到文件名與文件大小,然后開(kāi)始接受文件內(nèi)容字節(jié)

并寫(xiě)入創(chuàng)建的文件對(duì)象流中,最后驗(yàn)證文件大小與寫(xiě)入的字節(jié)流是否相等

最后發(fā)送一條消息到文件發(fā)送方,告訴對(duì)方文件傳輸完成,可以關(guān)閉TCP流。

該類(lèi)的完整源代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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 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, numReadBytes);
   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;
 }
 
}

客戶端:
FileTransferClient是客戶端UI類(lèi),用來(lái)實(shí)現(xiàn)到服務(wù)端的連接,然后選擇

要傳輸?shù)奈募?圖片,PDF,Word文檔等各種二進(jìn)制文件)。如果沒(méi)有

輸入服務(wù)器信息,會(huì)彈出提示要求輸入。端口已經(jīng)指定為:9999

【send File】按鈕會(huì)打開(kāi)文件選擇框,用戶選擇要傳輸文件以后,創(chuàng)建

FileTransferTask線程,并開(kāi)始執(zhí)行文件傳送。客戶端UI代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
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;
/**
 * 我一般寫(xiě)英文注釋?zhuān)紶栁乙矔?huì)寫(xiě)中文注釋?zhuān)皇怯X(jué)得寫(xiě)英文
 * 注釋跟代碼比較統(tǒng)一,無(wú)他。
 */
public class FileTransferClient extends JFrame implements ActionListener {
 /**
  *
  */
 private static final long 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, "Please enter server host and 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(); // 異步task執(zhí)行
   }
  } else {
   // do nothing
  }
 }
  
 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實(shí)現(xiàn)的功能主要有:

  • 1. 發(fā)送文件meta信息到接受方(文件名與文件大小)
  • 2. 讀取文件內(nèi)容字節(jié)寫(xiě)入Socket字節(jié)流中,發(fā)送到接受方
  • 3. 從Socket字節(jié)流中讀取對(duì)方接受完成通知信息,調(diào)用彈出文件傳輸成功信息

該類(lèi)完全源代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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 = selectedFile.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 all the bytes have been read in
  if (offset < fsize) {
   throw new IOException("Could not completely transfer file " + selectedFile.getName());
  }
  mSocket.shutdownOutput();
   
  // receive the file transfer successfully message from connection
   
  BufferedInputStream streamReader = new BufferedInputStream(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;
 }
}

數(shù)據(jù)包類(lèi)如下,不解釋?zhuān)?/p>

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.gloomyfish.socket.tutorial.filetransfer;
/**
 * this is very simple file transfer protocol over TCP socket
 */
public class FileDataPackage {
 
 private int dataLength; // 數(shù)據(jù)包中數(shù)據(jù)長(zhǎng)度,兩個(gè)字節(jié)
 private byte[] databuff; // 數(shù)據(jù)包中數(shù)據(jù),meici最大不超過(guò)2048字節(jié)
  
 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] = ' ';
   }
  }
 }
}

每次發(fā)送的最大字節(jié)數(shù)為2048個(gè)字節(jié)。程序最終運(yùn)行效果如下(win7 + JDK6u30):

Java基于TCP方式的二進(jìn)制文件傳輸

Java基于TCP方式的二進(jìn)制文件傳輸

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 草逼的视频| 爱情岛论坛自拍永久入口 | 欧美男同互吃gay老头 | 亚洲精品午夜级久久久久 | 成人影院在线观看 | 亚洲福利视频在线观看 | bnb998八度免费影院丫意浓 | 欧美一区二区三区四区视频 | 欧美日韩一区二区三区久久 | 国产精品免费久久久久影院小说 | 国产日产欧产精品精品软件 | 99精品在线视频 | 日韩在线一区二区 | 99热久久这里只精品国产www | 成人精品亚洲人成在线 | 国产婷婷综合丁香亚洲欧洲 | 日本videossexx日本人 | 91普通话国产对白在线 | 亚洲社区在线观看 | 欧美老女人b| 丝瓜视频黄色在线观看 | 成人123 | 日韩欧美一区二区三区免费看 | 麻豆小视频在线观看 | 亚洲国产精品自产在线播放 | melody中文字幕 | 成人毛片高清视频观看 | 日本视频免费在线 | 免费成人在线观看视频 | 亚洲图片一区二区 | 色婷婷综合缴情综六月 | 国产性视频 | 亚洲剧情在线观看 | 男人与禽交的方法 | 高清女主播一区二区三区 | gogort99人体专业网站 | 午夜欧美福利视频 | 国产免费看片 | 日本高清无吗 | 天天综合五月天 | 美女脱了内裤打开腿让人羞羞软件 |