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 ...
随机推荐
- 第一天学习oc用xcode做的一个加减乘除 圆的面积计算
#import <Foundation/Foundation.h> //这是oc的框架 @interface jisuan : NSObject //申明一个jisuan这样的类 并继 ...
- 远程连接(ssh安装)
更新源列表打开"终端窗口",输入"sudo apt-get update"-->回车-->"输入当前登录用户的管理员密码"--& ...
- Ansible9:条件语句【转】
在有的时候play的结果依赖于变量.fact或者是前一个任务的执行结果,从而需要使用到条件语句. 一.when 有的时候在特定的主机需要跳过特定的步骤,例如在安装包的时候,需要指定主机的操作系统 ...
- PMBok项目管理
这就是项目管理的九大领域:整合管理.范围管理.时间管理.费用管理.质量管理.人力资源管理.沟通管理.风险管理.采购管理. 项目管理好像一头大象,将其大卸九块之后,要装进冰箱就容易多了. 看看书上是怎样 ...
- PHP之音乐ID3扩展
不知道你有没有这样的经历,一些从网上下载的MP3音乐,文件名明明是01.02这样的序号,但播放时却能显示出歌曲的正确名称来,是不是有点奇妙? 这其实都是ID3在暗中相助 ID3,一般是位于一个mp3文 ...
- bjective-C 中核心处理字符串的类是 NSString 与 NSMutableString
Objective-C 中核心处理字符串的类是 NSString 与 NSMutableString ,这两个类最大的区别就是NSString 创建赋值以后该字符串的内容与长度不能在动态的更改,除非重 ...
- 错误 1 error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏 C:\Users\Administ
错误 1 error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏 C:\Users\Administ 这两个fatal error是因为从低版本的WTL到高版本的WTL转变后产生的 ...
- 浅谈SQL Server 对于内存的管理
简介 理解SQL Server对于内存的管理是对于SQL Server问题处理和性能调优的基本,本篇文章讲述SQL Server对于内存管理的内存原理. 二级存储(secondary storage) ...
- 织梦DEDE文章列表前面自动加递增数字标签
实现的办法很简单,只须要在序号递增的处所加上这段代码就行 [field:global runphp=""yes"" name=autoindex][/field ...
- 包(package)
防止文件重名,包体现在文件夹上.包必须建立文件夹. 类名的全称是:包名.类名 javac xx.java 命令编译的时候,不会建立对应的文件夹, 建立包对应的文件夹的命令,要用 javac -d ...