项目说明.txt
原始文档
1 2 3 4 |
TCP服务器提供文件下载服务,服务器支持多线程。
TCP Client从服务器上下载指定的文件,Client也支持多线程。
分服务器代码和客户端代码:ServerOneDownload.java 为服务器代码
DownLoadClient.java为客户端代码、DownFileThread.java为客户端代码
|
ServerOneDownload.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 133 134 135 136 137 138 139 140 |
//file:DownloadServer.java
import java.net.*;
import java.io.*;
class ServerOneDownload extends Thread {
private Socket socket = null;
private String downloadRoot = null;
private static final int Buffer = 8 * 1024;
public ServerOneDownload(Socket socket, String downloadRoot) {
super();
this.socket = socket;
this.downloadRoot = downloadRoot;
start();
}
// 检查文件是否真实存在,核对下载密码,若文件不存在或密码错误,则返回-1,否则返回文件长度
// 此处只要密码不为空就认为是正确的
private long getFileLength(String fileName, String password) {
// 若文件名或密码为null,则返回-1
if ((fileName == null) || (password == null))
return -1;
// 若文件名或密码长度为0,则返回-1
if ((fileName.length() == 0) || (password.length() == 0))
return -1;
String filePath = downloadRoot + fileName; // 生成完整文件路径
System.out.println("DownloadServer getFileLength----->" + filePath);
File file = new File(filePath);
// 若文件不存在,则返回-1
if (!file.exists())
return -1;
return file.length(); // 返回文件长度
}
// 用指定输出流发送指定文件
private void sendFile(DataOutputStream out, String fileName)
throws Exception {
String filePath = downloadRoot + fileName; // 生成完整文件路径
// 创建与该文件关联的文件输入流
FileInputStream in = new FileInputStream(filePath);
System.out.println("DownloadServer sendFile----->" + filePath);
byte[] buf = new byte[Buffer];
int len;
// 反复读取该文件中的内容,直到读到的长度为-1
while ((len = in.read(buf)) >= 0) {
out.write(buf, 0, len); // 将读到的数据,按读到的长度写入输出流
out.flush();
}
out.close();
in.close();
}
// 提供下载服务
public void download() throws IOException {
System.out.println("启动下载... ");
System.out.println("DownloadServer currentThread--->"
+ currentThread().getName());
System.out.println("DownloadServer currentThread--->"
+ currentThread().getId());
// 获取socket的输入流并包装成BufferedReader
BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
// 获取socket的输出流并包装成DataOutputStream
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
try {
String parameterString = in.readLine(); // 接收下载请求参数
// 下载请求参数字符串为自定义的格式,由下载文件相对于下载根目录的路径和
// 下载密码组成,两者间以字符 "@ "分隔,此处按 "@ "分割下载请求参数字符串
String[] parameter = parameterString.split("@ ");
String fileName = parameter[0]; // 获取相对文件路径
String password = parameter[1]; // 获取下载密码
// 打印请求下载相关信息
System.out.print(socket.getInetAddress().getHostAddress()
+ "提出下载请求, ");
System.out.println("请求下载文件: " + fileName);
// 检查文件是否真实存在,核对下载密码,获取文件长度
long len = getFileLength(fileName, password);
System.out.println("download fileName----->" + fileName);
System.out.println("download password----->" + password);
out.writeLong(len); // 向客户端返回文件大小
out.flush();
// 若获取的文件长度大于等于0,则允许下载,否则拒绝下载
if (len >= 0) {
System.out.println("允许下载 ");
System.out.println("正在下载文件 " + fileName + "... ");
sendFile(out, fileName); // 向客户端发送文件
System.out.println(fileName +": "+"下载完毕 ");
} else {
System.out.println("下载文件不存在或密码错误,拒绝下载! ");
}
} catch (Exception e) {
System.out.println(e.toString());
} finally {
socket.close(); // 关闭socket
}
}
@Override
public void run() {
try {
download();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// TODO Auto-generated method stub
super.run();
}
}
public class DownloadServer {
private final static int port = 65525;
private static String root = "C:\\ "; // 下载根目录
public static void main(String[] args) throws IOException {
String temp = null;
// 监听端口
try {
// 包装标准输入为BufferedReader
BufferedReader systemIn = new BufferedReader(new InputStreamReader(
System.in));
while (true) {
System.out.print("请输入下载服务器的下载根目录: ");
root = systemIn.readLine().trim(); // 从标准输入读取下载根目录
File file = new File(root);
// 若该目录确实存在且为目录,则跳出循环
if ((file.exists()) && (file.isDirectory())) {
temp = root.substring(root.length() - 1, root.length());
if (!temp.equals("\\"))
root += "\\";
}
break;
}
} catch (Exception e) {
System.out.println(e.toString());
}
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("Server start...");
try {
while (true) {
Socket socket = serverSocket.accept();
new ServerOneDownload(socket, root);
}
} finally {
serverSocket.close();
}
}
}
|
DownLoadClient.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 |
//file:DownLoadClient.java
package org.piaozhiye.study;
import java.io.IOException;
import java.net.Socket;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class DownLoadClient extends Activity {
private Button download = null;
private EditText et_serverIP = null;
private EditText et_fileName= null;
private String downloadFile = null;
private final static int PORT = 65525;
private final static String defaultIP = "192.168.0.100";
private static String serverIP = null;
private Socket socket;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
download = (Button)findViewById(R.id.download);
et_serverIP= (EditText)findViewById(R.id.et_serverip);
et_fileName = (EditText)findViewById(R.id.et_filename);
et_serverIP.setText("192.168.0.100");
download.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
serverIP = et_serverIP.getText().toString();
if(serverIP == null){
serverIP = defaultIP;
}
System.out.println("DownLoadClient serverIP--->" + serverIP );
System.out.println("DownLoadClient MainThread--->" + Thread.currentThread().getId() );
try{
socket = new Socket(serverIP, PORT);
}catch(IOException e){
}
downloadFile = et_fileName.getText().toString();
Thread downFileThread = new Thread(new DownFileThread(socket, downloadFile));
downFileThread.start();
System.out.println("DownLoadClient downloadFile--->" + downloadFile );
}
});
}
}
|
DownFileThread.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 |
package org.piaozhiye.study;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
public class DownFileThread extends Thread {
private Socket socket;
private String downloadFile;
private final static int Buffer = 8 * 1024;
public DownFileThread(Socket socket, String downloadFile) {
super();
this.socket = socket;
this.downloadFile = downloadFile;
}
public Socket getSocket() {
return socket;
}
public void setSocket(Socket socket) {
this.socket = socket;
}
public String getDownloadFile() {
return downloadFile;
}
public void setDownloadFile(String downloadFile) {
this.downloadFile = downloadFile;
}
// 向服务器提出下载请求,返回下载文件的大小
private long request(String fileName, String password) throws IOException {
// 获取socket的输入流并包装成DataInputStream
DataInputStream in = new DataInputStream(socket.getInputStream());
// 获取socket的输出流并包装成PrintWriter
PrintWriter out = new PrintWriter(new OutputStreamWriter(
socket.getOutputStream()));
// 生成下载请求字符串
String requestString = fileName + "@ " + password;
out.println(requestString); // 发出下载请求
out.flush();
return in.readLong(); // 接收并返回下载文件长度
}
// 接收并保存文件
private void receiveFile(String localFile) throws Exception {
// 获取socket的输入流并包装成BufferedInputStream
BufferedInputStream in = new BufferedInputStream(
socket.getInputStream());
// 获取与指定本地文件关联的文件输出流
FileOutputStream out = new FileOutputStream(localFile);
byte[] buf = new byte[Buffer];
int len;
// 反复读取该文件中的内容,直到读到的长度为-1
while ((len = in.read(buf)) >= 0) {
out.write(buf, 0, len); // 将读到的数据,按读到的长度写入输出流
out.flush();
}
out.close();
in.close();
}
// 从服务器下载文件
public void download(String downloadFile) throws Exception {
try {
String password = "password";
// String downloadFile ="imissyou.mp3";
String localpath = "/sdcard/";
String localFile = localpath + downloadFile;
long fileLength = request(downloadFile, password);
// 若获取的文件长度大于等于0,说明允许下载,否则说明拒绝下载
if (fileLength >= 0) {
System.out.println("fileLength: " + fileLength + " B");
System.out.println("downing...");
receiveFile(localFile); // 从服务器接收文件并保存至本地文件
System.out.println("file:" + downloadFile + " had save to "
+ localFile);
} else {
System.out.println("download " + downloadFile + " error! ");
}
} catch (IOException e) {
System.out.println(e.toString());
} finally {
socket.close(); // 关闭socket
}
}
@Override
public void run() {
System.out.println("DownFileThread currentThread--->"
+ DownFileThread.currentThread().getId());
// TODO Auto-generated method stub
try {
download(downloadFile);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
super.run();
}
}
|
本文介绍了一个基于TCP协议的文件下载服务实现,包括服务器端和客户端的代码细节。服务器支持多线程并发处理多个下载请求,客户端能够指定文件进行下载。
3782

被折叠的 条评论
为什么被折叠?



