Java中TCP傳輸、上傳文件、上傳圖片、多并發(fā)上傳

TCP傳輸

TCP傳輸是怎樣建立的呢?

  • Socket和ServerSocket
  • 建立客戶端和服務(wù)器端
  • 建立連接后,通過Socket中的IO流進(jìn)行數(shù)據(jù)的傳輸
  • 關(guān)閉socket

TCP傳輸客戶端與服務(wù)器端同樣是兩個獨(dú)立的應(yīng)用程序。
我們就來寫一個TCP輸出數(shù)據(jù)的程序。

TCP傳輸-客戶端

/* 
* TCP協(xié)議發(fā)送數(shù)據(jù): 
* A:創(chuàng)建發(fā)送端的Socket對象 
* 這一步如果成功,就說明連接已經(jīng)建立成功了。
* B:獲取輸出流,寫數(shù)據(jù) 
* C:釋放資源 
*/
public class ClientDemo { 
public static void main(String[] args) throws IOException {
 // 創(chuàng)建發(fā)送端的Socket對象 
Socket s = new Socket("192.168.2.102", 8888); 
// 獲取輸出流,寫數(shù)據(jù) 
OutputStream os = s.getOutputStream(); 
os.write("TCP來了".getBytes()); 
// 釋放資源
 s.close(); 
}
}

TCP傳輸-服務(wù)器

/* 
* TCP協(xié)議接收數(shù)據(jù):
* A:創(chuàng)建接收端的Socket對象 
* B:監(jiān)聽客戶端連接。返回一個對應(yīng)的Socket對象 
* C:獲取輸入流,讀取數(shù)據(jù)顯示在控制臺 
* D:釋放資源 */
public class ServerDemo { 
public static void main(String[] args) throws IOException { 
// 創(chuàng)建接收端的Socket對象 
ServerSocket ss = new ServerSocket(8888); 
// 監(jiān)聽客戶端連接。返回一個對應(yīng)的Socket對象 
Socket s = ss.accept(); // 偵聽并接受到此套接字的連接。此方法在連接傳入之前一直阻塞。 
// 獲取輸入流,讀取數(shù)據(jù)顯示在控制臺 
InputStream is = s.getInputStream();
 byte[] bys = new byte[1024]; 
int len = is.read(bys); 
// 阻塞式方法 
String str = new String(bys, 0, len); 
String ip = s.getInetAddress().getHostAddress(); 
System.out.println(ip + "---" + str);
 // 釋放資源
 s.close(); 
// ss.close();  //服務(wù)器一般不應(yīng)該關(guān)閉 
}
}

這樣我們九建立了TCP協(xié)議傳輸數(shù)據(jù)的客戶端和服務(wù)器,運(yùn)行程序,服務(wù)器會收到客戶端發(fā)來的數(shù)據(jù),但是這樣的代碼,當(dāng)服務(wù)器端收到客戶端的數(shù)據(jù)時,客戶端并不知道,所以,我們就要給客戶端一個反饋了。

/* * 服務(wù)器端 */
public class ServerDemo { 
public static void main(String[] args) throws IOException {
 // 創(chuàng)建服務(wù)器Socket對象 
ServerSocket ss = new ServerSocket(11111); 
// 監(jiān)聽客戶端的連接 
Socket s = ss.accept(); // 阻塞 
// 獲取輸入流
 InputStream is = s.getInputStream(); 
byte[] bys = new byte[1024]; 
int len = is.read(bys); // 阻塞 
String server = new String(bys, 0, len); 
System.out.println("server:" + server); 
// 獲取輸出流
 OutputStream os = s.getOutputStream(); o
s.write("數(shù)據(jù)已經(jīng)收到".getBytes()); 
// 釋放資源 
s.close(); 
// ss.close(); 
}
}
/* * 客戶端 */
public class ClientDemo { 
public static void main(String[] args) throws IOException { 
// 創(chuàng)建客戶端Socket對象 
Socket s = new Socket("192.168.2.102",11111); 
// 獲取輸出流 
OutputStream os = s.getOutputStream(); 
os.write("雙十一快樂!".getBytes());
 // 獲取輸入流
 InputStream is = s.getInputStream();
 byte[] bys = new byte[1024]; 
int len = is.read(bys);// 阻塞 
String client = new String(bys, 0, len); 
System.out.println("client:" + client); 
// 釋放資源 
s.close(); 
}
}

上傳文件

我們來完成通過TCP協(xié)議從客戶端上傳一個文件到服務(wù)器,并給出客戶端反饋文件上傳成功

/* * 上傳文件客戶端 */
public class UploadClient { 
public static void main(String[] args) throws IOException { 
// 創(chuàng)建客戶端Socket對象 
Socket s = new Socket("192.168.2.102", 12345); 
// 封裝文本文件 
BufferedReader br = new BufferedReader(new FileReader("a.txt")); 
// 封裝通道內(nèi)流 
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter( s.getOutputStream())); 
String line = null; 
while ((line = br.readLine()) != null) { 
// 阻塞 
bw.write(line);
 bw.newLine();
 bw.flush(); 
} 
//Socket提供了一個終止,它會通知服務(wù)器你別等了,我沒有數(shù)據(jù)過來了
 s.shutdownOutput(); 
// 接收反饋 
BufferedReader brClient = new BufferedReader(new InputStreamReader( s.getInputStream())); 
String client = brClient.readLine(); // 阻塞 
System.out.println(client); 
// 釋放資源 
br.close();
 s.close();
 }
}
/* * 上傳文件接收端(服務(wù)器) */
public class UploadServer { 
public static void main(String[] args) throws IOException { 
// 創(chuàng)建服務(wù)器端的Socket對象 
ServerSocket ss = new ServerSocket(12345);
 // 監(jiān)聽客戶端連接 
Socket s = ss.accept();// 阻塞 
// 封裝通道內(nèi)的流 
BufferedReader br = new BufferedReader(new InputStreamReader( s.getInputStream())); 
// 封裝文本文件 
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt")); String line = null;
 while ((line = br.readLine()) != null) {
 // 阻塞 
bw.write(line); 
bw.newLine();
 bw.flush(); 
} 
// 給出反饋 
BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter( s.getOutputStream())); 
bwServer.write("文件上傳成功"); 
bwServer.newLine();
 bwServer.flush(); 
// 釋放資源
 bw.close();
 s.close(); 
}
}

這是上傳文件并給出反饋的例子,我們再來看上傳圖片并給出反饋的例子怎么寫

上傳圖片

上傳圖片我們就要考慮不能用字符流了,要用字節(jié)流。

/* * 上傳圖片客戶端 */
public class UploadClient { 
public static void main(String[] args) throws IOException { 
// 創(chuàng)建客戶端Socket對象 
Socket s = new Socket("192.168.2.102", 96320); 
// 封裝圖片文件 
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.jpg")); 
// 封裝通道內(nèi)的流
 BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
 byte[] bys = new byte[1024]; 
int len = 0;
 while ((len = bis.read(bys)) != -1) { 
bos.write(bys, 0, len); 
bos.flush(); 
} 
s.shutdownOutput(); // 讀取反饋
 InputStream is = s.getInputStream(); 
byte[] bys2 = new byte[1024]; 
int len2 = is.read(bys2); 
String client = new String(bys2, 0, len2); 
System.out.println(client); 
// 釋放資源 
bis.close(); s.close(); 
}
}
/* * 上傳圖片接收端-服務(wù)器 */
public class UploadServer { 
public static void main(String[] args) throws IOException { 
// 創(chuàng)建服務(wù)器Socket對象 
ServerSocket ss = new ServerSocket(96320); 
// 監(jiān)聽客戶端連接 
Socket s = ss.accept(); 
// 封裝通道內(nèi)流 
BufferedInputStream bis = new BufferedInputStream(s.getInputStream());
 // 封裝圖片文件 
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("b.jpg")); 
byte[] bys = new byte[1024];
 int len = 0; 
while ((len = bis.read(bys)) != -1) {
 bos.write(bys, 0, len); 
bos.flush(); 
} 
// 給一個反饋 
OutputStream os = s.getOutputStream(); 
os.write("圖片上傳成功".getBytes());
 bos.close();
 s.close(); 
}
}

運(yùn)行程序,我們將客戶端a.jpg的圖片上傳到服務(wù)器后,服務(wù)器收到后會給我們返回圖片上傳成功

多并發(fā)上傳

在我們平時遇到的情況肯定不是一個客戶端對應(yīng)一個服務(wù)器,肯定是多個客戶端對應(yīng)一個服務(wù)器,那么就存在了多并發(fā)上傳,再大型項目中也要考慮服務(wù)器的負(fù)荷問題,那么我們就來用代碼實(shí)現(xiàn)一下當(dāng)多個用戶上傳文件到服務(wù)器時,我們應(yīng)該怎樣做?

如果我們還按照上面上傳文件的思路,去進(jìn)行多并發(fā)上傳,當(dāng)一個客戶端A建立連接之后,被服務(wù)端獲取到,服務(wù)端就在執(zhí)行代碼了,這個時候如果客戶端B建立連接只有等待客戶端A操作完成后它才能開始執(zhí)行,所以為了讓多個客戶端同時連接到服務(wù)器上傳代碼,我們就要運(yùn)用多線程技術(shù),把每個客戶端和服務(wù)器之間的連接封裝到一個線程中去,這樣就可以同時處理多個客戶端請求

/* * 服務(wù)器端 */
public class UploadServer { 
public static void main(String[] args) throws IOException { 
// 創(chuàng)建服務(wù)器Socket對象 
ServerSocket ss = new ServerSocket(11111);
 while (true) {
 Socket s = ss.accept(); 
new Thread(new UserThread(s)).start(); 
} 
}
}

/* * 并發(fā)的線程 */
public class UserThread implements Runnable { 
private Socket s; 
public UserThread(Socket s) { 
this.s = s;
 } 
@Override 
public void run() { 
try { 
// 封裝通道內(nèi)的流 
BufferedReader br = new BufferedReader(new InputStreamReader( s.getInputStream())); 
// 為了防止名稱沖突,每次命名為隨機(jī)的 
String newName = System.currentTimeMillis() + ".java"; BufferedWriter bw = new BufferedWriter(new FileWriter(newName)); String line = null; 
while ((line = br.readLine()) != null) { 
// 阻塞 
bw.write(line); 
bw.newLine();
 bw.flush(); 
} 
// 給出反饋 
BufferedWriter bwServer = new BufferedWriter( new OutputStreamWriter(s.getOutputStream())); 
bwServer.write("文件上傳成功"); 
bwServer.newLine(); 
bwServer.flush(); 
// 釋放資源 
bw.close();
 s.close(); 
} catch (IOException e) { 
e.printStackTrace();
 } 
}
}

這樣就完成了多用戶上傳文件到客戶端了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評論 19 139
  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 12,302評論 6 13
  • 18.1 引言 TCP是一個面向連接的協(xié)議。無論哪一方向另一方發(fā)送數(shù)據(jù)之前,都必須先在雙方之間建立一條連接。本章將...
    張芳濤閱讀 3,520評論 0 13
  • 個人認(rèn)為,Goodboy1881先生的TCP /IP 協(xié)議詳解學(xué)習(xí)博客系列博客是一部非常精彩的學(xué)習(xí)筆記,這雖然只是...
    貳零壹柒_fc10閱讀 5,180評論 0 8
  • 站在三十歲的門檻上,回顧從前,暢想未來。 時間這廝說快很快,說慢很慢。 轉(zhuǎn)眼間,我們都要三十歲了,昨天我們還是惹是...
    146195562bba閱讀 494評論 0 1

友情鏈接更多精彩內(nèi)容