Java如何利用Socket傳輸信息或文件
本文中的是使用TCP協(xié)議進(jìn)行文件傳輸
Socket
套接字(socket)是一個抽象層,應(yīng)用程序可以通過它發(fā)送或接收數(shù)據(jù),可對其進(jìn)行像對文件一樣的打開、讀寫和關(guān)閉等操作。
套接字允許應(yīng)用程序?qū)/O插入到網(wǎng)絡(luò)中,并與網(wǎng)絡(luò)中的其他應(yīng)用程序進(jìn)行通信。網(wǎng)絡(luò)套接字是IP地址與端口的組合。
信息與文件傳輸使用C/S(Client/Server)。
步驟
- 1、啟動服務(wù)端,等待客戶端連接。
- 2、啟動客戶端連接服務(wù)端。
- 3、傳輸數(shù)據(jù)。
- 4、關(guān)閉客戶端。
- 5、關(guān)閉服務(wù)端。
代碼
首先啟動服務(wù)端
package priv.zb.socket; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class FileServer { @SuppressWarnings("resource") public static void main(String[] args) throws IOException { ServerSocket server = null; Socket socket = null; //向外界暴露一個端口9999的服務(wù),默認(rèn)IP為本機(jī)IP:127.0.0.1 server = new ServerSocket(9999); //返回一個Socket對象 socket = server.accept(); /** * * 啟動服務(wù)端之后,會在 server.accept(); 方法處等待客戶端的 * 連接,當(dāng)啟動客戶端連接上服務(wù)端之后走過此方法運行后面的代碼。 */ System.out.println("接收到客戶端的連接"); //服務(wù)端向客戶端發(fā)送消息 通過OutputStream //發(fā)出信息使用輸出流OutputStream,接收信息使用輸入咯InputStream OutputStream output = socket.getOutputStream(); //傳輸字符串 // byte[] bs = new byte[100]; // output.write("Hello".getBytes()); //傳輸文件 String filePath = "存放文件路徑"; File file = new File(filePath ); byte[] fileBytes = new byte[100]; //定義文件每次發(fā)送大小 //讀入到內(nèi)存中,new 一個inputStream即可 //文件較大,不能一次性發(fā)送完畢,因此需要循環(huán)操作 InputStream fileIn = new FileInputStream(file); int len = -1; while((len = fileIn.read(fileBytes)) != -1) { output.write(fileBytes, 0, len); } //接受客戶端消息 // InputStream in = socket.getInputStream(); // in.read(bs); // System.out.println("Server接收到信息:" + new String(bs)); System.out.println("發(fā)送成功"); output.close(); fileIn.close(); } }
之后啟動客戶端
package priv.zb.socket; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; public class FileClient { @SuppressWarnings("resource") public static void main(String[] args) throws UnknownHostException, IOException { //建立連接 //客戶端訪問服務(wù)端發(fā)布的服務(wù) Socket socket = new Socket("192.168.0.108",9999); //通過InputStream接收信息 InputStream input = socket.getInputStream(); byte[] fileBytes = new byte[100]; File file = new File("E:\\JAVA\\Java SE\\srcCopy.zip"); OutputStream output = new FileOutputStream(file); int len = -1; while( (len = input.read(fileBytes)) != -1) { output.write(fileBytes, 0, len); } //客戶端接收到信息返回一個標(biāo)識 // byte[] bs = new byte[100]; // input.read(bs); // System.out.println("Client 接收到消息:" + new String(bs)); //客戶端向服務(wù)端發(fā)送一個消息 // OutputStream output = socket.getOutputStream(); // output.write("World".getBytes()); System.out.println("接收成功?。?); output.close(); input.close(); } }
這個代碼在客戶端連接一次之后,服務(wù)端便會主動關(guān)閉。
但是在實際的使用中一般不會只使用一次服務(wù)端,將會不斷地重復(fù)連接服務(wù)端這一過程。
因此使用while(true)死循環(huán)來保持服務(wù)端的始終開啟,利用多線程來解決這一問題。
優(yōu)化
使用多線程是在服務(wù)端
服務(wù)端
package priv.zb.socket.runable; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class FileServer { @SuppressWarnings("resource") public static void main(String[] args) throws IOException { //向外界暴露一個端口9999的服務(wù),默認(rèn)IP為本機(jī)IP:127.0.0.1 ServerSocket server = new ServerSocket(9999); while(true) { Socket socket = server.accept(); //使用構(gòu)造方法傳入一個Socket對象與下載線程保持關(guān)聯(lián) new Thread(new MyDownload(socket)).start(); //下載線程 /* * MyDownload download = new MyDownload(socket); * //Runnable變?yōu)門hered對象 * new Thread(download).start(); */ } } }
下載線程:MyDownload.java
package priv.zb.socket.runable; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; public class MyDownload implements Runnable { //Mydownload.java與Server之間使用Socket對象聯(lián)系 private Socket socket; public MyDownload(Socket socket) { this.socket = socket; } @Override public void run() { //返回一個Socket對象 OutputStream output =null; InputStream fileIn = null; try { System.out.println("接收到客戶端的連接"); //服務(wù)端向客戶端發(fā)送消息 通過OutputStream File file = new File("E:\\JAVA\\Java SE\\src.zip"); byte[] fileBytes = new byte[100]; //定義文件每次發(fā)送大小 //讀入到內(nèi)存中,new 一個inputStream即可 //文件較大,不能一次性發(fā)送完畢,因此需要循環(huán)操作 fileIn = new FileInputStream(file); int len = -1; output = socket.getOutputStream(); while((len = fileIn.read(fileBytes)) != -1) { output.write(fileBytes, 0, len); } System.out.println("發(fā)送成功"); } catch (IOException e1) { e1.printStackTrace(); } finally { try { if(output != null) output.close(); if(fileIn != null) fileIn.close(); } catch (IOException e) { e.printStackTrace(); } } } }
之后即可多次傳輸信息不關(guān)閉服務(wù)端。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
詳解java如何實現(xiàn)帶RequestBody傳Json參數(shù)的GET請求
在調(diào)試Fate平臺時,遇到了一個奇葩的接口類型,該接口為Get方式,入?yún)⑹且粋€json類型在body中傳遞,使用body中傳參的話為什么不用POST請求而使用了GET請求,下面我們就來深入研究一下2024-02-02Java如何基于ProcessBuilder類調(diào)用外部程序
這篇文章主要介紹了Java如何基于ProcessBuilder類調(diào)用外部程序,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-01-01Java 中HashCode作用_動力節(jié)點Java學(xué)院整理
這篇文章主要介紹了Java 中HashCode作用以及hashcode對于一個對象的重要性,對java中hashcode的作用相關(guān)知識感興趣的朋友一起學(xué)習(xí)吧2017-05-05Java基于Socket實現(xiàn)簡單的多線程回顯服務(wù)器功能示例
這篇文章主要介紹了Java基于Socket實現(xiàn)簡單的多線程回顯服務(wù)器功能,結(jié)合實例形式分析了java使用socket進(jìn)行多線程數(shù)據(jù)傳輸?shù)南嚓P(guān)操作技巧,需要的朋友可以參考下2017-08-08Java SpringMVC實現(xiàn)國際化整合案例分析(i18n)
本篇文章主要介紹了Java SpringMVC實現(xiàn)國際化整合案例分析(i18n),具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-05-05Java8新特性之lambda(動力節(jié)點Java學(xué)院整理)
這篇文章主要介紹了Java8新特性之lambda(動力節(jié)點Java學(xué)院整理)表達(dá)式的相關(guān)知識,包括lambda語法方面的知識,非常不錯,具有參考借鑒價值,需要的朋友參考下吧2017-06-06