您的位置:首页 > 编程语言 > Java开发

Java关于个人对于Socket的理解,Socket多线程批量上传文件,适合新手

2015-01-03 00:39 691 查看

搞软件将近三年了,回想三年来匆匆忙忙,所涉猎的东西比较驳杂,Java、android、c#、ios,当回首望去才发现,原来,想要真正精通一门语言其实还是比较困难的,因此,在今天终于是开了博客,希望能够记住自己偶尔的感悟和一些编程思想,同时,也希望能够帮助更多的人进入软件行业,同为程序员,大家互相交流新得,这样才能不断的进步,程序员的大家庭才能更轻松,若本人所写东西有不得当之处,希望五湖四海的朋友能够不吝指导,谢谢。


话不多说,直接贴代码:

客户端:

<span style="color:#000000;">package com.qzf.socket;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class SocketClient {

private static List<String> fQuene = new ArrayList<String>();// 文件路径的消息队列

public static void main(String[] args) {
fQuene.add("E:\\2013-12-08-2.bmp");
fQuene.add("E:\\U盘备份\\111726邱振飞_数据结构.rar");
fQuene.add("F:\\music\\BEYOND - 光辉岁月.mp3");
fQuene.add("F:\\迅雷下载\\MB855tools.zip");
fQuene.add("d:\\Mavericks.cdr");
new Thread(new Runnable() {

@Override
public void run() {// 开启遍历消息队列的线程检查消息队列中是否有文件需要上传
try {
while (true) {
Thread.sleep(200);
if (!fQuene.isEmpty()) {
String fName = fQuene.remove(0);
if (new File(fName).exists()) {
sendFile(fName);
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();

}

static int i = 0;

static void sendFile(String fName) {
Socket sendSocket = null;
try {
sendSocket = new Socket(Configs.SERVER_IP, Configs.SERVER_PORT);
new SendThread(sendSocket, "thread-" + ++i, fName).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}

class SendThread extends Thread {
private Socket socket;
private String fName;
private String fNameTemp;

public SendThread(Socket socket, String name, String fName) {
this.socket = socket;
this.setName(name);
this.fName = fName;
this.fNameTemp= fName.substring(fName.lastIndexOf('\\'));//这里是取得文件的名称,不带路径,一般用文件分隔符,这里我偷懒了
}

@Override
public void run() {
try {
Thread.sleep(1000);
OutputStream os = socket.getOutputStream();
os.write(fNameTemp.getBytes("utf-8"));//将文件名称发送过去
InputStream is = socket.getInputStream();
byte[] revBuff = new byte[1];
is.read(revBuff);//接收服务端传回的握手结果
int result = revBuff[0];//自行处理,可以不处理,但是要read握手结果,表示对方已经接收到文件名称
System.out.println(result);
if(result == 1){//表示成功接收文件名,我自定义的返回结果为1
System.out.println("start send file:" + fName);
File sendFile = new File(fName);
FileInputStream fis = new FileInputStream(sendFile);
byte[] buffer = new byte[Configs._BUFFER_SIZE];
int fLen = (int)sendFile.length();//文件大小
//接下来打包发送文件,将字节数组的前四个字节放置文件的大小,当然,也可以像前面一样握手,这里不再进行握手
byte[] fLenBuff = Utils.int2bytes(fLen);
for(int i=0; i<fLenBuff.length; i++){
//将文件大小放到传送的缓存数组中,待发送,这里就是简单的自定义传输协议了,包头4个字节放文件大小,后面是文件内容
//实际操作中,我们都是这么组包的,文件名等内容也是一起组包的,不过为了方便理解,这里介绍了握手操作,以及read这个
//阻塞方法的应用,其实都是自定义传输协议,不过,如果商用,就是组协议包,这样比较通用,理解之后,随便自定义
buffer[i] = fLenBuff[i];
}
//sendLen 记录已经发送的字节数,可用于断点续传,也可用来标识上传进度
int read, sendLen = fis.read(buffer, fLenBuff.length, buffer.length - fLenBuff.length);
os.write(buffer);
sendLen += fLenBuff.length;
while((read = fis.read(buffer, 0, buffer.length)) > 0){//循环发送输入流读取到的数据
sendLen += read;
os.write(buffer, 0, read);
if(sendLen == fLen)//发送完成
break;
}
byte[] overOuffer = new byte[1024];
int overLen = is.read(overOuffer);
System.out.println("send over:" + new String(overOuffer, 0, overLen, "utf-8"));
os.close();
fis.close();
is.close();
socket.close();
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}</span>

服务端:

<span style="color:#000000;">package com.qzf.socket;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class SocketReceiveServer {

private static ServerSocket linstener = null;
private static boolean isRunning = false;

public static void main(String[] args) {
isRunning = true;
new Thread(new Runnable() {// 启动线程监听是否有连接上来

@Override
public void run() {
try {
linstener = new ServerSocket(Configs.SERVER_PORT);
System.out.println("准备就绪..");
} catch (IOException e) {
System.out.println("linstenner exception:"
+ e.toString());
}

while (isRunning) {
try {
Thread.sleep(90);
Socket socket = linstener.accept();// 阻塞监听,获取socket实例
System.out.println("有新连接上来..");
new ReceiveThread(socket).start();// 开启新线程处理socket的数据
} catch (InterruptedException e) {
} catch (IOException e) {
}
}

}
}).start();
}
}

class ReceiveThread extends Thread {
private Socket revSocket = null;

public ReceiveThread(Socket revSocket) {// 构造器实例化socket
this.revSocket = revSocket;
}

@Override
public void run() {
System.out.println("接收线程开始启动");
byte[] buffer = new byte[Configs._BUFFER_SIZE];
// 接收到的字节数
InputStream is;
OutputStream os ;
try {
is = revSocket.getInputStream();
os = revSocket.getOutputStream();
int received = is.read(buffer);
if (received > 0) {
String fName = new String(buffer, 0 , received, "utf-8");
System.out.println("开始接受:" + fName);
os.write(new byte[]{1});//返回握手结果1
// length文件的长度,receive已接收的文件长度
is.read(buffer);
int receive, length = Utils.bytes2int(buffer);//将收到的数组前四字节转化得到文件大小
System.out.println(fName + " size:" + length + " B");
FileOutputStream fos = new FileOutputStream(new File(Configs.TEST_ROOT_DIR + fName));
fos.write(buffer, 4, buffer.length - 4);//这边的-4指的 是客户端发过来的文件大小的4个字节
received = buffer.length - 4;
while((receive = is.read(buffer, 0, buffer.length)) > 0){
fos.write(buffer, 0, receive);
received += receive;
if(received == length){//接收完毕
os.write((fName + " Recevice OK.").getBytes("utf-8"));//发送接收成功给客户端
break;
}
}
System.out.println("rev over");
fos.close();
is.close();
os.close();
revSocket.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
}
</span>



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: