Java如何利用Socket傳輸信息或文件
本文中的是使用TCP協(xié)議進行文件傳輸
Socket
套接字(socket)是一個抽象層,應用程序可以通過它發(fā)送或接收數(shù)據(jù),可對其進行像對文件一樣的打開、讀寫和關閉等操作。
套接字允許應用程序將I/O插入到網(wǎng)絡中,并與網(wǎng)絡中的其他應用程序進行通信。網(wǎng)絡套接字是IP地址與端口的組合。
信息與文件傳輸使用C/S(Client/Server)。
步驟
- 1、啟動服務端,等待客戶端連接。
- 2、啟動客戶端連接服務端。
- 3、傳輸數(shù)據(jù)。
- 4、關閉客戶端。
- 5、關閉服務端。
代碼
首先啟動服務端
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的服務,默認IP為本機IP:127.0.0.1
server = new ServerSocket(9999);
//返回一個Socket對象
socket = server.accept();
/**
*
* 啟動服務端之后,會在 server.accept(); 方法處等待客戶端的
* 連接,當啟動客戶端連接上服務端之后走過此方法運行后面的代碼。
*/
System.out.println("接收到客戶端的連接");
//服務端向客戶端發(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ā)送大小
//讀入到內存中,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 {
//建立連接
//客戶端訪問服務端發(fā)布的服務
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);
}
//客戶端接收到信息返回一個標識
// byte[] bs = new byte[100];
// input.read(bs);
// System.out.println("Client 接收到消息:" + new String(bs));
//客戶端向服務端發(fā)送一個消息
// OutputStream output = socket.getOutputStream();
// output.write("World".getBytes());
System.out.println("接收成功!!");
output.close();
input.close();
}
}這個代碼在客戶端連接一次之后,服務端便會主動關閉。
但是在實際的使用中一般不會只使用一次服務端,將會不斷地重復連接服務端這一過程。
因此使用while(true)死循環(huán)來保持服務端的始終開啟,利用多線程來解決這一問題。
優(yōu)化
使用多線程是在服務端
服務端
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的服務,默認IP為本機IP:127.0.0.1
ServerSocket server = new ServerSocket(9999);
while(true) {
Socket socket = server.accept();
//使用構造方法傳入一個Socket對象與下載線程保持關聯(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("接收到客戶端的連接");
//服務端向客戶端發(fā)送消息 通過OutputStream
File file = new File("E:\\JAVA\\Java SE\\src.zip");
byte[] fileBytes = new byte[100]; //定義文件每次發(fā)送大小
//讀入到內存中,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();
}
}
}
}之后即可多次傳輸信息不關閉服務端。
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
詳解java如何實現(xiàn)帶RequestBody傳Json參數(shù)的GET請求
在調試Fate平臺時,遇到了一個奇葩的接口類型,該接口為Get方式,入?yún)⑹且粋€json類型在body中傳遞,使用body中傳參的話為什么不用POST請求而使用了GET請求,下面我們就來深入研究一下2024-02-02
Java 中HashCode作用_動力節(jié)點Java學院整理
這篇文章主要介紹了Java 中HashCode作用以及hashcode對于一個對象的重要性,對java中hashcode的作用相關知識感興趣的朋友一起學習吧2017-05-05
Java基于Socket實現(xiàn)簡單的多線程回顯服務器功能示例
這篇文章主要介紹了Java基于Socket實現(xiàn)簡單的多線程回顯服務器功能,結合實例形式分析了java使用socket進行多線程數(shù)據(jù)傳輸?shù)南嚓P操作技巧,需要的朋友可以參考下2017-08-08
Java SpringMVC實現(xiàn)國際化整合案例分析(i18n)
本篇文章主要介紹了Java SpringMVC實現(xiàn)國際化整合案例分析(i18n),具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-05-05
Java8新特性之lambda(動力節(jié)點Java學院整理)
這篇文章主要介紹了Java8新特性之lambda(動力節(jié)點Java學院整理)表達式的相關知識,包括lambda語法方面的知識,非常不錯,具有參考借鑒價值,需要的朋友參考下吧2017-06-06

