java socket 多线程网络传输多个文件
http://blog.csdn.net/njchenyi/article/details/9072845


由于需要研究了下用 java socket 传输文件,由于需要传输多个文件,因此,采用了多线程设计。客户端每个线程创建一个 socket 连接,每个 socket 连接负责传输一个文件,服务端的ServerSocket每次 accept 一个 socket 连接,创建一个线程用于接收客户端传来的文件。
1、服务端
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TransferServer {
private int defaultBindPort = Constants.DEFAULT_BIND_PORT; //默认监听端口号为10000
private int tryBindTimes = 0; //初始的绑定端口的次数设定为0
private ServerSocket serverSocket; //服务套接字等待对方的连接和文件发送
private ExecutorService executorService; //线程池
private final int POOL_SIZE = 4; //单个CPU的线程池大小
/**
* 不带参数的构造器,选用默认的端口号
* @throws Exception
*/
public TransferServer() throws Exception{
try {
this.bingToServerPort(defaultBindPort);
executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * POOL_SIZE);
System.out.println("开辟线程数 : " + Runtime.getRuntime().availableProcessors() * POOL_SIZE);
} catch (Exception e) {
throw new Exception("绑定端口不成功!");
}
}
/**
* 带参数的构造器,选用用户指定的端口号
* @param port
* @throws Exception
*/
public TransferServer(int port) throws Exception{
try {
this.bingToServerPort(port);
executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * POOL_SIZE);
} catch (Exception e) {
throw new Exception("绑定端口不成功!");
}
}
private void bingToServerPort(int port) throws Exception{
try {
serverSocket = new ServerSocket(port);
System.out.println(port);
System.out.println("服务启动!");
} catch (Exception e) {
this.tryBindTimes = this.tryBindTimes + 1;
port = port + this.tryBindTimes;
if(this.tryBindTimes >= 20){
throw new Exception("您已经尝试很多次了,但是仍无法绑定到指定的端口!请重新选择绑定的默认端口号");
}
//递归绑定端口
this.bingToServerPort(port);
}
}
public void service(){
Socket socket = null;
while (true) {
try {
socket = serverSocket.accept();
executorService.execute(new Handler(socket));
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Handler implements Runnable{
private Socket socket;
public Handler(Socket socket){
this.socket = socket;
}
public void run() {
System.out.println("New connection accepted " + socket.getInetAddress() + ":" + socket.getPort());
DataInputStream dis = null;
DataOutputStream dos = null;
int bufferSize = 8192;
byte[] buf = new byte[bufferSize];
try {
dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
String savePath = Constants.RECEIVE_FILE_PATH + dis.readUTF();
long length = dis.readLong();
dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(savePath)));
int read = 0;
long passedlen = 0;
while ((read = dis.read(buf)) != -1) {
passedlen += read;
dos.write(buf, 0, read);
System.out.println("文件[" + savePath + "]已经接收: " + passedlen * 100L/ length + "%");
}
System.out.println("文件: " + savePath + "接收完成!");
} catch (Exception e) {
e.printStackTrace();
System.out.println("接收文件失败!");
}finally{
try {
if(dos != null){
dos.close();
}
if(dis != null){
dis.close();
}
if(socket != null){
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws Exception{
new TransferServer().service();
}
}
2、客户端
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Random;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TransferClient {
private static ArrayList<String> fileList = new ArrayList<String>();
private String sendFilePath = Constants.SEND_FILE_PATH;
/**
* 带参数的构造器,用户设定需要传送文件的文件夹
* @param filePath
*/
public TransferClient(String filePath){
getFilePath(filePath);
}
/**
* 不带参数的构造器。使用默认的传送文件的文件夹
*/
public TransferClient(){
getFilePath(sendFilePath);
}
public void service(){
ExecutorService executorService = Executors.newCachedThreadPool();
Vector<Integer> vector = getRandom(fileList.size());
for(Integer integer : vector){
String filePath = fileList.get(integer.intValue());
executorService.execute(sendFile(filePath));
}
}
private void getFilePath(String dirPath){
File dir = new File(dirPath);
File[] files = dir.listFiles();
if(files == null){
return;
}
for(int i = 0; i < files.length; i++){
if(files[i].isDirectory()){
getFilePath(files[i].getAbsolutePath());
}
else {
fileList.add(files[i].getAbsolutePath());
}
}
}
private Vector<Integer> getRandom(int size){
Vector<Integer> v = new Vector<Integer>();
Random r = new Random();
boolean b = true;
while(b){
int i = r.nextInt(size);
if(!v.contains(i))
v.add(i);
if(v.size() == size)
b = false;
}
return v;
}
private static Runnable sendFile(final String filePath){
return new Runnable(){
private Socket socket = null;
private String ip ="localhost";
private int port = 10000;
public void run() {
System.out.println("开始发送文件:" + filePath);
File file = new File(filePath);
if(createConnection()){
int bufferSize = 8192;
byte[] buf = new byte[bufferSize];
try {
DataInputStream fis = new DataInputStream(new BufferedInputStream(new FileInputStream(filePath)));
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.writeUTF(file.getName());
dos.flush();
dos.writeLong(file.length());
dos.flush();
int read = 0;
int passedlen = 0;
long length = file.length(); //获得要发送文件的长度
while ((read = fis.read(buf)) != -1) {
passedlen += read;
System.out.println("已经完成文件 [" + file.getName() + "]百分比: " + passedlen * 100L/ length + "%");
dos.write(buf, 0, read);
}
dos.flush();
fis.close();
dos.close();
socket.close();
System.out.println("文件 " + filePath + "传输完成!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
private boolean createConnection() {
try {
socket = new Socket(ip, port);
System.out.println("连接服务器成功!");
return true;
} catch (Exception e) {
System.out.println("连接服务器失败!");
return false;
}
}
};
}
public static void main(String[] args){
new TransferClient().service();
}
}
3、常量类
public interface Constants {
public final static String RECEIVE_FILE_PATH = "E:\\receive\\";
public final static String SEND_FILE_PATH = "E:\\send";
public final static int DEFAULT_BIND_PORT = 10000;
}
java socket 多线程网络传输多个文件的更多相关文章
- java Socket多线程聊天程序
参考JAVA 通过 Socket 实现 TCP 编程 参考java Socket多线程聊天程序(适合初学者) 以J2SDK-1.3为例,Socket和ServerSocket类库位于java.net包 ...
- Java中HTTP网络传输中文编码问题
Java中HTTP网络传输中文编码问题 1.java中new String(str.getBytes("utf-8"),"iso-8859-1")编码详解 前提 ...
- python+socket实现网络信息交互及文件传输
Socket 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket. Socket又称"套接字",应用程序通常通过"套接字" ...
- Java Socket编程----网络基础
详见:https://www.cnblogs.com/rocomp/p/4790340.html Java最初是作为网络编程语言出现的,其对网络提供了高度的支持,使得客户端和服务器的沟通变成了现实,而 ...
- java--基于socket的网络传输开发
继http://blog.csdn.net/gaopeng0071/article/details/10959845此文章内容展开的研究. socket传输是基于tcp的网络传输协议进行的传输,tcp ...
- Java Socket通讯---网络基础
java socket 通讯 参考慕课网:http://www.imooc.com/learn/161 一.网络基础知识 1.1 通讯示意图 1.2 TCP/IP协议 TCP/IP是世界上应用最为广泛 ...
- java socket编程(网络编程)
一,网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输. 在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可 ...
- Java Socket 多线程聊天室
本来这次作业我是想搞个图形界面的,然而现实情况是我把题意理解错了,于是乎失去了最初的兴致,还是把程序变成了功能正确但是“UI”不友好的console了,但是不管怎么样,前期的图形界面的开发还是很有收获 ...
- Java Socket实战之三 传输对象
首先需要一个普通的对象类,由于需要序列化这个对象以便在网络上传输,所以实现java.io.Serializable接口就是必不可少的了,入下: public class User implements ...
随机推荐
- JqGrid动态改变列名
setLabel colname, data, class, properties jqGrid对象 给指定列设置一个新的显示名称.colname:列名称,也可以是列的位置索引,从0开始:data:列 ...
- what a malloc has to do
1) Allocate a chunk of memory big enough to satisfy the request, and return a pointer to it.2) Remem ...
- docker 基础命令
检查Docker安装是否正确docker info拉取镜像docker pull (image name)启动docker run -d -d 后台运行查看日志docker logs $sample_ ...
- 其它网页可以上网,IE浏览器打不开网页的解决办法
下面是自己引用别人的,作为自己的备注 昨天由于安装了多款软件,今天开机发现IE浏览器打不开了,废了些周折终于,修复了IE浏览器,现将ie浏览器打不开网页的经验分享给大家,希望此经验对于出现过此类情况的 ...
- wpf计时器
wpf应用程序间隔一段时间触发一个事件,代码如下: public MainWindow() { InitializeComponent(); DispatcherTimer timer = new D ...
- Htttp协议
我 们在浏览器的地址栏里输入的网站地址叫做URL(UniformResourceLocator,统一资源定位符).就像每家每户都有一个门牌地址一样, 每个网页也都有一个Internet地址.当你在浏览 ...
- java设计模式案例详解:工厂模式
1.简单工厂模式 在不考虑扩展的情况下还是很好用的,其实我们写代码也很经常用到,其主要理解在于传入不同参数则构建不同对象,只有一个工厂,如需添加产品涉及到扩展需要修改比较多的东西,不符合开闭原则,如下 ...
- 初探JavaScript魅力(四)
选项卡 <title>无标题文档</title> <style> #div1 .active{background:#FF0;} #div1 div{width:2 ...
- static加载问题
原文地址:http://blog.csdn.net/lubiaopan/article/details/4802430 感谢原作者! static{}(即static块),会在类被加载的时候执 ...
- IDL 建立影像金字塔
形成按目录放好的,类似于Google Map Tile的金字塔瓦片Jpg. 1: ; 2: pro tsplit 3: ; 读入Jpeg格式文件 4: szFile = 'e:\test.jpg'; ...