Fork me on GitHub

UDP简单大文件传送

话不多说,直接上代码。
运行的时候先运行You.java, 再运行My.java

My.java

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
import java.net.*;
import java.util.concurrent.TimeoutException;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import javax.swing.*;
public class My{
public static void main(String[] args) {
new MyFrame();
}
}
class MyFrame extends JFrame implements ActionListener {
JTextField out_message = new JTextField(16);
JTextArea in_message = new JTextArea();
JButton cfile = new JButton("选择文件");
JFileChooser chooser = new JFileChooser();
public MyFrame() {
setTitle("My");
// setSize(600, 600);
setVisible(true);
setBounds(300, 200, 350, 300);
cfile.addActionListener(this);
// send.addActionListener(this);
// out_message.addKeyListener(this);
JPanel pSouth = new JPanel();
pSouth.add(out_message);
pSouth.add(cfile);
// pSouth.add(send);
add(pSouth, "South");
add(new JScrollPane(in_message), "Center");
validate();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent event) {
chooser.setFileSelectionMode(0);
int status = chooser.showOpenDialog(null);
if (status == 1) {
return;
} else {
File file = chooser.getSelectedFile();
out_message.setText(file.getAbsolutePath());
out_message.grabFocus();
long startTime = System.currentTimeMillis();// 获取当前时间
byte[] buf = new byte[UDPUtils.BUFFER_SIZE];// 发送文件的字节数组
byte[] receiveBuf = new byte[Math.max(UDPUtils.successData.length, UDPUtils.exitData.length)];// 传送验证信息的字节数组
RandomAccessFile accessFile = null;
DatagramPacket dpk = null;
DatagramSocket dsk = null;
int readSize = -1;
try {
accessFile = new RandomAccessFile(file.getAbsolutePath(), "r");// 创建一个只读的文件流
dpk = new DatagramPacket(buf, buf.length,
new InetSocketAddress(InetAddress.getByName("192.168.199.143"), UDPUtils.PORT + 1));// 创建一个待发送数据包
dsk = new DatagramSocket(UDPUtils.PORT);// 接收....
dsk.setSoTimeout(1000);// 设置确认报文超时重传
int sendCount = 0;// 记录发送的数据包的数量
while ((readSize = accessFile.read(buf, 0, buf.length)) != -1) {// 将文件的数据读满字节数组,返回读入数组的总字节数,如果到文件尾则等于-1
// 未读到文件尾
dpk.setData(buf, 0, readSize);// 设置包的缓冲区长度为读入的字节数
dsk.send(dpk);// 发送包
// 等待服务端回应
{
while (true) {
dpk.setData(receiveBuf, 0, receiveBuf.length);// UDPUtils.successData.length);
try {
dsk.receive(dpk);// 接收数据包
if (!UDPUtils.isEqualsByteArray(UDPUtils.successData, receiveBuf, dpk.getLength())) {// 返回的不是成功标志
throw new TimeoutException("数据没有收到!");
} else {
break;
}
} catch (SocketTimeoutException | TimeoutException e) {//没有收到数据包或返回的不是成功标志
// TODO 超时重传
System.out.println("resend ...");
dpk.setData(buf, 0, readSize);
dsk.send(dpk);
continue;
}
}
}
System.out.println("send count of " + (++sendCount) + "!");
}
// 发送退出标志等待回应
System.out.println("客户端退出 ....");
dpk.setData(UDPUtils.exitData, 0, UDPUtils.exitData.length);
dsk.send(dpk);
while (true) {
dpk.setData(receiveBuf, 0, receiveBuf.length);
// byte[] receiveData = dpk.getData();
try {
dsk.receive(dpk);
if (!UDPUtils.isEqualsByteArray(UDPUtils.exitData, receiveBuf, dpk.getLength())) {
throw new TimeoutException("Msg not equal");
} else {
break;
}
} catch (SocketTimeoutException | TimeoutException e) {
// TODO 超时重传
System.out.println("client Resend exit message ....");
dsk.send(dpk);
continue;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (accessFile != null)
accessFile.close();
if (dsk != null)
dsk.close();
} catch (IOException e) {
e.printStackTrace();
}
}
long endTime = System.currentTimeMillis();
System.out.println("time:" + (endTime - startTime));
}
}
}

You.java

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
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
public class You {
private static final String SAVE_FILE_PATH = "C:/Users/马冲/Desktop/flag.zip";//接收文件存储的路径
public static void main(String[] args) {
byte[] buf = new byte[UDPUtils.BUFFER_SIZE];
DatagramPacket dpk = null;//定义一个数据包
DatagramSocket dsk = null;//定义一个接收数据包
BufferedOutputStream bos = null;//定义一个缓冲的文件输出流
try {
dpk = new DatagramPacket(buf, buf.length,
new InetSocketAddress(InetAddress.getByName("127.0.0.1"), UDPUtils.PORT));
dsk = new DatagramSocket(UDPUtils.PORT + 1);//创建一个数据包由于接收
bos = new BufferedOutputStream(new FileOutputStream(SAVE_FILE_PATH));//创建一个缓冲的文件输出流
System.out.println("等待客户端....");
dsk.receive(dpk);//等待客户端发送文件
int readSize = 0;
int readCount = 0;
int flushSize = 0;
while ((readSize = dpk.getLength()) != 0) {
// 验证客户端发送退出标志
if (UDPUtils.isEqualsByteArray(UDPUtils.exitData, buf, readSize)) {
System.out.println("服务器退出 ...");
dpk.setData(UDPUtils.exitData, 0, UDPUtils.exitData.length);//设置包中数据为退出标志
dsk.send(dpk);//发送退出标志
break;//退出
}
bos.write(buf, 0, readSize);//将字节数组中的数据写入缓冲流
if (++flushSize % 1000 == 0) {
flushSize = 0;
bos.flush();
}
dpk.setData(UDPUtils.successData, 0, UDPUtils.successData.length);//设置包中数据为接收成功标志
dsk.send(dpk);//返回一个接收成功标志
dpk.setData(buf, 0, buf.length);//重新设置包用于接收下一个数据包
System.out.println("receive count of " + (++readCount) + " !");
dsk.receive(dpk);//等待客户端发送文件
}
// last flush
bos.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (bos != null)
bos.close();
if (dsk != null)
dsk.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

UDPUtils.java

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
public class UDPUtils {
private UDPUtils() {
}
/** transfer file byte buffer **/
public static final int BUFFER_SIZE = 50 * 1024;
/** controller port **/
public static final int PORT = 50000;
/** mark transfer success **/
public static final byte[] successData = "success data mark".getBytes();
/** mark transfer exit **/
public static final byte[] exitData = "exit data mark".getBytes();
/**
* compare byteArray equest successData
*
* @param compareBuf
* src
* @param buf
* target
* @return
*/
public static boolean isEqualsByteArray(byte[] compareBuf, byte[] buf, int len) {
if (buf == null || buf.length == 0 || compareBuf.length < len)
return false;
boolean flag = true;
int innerMinLen = Math.min(compareBuf.length, len);
// if(buf.length == compareBuf.length){
for (int i = 0; i < innerMinLen; i++) {
if (buf[i] != compareBuf[i]) {
flag = false;
break;
}
}
// }else
// return false;
return flag;
}
}

Your support will encourage me to continue to create!