java网络编程实例2.1——用阻塞+线程池实现的文件传输客户端
来源:互联网 发布:大闹天宫美人神兵数据 编辑:程序博客网 时间:2024/05/24 02:14
【任务】
写一个文件传输服务器和客户端。客户端用“GET 文件名”和“PUT 文件名”请求下载或上传文件。
这里要自定义文件传输协议。每传输一个文件都新建立一个连接,首先是客户端发送请求长度和请求内容,接着服务器根据自身情况向发送响应长度和响应内容,然后文件的发送方发送文件长度和文件内容,最后关闭连接。
为了能够练习尽量多的知识点,客户端用的是阻塞通信+线程池来实现的,服务端用的是非阻塞通信实现的。
现在的代码已经能正常行使功能,只是健壮性不强,所以还不完美。
【客户端代码】
package c_transfer_file;import java.io.*;public class App{public static void main(String[] args) throws IOException, InterruptedException{new ClientTransferFile("localhost").work();}}
package c_transfer_file;import java.io.*;import java.util.concurrent.*;public class ClientTransferFile//文件传输客户端{String serverName;//服务器名BufferedReader keyboardIn;//键盘输入流ExecutorService threadPool;//线程池public ClientTransferFile(String serverName){this.serverName = serverName;keyboardIn = new BufferedReader(new InputStreamReader(System.in));//获得键盘输入流threadPool = Executors.newCachedThreadPool();//创建线程池}public void work() throws IOException, InterruptedException{/*********工作循环*********/while(true){/*********从键盘获取并解析用户要求*********/String command = keyboardIn.readLine();String command_up = command.toUpperCase();if(command_up.equals("Q"))break;else if(command_up.startsWith("GET ")){String fileName = command.substring(4);threadPool.submit(new TaskGetFile(serverName,fileName));}else if(command_up.startsWith("PUT ")){String fileName = command.substring(4);threadPool.submit(new TaskPutFile(serverName,fileName));}elseSystem.out.println(command+"是未定义的命令");/*********从键盘获取并解析用户要求*********/}/*********工作循环*********/keyboardIn.close();/*********关闭线程池*********/threadPool.shutdownNow();if(!threadPool.awaitTermination(30,TimeUnit.SECONDS)){threadPool.shutdownNow();System.out.println("强制关闭了线程池");}/*********关闭线程池*********/}}
package c_transfer_file;import java.util.concurrent.*;import java.io.*;import java.nio.channels.*;import java.nio.charset.*;import java.net.*;public class TaskGetFile implements Callable<Object>//线程任务:下载文件{String serverName;//服务器名String fileName;//下载文件的名称public TaskGetFile(String serverName, String fileName){this.serverName = serverName;this.fileName = fileName;}public Object call() throws IOException//线程任务的流程{/*********建立连接*********/InetSocketAddress serverPort = new InetSocketAddress(serverName, 5299);//服务器端口地址SocketChannel socketChannel;try{socketChannel = SocketChannel.open(serverPort);}//建立连接catch(UnsupportedAddressTypeException e){System.out.println(serverName+"是不支持的地址类型");return null;}catch(UnresolvedAddressException e){System.out.println("无法解析地址"+serverName);return null;}catch(ConnectException e){System.out.println(serverName+"拒绝了连接请求");return null;}//这里不要把SocketChannel关掉,因为SocketChannel还不存在/*********建立连接*********//*********获得网络输入输出流*********/Socket socket = socketChannel.socket();DataInputStream socketIn = new DataInputStream(new BufferedInputStream(socket.getInputStream()));DataOutputStream socketOut = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));/*********获得网络输入输出流*********//*********发送请求*********/byte[] requestBytes = ("GET "+fileName).getBytes(Charset.forName("utf-8"));socketOut.writeInt(requestBytes.length);socketOut.write(requestBytes);socketOut.flush();/*********发送请求*********//*********接收响应信息*********/int responseLen = socketIn.readInt();//响应信息的长度byte[] responseBytes = new byte[responseLen];//用于接收响应信息的字节数组socketIn.read(responseBytes);String response = new String(responseBytes, Charset.forName("utf-8"));//响应信息if(!response.equals("OK"))//如果响应信息表示没法下载{System.out.println(response);socketChannel.close();return null;}/*********接收响应信息*********//*********创建写文件流*********/BufferedOutputStream writeFileStream;try{writeFileStream = new BufferedOutputStream(new FileOutputStream(fileName));}catch(FileNotFoundException e){System.out.println("无法创建文件"+fileName);socketChannel.close();return null;}/*********创建写文件流*********//*********下载和转存文件*********/int fileLen = socketIn.readInt();//文件长度for(int i = 0; i < fileLen; i++)writeFileStream.write(socketIn.read());writeFileStream.flush();writeFileStream.close();/*********下载和转存文件*********/System.out.println("文件"+fileName+"下载完成");socketChannel.close();//断开连接return null;}}
package c_transfer_file;import java.util.concurrent.*;import java.io.*;import java.nio.charset.*;import java.net.*;import java.nio.channels.*;public class TaskPutFile implements Callable<Object>//线程任务:上传文件{String serverName;//服务器名String fileName;//上传文件的名称public TaskPutFile(String serverName, String fileName){this.serverName = serverName;this.fileName = fileName;}public Object call() throws IOException//线程任务的流程{/*********创建读文件流*********/BufferedInputStream readFileStream;try{readFileStream = new BufferedInputStream(new FileInputStream(fileName));}catch(FileNotFoundException e){System.out.println("文件"+fileName+"不存在");return null;}/*********创建读文件流*********//*********建立连接*********/InetSocketAddress serverPort = new InetSocketAddress(serverName, 5299);//服务器端口地址SocketChannel socketChannel;try{socketChannel = SocketChannel.open(serverPort);}//建立连接catch(UnsupportedAddressTypeException e){System.out.println(serverName+"是不支持的地址类型");readFileStream.close();return null;}catch(UnresolvedAddressException e){System.out.println("无法解析地址"+serverName);readFileStream.close();return null;}catch(ConnectException e){System.out.println(serverName+"拒绝了连接请求");readFileStream.close();return null;}//这里不要把SocketChannel关掉,因为SocketChannel还不存在/*********建立连接*********//*********获得网络输入输出流*********/Socket socket = socketChannel.socket();DataInputStream socketIn = new DataInputStream(new BufferedInputStream(socket.getInputStream()));DataOutputStream socketOut = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));/*********获得网络输入输出流*********//*********发送请求*********/byte[] requestBytes = ("PUT "+fileName).getBytes(Charset.forName("utf-8"));socketOut.writeInt(requestBytes.length);socketOut.write(requestBytes);socketOut.flush();/*********发送请求*********//*********接收响应信息*********/int responseLen = socketIn.readInt();//响应信息的长度byte[] responseBytes = new byte[responseLen];//用于接收响应信息的字节数组socketIn.read(responseBytes);String response = new String(responseBytes, Charset.forName("utf-8"));//响应信息if(!response.equals("OK"))//如果响应信息表示没法上传{System.out.println(response);socketChannel.close();readFileStream.close();return null;}/*********接收响应信息*********//*********读取和上传文件*********/int fileLen = readFileStream.available();//文件长度socketOut.writeInt(fileLen);for(int i = 0; i < fileLen; i++)socketOut.write(readFileStream.read());socketOut.flush();readFileStream.close();/*********读取和上传文件*********/socketChannel.close();//断开连接System.out.println("文件"+fileName+"上传完成");return null;}}未完待续
0 0
- java网络编程实例2.1——用阻塞+线程池实现的文件传输客户端
- java网络编程实例2.2——用非阻塞通信实现的文件传输服务器
- 实例:网络聊天和文件传输的实现
- java网络编程实现客户端连接服务器端,并发送消息例子(1)。(阻塞式的方法)
- java网络编程实例1——用socket类写http客户端
- socket网络编程之多线程阻塞IO实例
- Python 网络编程---简单的服务器与客户端实现---阻塞式编写
- Unix网络编程学习日记(一):半双工非阻塞socket客户端的实现
- Java网络编程——使用NIO实现非阻塞Socket通信
- Java网络编程——使用NIO实现非阻塞Socket通信
- Java网络编程——使用NIO实现非阻塞Socket通信
- 网络编程——TCP文件传输
- 书:深入理解计算机系统(P649) 之 并发编程:用socket实现多客户端的文件传输
- Socket网络编程简单实例Demo,文件传输。
- Java线程——线程池结合网络编程
- 网络编程 基于Socket的多文件传输程序实现(一)
- 基于网络编程的文件传输
- java网络编程----------Socket实现客户端和服务器的连接
- poj 1679 The Unique MST(图论:最小生成树)
- 玩转JPA(一)---异常:Repeated column in mapping for entity/should be mapped with insert="false" update="fal
- java基础测试(面向对象之前)
- .net的session详解
- 签到应用总结
- java网络编程实例2.1——用阻塞+线程池实现的文件传输客户端
- 2014 Multi-University Training Contest 1--by FZU 解题报告
- 根据屏幕大小自适应字体大小
- 日记之php程序调试
- STM32开发指南笔记(前言)
- gsm 收发短信 打电话
- eclipse中tomcat内存溢出设置
- linux中grep和egrep的用法1
- 同步互斥阻塞