Java如何利用Socket傳輸信息或文件
本文中的是使用TCP協(xié)議進(jìn)行文件傳輸
Socket
套接字(socket)是一個(gè)抽象層,應(yīng)用程序可以通過它發(fā)送或接收數(shù)據(jù),可對(duì)其進(jìn)行像對(duì)文件一樣的打開、讀寫和關(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、啟動(dòng)服務(wù)端,等待客戶端連接。
- 2、啟動(dòng)客戶端連接服務(wù)端。
- 3、傳輸數(shù)據(jù)。
- 4、關(guān)閉客戶端。
- 5、關(guān)閉服務(wù)端。
代碼
首先啟動(dòng)服務(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;
//向外界暴露一個(gè)端口9999的服務(wù),默認(rèn)IP為本機(jī)IP:127.0.0.1
server = new ServerSocket(9999);
//返回一個(gè)Socket對(duì)象
socket = server.accept();
/**
*
* 啟動(dòng)服務(wù)端之后,會(huì)在 server.accept(); 方法處等待客戶端的
* 連接,當(dāng)啟動(dòng)客戶端連接上服務(wù)端之后走過此方法運(yùn)行后面的代碼。
*/
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 一個(gè)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();
}
}之后啟動(dòng)客戶端
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);
}
//客戶端接收到信息返回一個(gè)標(biāo)識(shí)
// byte[] bs = new byte[100];
// input.read(bs);
// System.out.println("Client 接收到消息:" + new String(bs));
//客戶端向服務(wù)端發(fā)送一個(gè)消息
// OutputStream output = socket.getOutputStream();
// output.write("World".getBytes());
System.out.println("接收成功??!");
output.close();
input.close();
}
}這個(gè)代碼在客戶端連接一次之后,服務(wù)端便會(huì)主動(dòng)關(guān)閉。
但是在實(shí)際的使用中一般不會(huì)只使用一次服務(wù)端,將會(huì)不斷地重復(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 {
//向外界暴露一個(gè)端口9999的服務(wù),默認(rèn)IP為本機(jī)IP:127.0.0.1
ServerSocket server = new ServerSocket(9999);
while(true) {
Socket socket = server.accept();
//使用構(gòu)造方法傳入一個(gè)Socket對(duì)象與下載線程保持關(guān)聯(lián)
new Thread(new MyDownload(socket)).start();
//下載線程
/*
* MyDownload download = new MyDownload(socket);
* //Runnable變?yōu)門hered對(duì)象
* 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對(duì)象聯(lián)系
private Socket socket;
public MyDownload(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
//返回一個(gè)Socket對(duì)象
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 一個(gè)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é)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
詳解java如何實(shí)現(xiàn)帶RequestBody傳Json參數(shù)的GET請(qǐng)求
在調(diào)試Fate平臺(tái)時(shí),遇到了一個(gè)奇葩的接口類型,該接口為Get方式,入?yún)⑹且粋€(gè)json類型在body中傳遞,使用body中傳參的話為什么不用POST請(qǐng)求而使用了GET請(qǐng)求,下面我們就來深入研究一下2024-02-02
Java如何基于ProcessBuilder類調(diào)用外部程序
這篇文章主要介紹了Java如何基于ProcessBuilder類調(diào)用外部程序,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-01-01
Java 中HashCode作用_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了Java 中HashCode作用以及hashcode對(duì)于一個(gè)對(duì)象的重要性,對(duì)java中hashcode的作用相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧2017-05-05
Java基于Socket實(shí)現(xiàn)簡(jiǎn)單的多線程回顯服務(wù)器功能示例
這篇文章主要介紹了Java基于Socket實(shí)現(xiàn)簡(jiǎn)單的多線程回顯服務(wù)器功能,結(jié)合實(shí)例形式分析了java使用socket進(jìn)行多線程數(shù)據(jù)傳輸?shù)南嚓P(guān)操作技巧,需要的朋友可以參考下2017-08-08
Java實(shí)現(xiàn)圖書管理系統(tǒng)的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何利用java語言實(shí)現(xiàn)簡(jiǎn)單的圖書管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08
Java SpringMVC實(shí)現(xiàn)國際化整合案例分析(i18n)
本篇文章主要介紹了Java SpringMVC實(shí)現(xiàn)國際化整合案例分析(i18n),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05
Android內(nèi)存泄漏實(shí)戰(zhàn)解析
Java是垃圾回收語言的一種。這篇文章主要介紹了Android內(nèi)存泄漏 的相關(guān)資料,需要的朋友可以參考下2016-10-10
Java8新特性之lambda(動(dòng)力節(jié)點(diǎn)Java學(xué)院整理)
這篇文章主要介紹了Java8新特性之lambda(動(dòng)力節(jié)點(diǎn)Java學(xué)院整理)表達(dá)式的相關(guān)知識(shí),包括lambda語法方面的知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-06-06

