设计一个简单的文件传输程序,服务器接受文件,客户端发送文件,设计一个简单的文件传输协议,比如,先传输文件名,再传输文件大小,再传输文件内容。
设计不合理。
一个文件信息,不需要分成几个包来来回回请求应答。
协议格式类似如下:
8位数据包总长+3位文件名长度+文件名+ 8位文件内容长度+文件内容
以上为变长报文格式,举例如下:
00001048+008+test.txt+00001024+文件内容
要么像2L所定义的协议那样发送,简单
要么就像你期望的那样,定义协议位 数据长度(固定长度)+数据类型(固定长度)+数据
第一次传文件名 比如8位长度(String.format("%08d", filename.getBytes().length).getByes())+数据类型("01".getBytes())+数据(filename.getBytes())
第二次传文件大小 8位长度+数据类型("02")+file.getLength()
第三次以后 8位长度+数据类型("03")+file.read(buf) //最后要check和第二次传送的文件长度一致
如果是基于tcp的长连接进行传输,最好先把文件名、文件大小等文件信息进行加密传输,然后再传输实际的文件流,这样接收方可以先解密文件报文,再取根据报文内容来解析文件流。这样一是可以保证文件安全,排除非法文件传输,二是可以让接收方有据可依。
怎么用多线程完成这个任务啊
这个问题,相当于一个问题终结者。资源代下载99dxz
楼主的协议太墨迹了,我写了一个简单的demo,和楼主共同探讨一下。
我觉得没有必要多次交互,服务端只需要被动的接受就好了。
如果需要交互行为的话,服务端和客户端的编程模式就会复杂一些,建议使用netty进行开发。
这个是服务端的demo,接收一个文件。
package
houlei.net.tcp;
import
java.io.*;
import
java.net.ServerSocket;
import
java.net.Socket;
import
java.nio.charset.Charset;
import
java.text.SimpleDateFormat;
import
java.util.Date;
import
java.util.LinkedList;
public
class
FileServer {
private
final
File tmpPath;
private
final
File targetPath;
private
final
int
port;
private
final
LinkedList
new
LinkedList
private
ServerSocket serverSocket;
private
class
Worker
extends
Thread {
private
final
Socket socket;
private
Worker(Socket socket) {
this
.socket = socket;
}
public
void
run(){
try
{
InputStream is = socket.getInputStream();
byte
[] nameLen =
new
byte
[
4
];
if
(is.read(nameLen) ==
4
) {
int
nameLength = (nameLen[
0
]&
0xFF
)<<
24
| (nameLen[
1
]&
0xFF
)<<
16
| (nameLen[
2
]&
0xFF
)<<
8
| (nameLen[
3
]&
0xFF
)<<
0
;
byte
[] name =
new
byte
[nameLength];
if
(nameLength == is.read(name)) {
String fileName =
new
String(name, Charset.forName(
"UTF-8"
));
byte
[] length =
new
byte
[
8
];
if
(is.read(length) ==
8
) {
long
fileLength = (length[
0
]&
0xFF
)<<
56
| (length[
1
]&
0xFF
)<<
48
| (length[
2
]&
0xFF
)<<
40
| (length[
3
]&
0xFF
)<<
32
|
(length[
4
]&
0xFF
)<<
24
| (length[
5
]&
0xFF
)<<
16
| (length[
6
]&
0xFF
)<<
8
| (length[
7
]&
0xFF
)<<
0
;
readFile(fileName, fileLength, is);
}
}
}
}
catch
(Exception ex) {
ex.printStackTrace();
}
finally
{
try
{
socket.close();
}
catch
(IOException e) {
e.printStackTrace();
}
workers.remove(Worker.
this
);
System.out.println(
"bye : "
+socket.getRemoteSocketAddress());
}
}
private
void
readFile(String fileName,
long
fileLength, InputStream is)
throws
IOException {
String prefix =
"trans-"
+
new
SimpleDateFormat(
"yyyyMMddHHmmssSSS"
).format(
new
Date());
if
(tmpPath.getUsableSpace() > fileLength && targetPath.getUsableSpace() > fileLength) {
File tempFile = File.createTempFile(prefix,
"tmp"
, tmpPath);
OutputStream os =
new
FileOutputStream(tempFile);
transform(os, is);
os.close();
File targetFile =
new
File(targetPath, fileName);
if
(tempFile.renameTo(targetFile)) {
// succeed.
}
}
}
private
void
transform(OutputStream os, InputStream is)
throws
IOException {
byte
[] buffer =
new
byte
[
4096
];
int
length =
0
;
while
((length = is.read(buffer))>
0
) {
os.write(buffer,
0
, length);
}
os.flush();
}
}
public
FileServer(File tmpPath, File targetPath,
int
port) {
if
(tmpPath ==
null
) {
tmpPath =
new
File(System.getProperty(
"java.io.tmpdir"
));
}
if
(!tmpPath.exists()) {
tmpPath.mkdirs();
}
if
(targetPath ==
null
|| !targetPath.exists()) {
throw
new
IllegalArgumentException(
"targetPath does not exists."
);
}
this
.tmpPath = tmpPath;
this
.targetPath = targetPath;
this
.port = port;
}
public
void
start()
throws
IOException {
if
(serverSocket ==
null
) {
serverSocket =
new
ServerSocket(port);
Socket socket;
while
((socket = serverSocket.accept()) !=
null
) {
System.out.println(
"accept : "
+ socket.getRemoteSocketAddress());
Worker worker =
new
Worker(socket);
workers.add(worker);
worker.start();
}
}
}
public
static
void
main(String[] args)
throws
IOException {
File targetFolder =
new
File(
"/Users/naver/target"
);
targetFolder.mkdirs();
FileServer server =
new
FileServer(
null
, targetFolder,
6606
);
server.start();
}
}
这个是客户端的demo,和服务端配合,将客户端的文件传输到服务端。
package
houlei.net.tcp;
import
java.io.*;
import
java.net.Socket;
import
java.nio.charset.Charset;
public
class
FileClient {
private
final
String serverIp;
private
final
int
serverPort;
private
Socket socket;
public
FileClient(String serverIp,
int
serverPort) {
this
.serverIp = serverIp;
this
.serverPort = serverPort;
}
public
void
connect()
throws
IOException {
if
(socket ==
null
) {
socket =
new
Socket(serverIp, serverPort);
}
}
public
void
sendFile(File file)
throws
IOException {
if
(!file.exists() || !file.isFile()) {
throw
new
IllegalArgumentException(
"file ("
+file.getName()+
") does not exists."
);
}
String fileName = file.getName();
long
fileLength = file.length();
InputStream inputStream =
new
FileInputStream(file);
sendFile(fileName, fileLength, inputStream);
}
private
void
sendFile(String fileName,
long
fileLength, InputStream inputStream)
throws
IOException {
byte
[] name = fileName.getBytes(Charset.forName(
"UTF-8"
));
byte
[] nameLen =
new
byte
[
4
];
nameLen[
0
] = (
byte
) ((name.length>>>
24
)&
0xFF
);nameLen[
1
] = (
byte
) ((name.length>>>
16
)&
0xFF
);
nameLen[
2
] = (
byte
) ((name.length>>>
8
)&
0xFF
);nameLen[
3
] = (
byte
) ((name.length>>>
0
)&
0xFF
);
byte
[] length =
new
byte
[
8
];
length[
0
] = (
byte
) ((fileLength>>>
56
)&
0xFF
);length[
1
] = (
byte
) ((fileLength>>>
48
)&
0xFF
);
length[
2
] = (
byte
) ((fileLength>>>
40
)&
0xFF
);length[
3
] = (
byte
) ((fileLength>>>
32
)&
0xFF
);
length[
4
] = (
byte
) ((fileLength>>>
24
)&
0xFF
);length[
5
] = (
byte
) ((fileLength>>>
16
)&
0xFF
);
length[
6
] = (
byte
) ((fileLength>>>
8
)&
0xFF
);length[
7
] = (
byte
) ((fileLength>>>
0
)&
0xFF
);
if
(socket.isConnected()) {
OutputStream os = socket.getOutputStream();
os.write(nameLen);
os.write(name);
os.write(length);
os.flush();
transform(os, inputStream);
}
}
private
void
transform(OutputStream os, InputStream is)
throws
IOException {
byte
[] buffer =
new
byte
[
4096
];
int
length =
0
;
while
((length = is.read(buffer))>
0
) {
os.write(buffer,
0
, length);
}
os.flush();
}
public
static
void
main(String[] args)
throws
IOException {
FileClient client =
new
FileClient(
"127.0.0.1"
,
6606
);
client.connect();
client.sendFile(
new
File(
"/Users/naver/helper.js"
));
}
}