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

来源:互联网 发布:excel表格数据相乘 编辑:程序博客网 时间:2024/06/05 09:14

       搞软件将近三年了,回想三年来匆匆忙忙,所涉猎的东西比较驳杂,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() {@Overridepublic 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('\\'));//这里是取得文件的名称,不带路径,一般用文件分隔符,这里我偷懒了}@Overridepublic 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){//表示成功接收文件名,我自定义的返回结果为1System.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() {// 启动线程监听是否有连接上来@Overridepublic 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) {// 构造器实例化socketthis.revSocket = revSocket;}@Overridepublic 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 blocke.printStackTrace();}}}</span>



0 0
原创粉丝点击