一、实验要求
1、在服务器端,接收客户端传输的数据流,并按
IP
地址保存在服务器端(文
件名重复的,可以覆盖)。
2、如果传输过程中服务器端发现客户端断开,服务器端应删除文件,并在屏幕
上提示,如“ IP : 1.2.3.4 发来 abcd.txt 文件过程中失去连接。”。如果客户端发
现服务器端不工作,客户端应有提示“服务器 1.2.3.5:62345 失去连接”。
件名重复的,可以覆盖)。
2、如果传输过程中服务器端发现客户端断开,服务器端应删除文件,并在屏幕
上提示,如“ IP : 1.2.3.4 发来 abcd.txt 文件过程中失去连接。”。如果客户端发
现服务器端不工作,客户端应有提示“服务器 1.2.3.5:62345 失去连接”。
(
Java实现 Windows Socket TCP实现大文件的传输,请参考:http://blog.csdn.net/qq_24874985/article/details/71305649
)二、C/S嵌套字,面向UDP的传输流程
三、具体代码实现
1、server端
package indi.tangkai.internet.udp;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
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 Server extends Thread {
// 文件的保存路径
private String fileDir;
// socket服务器端口号
private int port;
public String getFileDir() {
return fileDir;
}
public void setFileDir(String fileDir) {
this.fileDir = fileDir;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public static void main(String[] args) {
Server server = new Server();
server.setFileDir("E:\\test\\download\\");
server.setPort(9005);
server.start();
}
/**
* 文件下载
*/
@Override
public void run() {
int bufferSize = 8192;
byte[] buf = new byte[bufferSize];
DatagramPacket dpk = null;
DatagramSocket dsk = null;
DataOutputStream fileOut = null;//文件输出流
long passedlen = 0;//完成传输的大小
long len = 0;//文件的大小
int readSize = 0;//每次读取数据的大小
String fileName = null;//接受的文件名
try {
dpk = new DatagramPacket(buf, buf.length,new InetSocketAddress(InetAddress.getByName("localhost"), port));
dsk = new DatagramSocket(port + 1, InetAddress.getByName("localhost"));
// public Socket accept() throws
// IOException侦听并接受到此套接字的连接。此方法在进行连接之前一直阻塞。
System.out.println("等待客户端链接");
dsk.receive(dpk);
// 本地保存路径,文件名会自动从服务器端继承而来。
// 获取文件名
fileName = new String(buf).trim();
fileDir = fileDir + dpk.getAddress().toString().split("/")[1];
File file = new File(fileDir);
if(!file.exists())
{
file.mkdir();
}
String filePath = fileDir + "\\" + fileName;
dsk.receive(dpk);
System.out.println("buf文件的路径" + filePath + "\n");
file = new File(filePath);
if(!file.exists())
{
file.createNewFile();
}
fileOut = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
len = Long.parseLong(new String(buf, 0, dpk.getLength()));
System.out.println("开始接收文件!" + "\n");
dsk.receive(dpk);
while ((readSize = dpk.getLength()) != 0) {
passedlen += readSize;
//在图形化界面,该部分可以用来作为进度条
//System.out.println("文件接收了" + (passedlen * 100 / len) + "%\n");
fileOut.write(buf, 0, readSize);
fileOut.flush();
dsk.receive(dpk);
}
if(passedlen != len)
{
System.out.printf("IP:%s发来的%s传输过程中失去连接\n",dpk.getAddress(),fileName);
file.delete();//将缺损文件删除
}
else
System.out.println("接收完成,文件存为" + filePath + "\n");
} catch (Exception e) {
System.out.println("接收消息错误" + "\n");
e.printStackTrace();
return;
}finally{
if(fileOut != null)
try {
fileOut.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(dsk != null)
dsk.close();
if(passedlen != len)
{
System.out.printf("IP:%s发来的%s传输过程中失去连接\n",dpk.getAddress(),fileName);
}
}
}
}
2、client端
package indi.tangkai.internet.udp;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
public class Client {
// 上传的文件路径,可在main函数中修改
private String filePath;
// socket服务器地址和端口号
private String host;
private int port;
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public static void main(String[] args) {
Client client = new Client();
client.setHost("127.0.0.1");
client.setPort(9005);
client.setFilePath("E:\\test\\upload\\");
client.uploadFile("test.rar");
}
/**
* 客户端文件上传
* @param fileName 文件名
*/
public void uploadFile(String fileName) {
DatagramSocket dsk = null;
DatagramPacket dpk = null;
DataInputStream fis = null;
try {
dsk = new DatagramSocket(port, InetAddress.getByName(host));
int bufferSize = 8192;
byte[] buf = new byte[bufferSize];
dpk = new DatagramPacket(buf, buf.length,new InetSocketAddress(InetAddress.getByName(host), port + 1));
// 选择进行传输的文件
File fi = new File(filePath + fileName);
System.out.println("文件长度:" + (int) fi.length());
fis = new DataInputStream(new FileInputStream(filePath + fileName));
buf = fi.getName().getBytes();
dpk.setData(buf, 0, fileName.length());
dsk.send(dpk);
String fileLen = Long.toString((long) fi.length());
buf = fileLen.getBytes();
System.out.println("buf文件长度"+new String(buf));
dpk.setData(buf, 0, fileLen.length());
dsk.send(dpk);
while (true) {
int read = 0;
if (fis != null) {
read = fis.read(buf);
}
if (read == -1) {
break;
}
dpk.setData(buf, 0, read);
dsk.send(dpk);
}
//给服务器发布一个终止信号
dpk.setData(buf, 0, 0);
dsk.send(dpk);
System.out.println("文件传输完成");
} catch (Exception e) {
System.out.println("服务器"+host+":"+port+"失去连接");
e.printStackTrace();
}finally{
try{
if(fis!=null)
fis.close();
if(dsk != null)
dsk.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
}
四、运行截图示例
1、server端
2、client端