描述:html
(1)jdk自帶線程池見 JDK自帶線程池配置java
(2)此上傳文件服務器中上傳文件的後綴名經過第一段緩衝字符流傳遞,此緩衝字符流大小爲1024,在文件接收端以1024接收、處理。服務器
一、服務器代碼以下(使用jdk自帶線程池):網絡
1 /** 2 * 服務器處理多線程問題 3 * 4 * 1.由於服務器是要不少人訪問的,所以裏面必定要用多線程來處理,否則只能一我的一我的的訪問,那還叫Y啥服務器 5 * 6 * 2,拿上面這個文件上傳的例子來講,它將每一個鏈接它的用戶封裝到線程裏面去,把用戶要執行的操做定義到 run 方法裏面 7 * 一個用戶拿一個線程,拿到線程的就本身去執行,若是有其它用戶來的時候,再給新來的用戶分配一個新的線程 這樣就完成了服務器處理多線程的問題 3. 8 * 在服務器與客戶端互傳數據時,咱們要特別注意的是,防止兩個程序形成 死等的狀態,通常緣由有如下: 9 * 10 * 1. 客戶端向數據端發送數據時,當發送的是字符時,第次以一行來發送,而服務端在讀取的時候,也是以 一行來讀取,readLine() 11 * 而發送的時候每每只是發送換行以行的內容,而不能發換行也發送過去, 那麼服務端在讀取的時候就不讀取不到換行 ,那麼 readLine() 就不會中止 2. 12 * 客戶端發送數據時,若是處理的是用 字符流 或是緩衝流的話,必定要記得刷新流,否則的話,數據就會發不出來 3 在用IO 讀取文件裏面的數據而後發送到服務端 13 * 時,當家讀取文件 while(in.read()) 讀取文件結束時,而在 服務端的接收程序 14 * while(sin.read())不會接到一個發送完畢的提示,因此會一直等待下去,因此咱們在處理這 15 * 個問題的時候,還要將其發送一個文件讀取結束的標誌,告訴接收端文件已經讀取完結,不要再等待了 而socket 裏面給咱們封裝了 shutdownInput 16 * shutdownOutput 兩個操做,此能夠關閉 流,兩樣也能夠起到告訴 接收方文件傳送完畢的效果 17 * 18 * 19 * 20 * */ 21 public class Server { 22 23 private static Logger logger = LoggerFactory.getLogger(Server.class); 24 private static final Integer PORT = 2222; 25 26 27 public static void main(String args[]) throws Exception { 28 29 ServerSocket server = new ServerSocket(PORT); 30 31 logger.info("服務器啓動:::端口號爲:{}",PORT); 32 ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 20, 300, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(3), 33 new ThreadPoolExecutor.CallerRunsPolicy()); 34 35 while (true) { 36 37 Socket client = server.accept(); 38 executor.execute(new UploadThread(client)); 39 // new Thread(new UploadThread(client)).start(); 40 } 41 42 } 43 }
二、上傳文件代碼以下:多線程
package cn.iautos.manager.test.load; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.PrintStream; import java.net.Socket; import java.util.Timer; import java.util.TimerTask; public class Upload { public static void main(String args[]) throws Exception { Timer timer = new Timer(); timer.schedule(new TimerTask() { public void run() { try { System.out.println("--------開始上傳文件-------"); loadMethod(); } catch (Exception e) { e.printStackTrace(); } } }, 0, 500); } public static void loadMethod() throws Exception{ String name = "E:\\qqq.jpg"; Socket client = new Socket("127.0.0.1", 2222); File file = new File(name); String imgSuffix = ImgUtils.getImgSuffix(name); BufferedInputStream fin = new BufferedInputStream(new FileInputStream( file)); // 文件讀取流 PrintStream sout = new PrintStream(client.getOutputStream(), true); // 獲得socket流 /** * 添加後綴名 */ byte[] b = new byte[1024]; byte[] bb = (imgSuffix+"\n").getBytes(); for(int j = 0;j<bb.length;j++){ b[j] = bb[j]; } sout.write(b,0,b.length); int len = 0; while ((len = fin.read(b)) != -1) { sout.write(b, 0, len); System.out.println(len + "...發送中"); } client.shutdownOutput(); BufferedInputStream sin = new BufferedInputStream(client .getInputStream()); len = sin.read(b); System.out.println(len); System.out.println(new String(b, 0, len)); sin.close(); sout.close(); fin.close(); } }
三、接收文件代碼以下:socket
package cn.iautos.manager.test.load; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.PrintStream; import java.net.Socket; public class UploadThread implements Runnable // 將上傳封裝到線程裏 { private Socket client; public UploadThread(Socket s) { this.client = s; } public void run() { // String ip = client.getInetAddress().getHostAddress(); // 獲得 IP地址 try { BufferedInputStream sin = new BufferedInputStream(client.getInputStream()); // Socket 讀取流 byte b[] = new byte[1024]; int l = sin.read(b); String line = new String(b, 0, l).split("\n")[0]; System.out.println("--------文件後綴爲------"+line); File file = new File("E:\\loadServer\\" + ImgUtils.getImgName() + line); BufferedOutputStream fout = new BufferedOutputStream( new FileOutputStream(file)); // 文件輸出流 int len = 0; // 開始從網絡中讀取數據 while (true) { len = sin.read(b); if(len != -1){ fout.write(b, 0, len); }else{ break; } // System.out.println("--------------"+new String(buf,0,len)); } PrintStream sout = new PrintStream(client.getOutputStream()); sout.write("發送成功".getBytes()); // sout.flush(); //雖然是字節流,但其用的是BufferedOutputStream fout.close(); sin.close(); sout.close(); } catch (Exception ex) { System.out.println(); ex.printStackTrace(); } } }