java -TCP通信
TCP通信
TCP通信同UDP通信一樣,都能實現兩臺計算機之間的通信,通信的兩端都需要創建socket對象。
區別在于,UDP中只有發送端和接收端,不區分客戶端與服務器端,計算機之間可以任意地發送數據。
而TCP通信是嚴格區分客戶端與服務器端的,在通信時,必須先由客戶端去連接服務器端才能實現通信,服務器端不可以主動連接客戶端,并且服務器端程序需要事先啟動,等待客戶端的連接。
在JDK中提供了兩個類用于實現TCP程序,一個是ServerSocket類,用于表示服務器端,一個是Socket類,用于表示客戶端。
通信時,首先創建代表服務器端的ServerSocket對象,該對象相當于開啟一個服務,并等待客戶端的連接,然后創建代表客戶端的Socket對象向服務器端發出連接請求,服務器端響應請求,兩者建立連接開始通信。
ServerSocket
通過前面的學習知道,在開發TCP程序時,首先需要創建服務器端程序。JDK的java.net包中提供了一個ServerSocket類,該類的實例對象可以實現一個服務器段的程序。通過查閱API文檔可知,ServerSocket類提供了多種構造方法,接下來就對ServerSocket的構造方法進行逐一地講解。
?
?
使用該構造方法在創建ServerSocket對象時,就可以將其綁定到一個指定的端口號上(參數port就是端口號)。
接下來學習一下ServerSocket的常用方法,如表所示。
?
?
ServerSocket對象負責監聽某臺計算機的某個端口號,在創建ServerSocket對象后,需要繼續調用該對象的accept()方法,接收來自客戶端的請求。當執行了accept()方法之后,服務器端程序會發生阻塞,直到客戶端發出連接請求,accept()方法才會返回一個Scoket對象用于和客戶端實現通信,程序才能繼續向下執行。
Socket
講解了ServerSocket對象可以實現服務端程序,但只實現服務器端程序還不能完成通信,此時還需要一個客戶端程序與之交互,為此JDK提供了一個Socket類,用于實現TCP客戶端程序。
通過查閱API文檔可知Socket類同樣提供了多種構造方法,接下來就對Socket的常用構造方法進行詳細講解。
?
?
使用該構造方法在創建Socket對象時,會根據參數去連接在指定地址和端口上運行的服務器程序,其中參數host接收的是一個字符串類型的IP地址。
?
?
該方法在使用上與第二個構造方法類似,參數address用于接收一個InetAddress類型的對象,該對象用于封裝一個IP地址。
在以上Socket的構造方法中,最常用的是第一個構造方法。
接下來學習一下Socket的常用方法,如表所示。
| 方法聲明 | 功能描述 |
| int getPort() | 該方法返回一個int類型對象,該對象是Socket對象與服務器端連接的端口號 |
| InetAddress getLocalAddress() | 該方法用于獲取Socket對象綁定的本地IP地址,并將IP地址封裝成InetAddress類型的對象返回 |
| void close() | 該方法用于關閉Socket連接,結束本次通信。在關閉socket之前,應將與socket相關的所有的輸入/輸出流全部關閉,這是因為一個良好的程序應該在執行完畢時釋放所有的資源 |
| InputStream getInputStream() | 該方法返回一個InputStream類型的輸入流對象,如果該對象是由服務器端的Socket返回,就用于讀取客戶端發送的數據,反之,用于讀取服務器端發送的數據 |
| OutputStream getOutputStream() | 該方法返回一個OutputStream類型的輸出流對象,如果該對象是由服務器端的Socket返回,就用于向客戶端發送數據,反之,用于向服務器端發送數據 |
在Socket類的常用方法中,getInputStream()和getOutStream()方法分別用于獲取輸入流和輸出流。當客戶端和服務端建立連接后,數據是以IO流的形式進行交互的,從而實現通信。
接下來通過一張圖來描述服務器端和客戶端的數據傳輸,如下圖所示。
?多線程循環上傳文件實例(自動獲取文件后綴)
package com.oracle.TCPTest;import java.io.BufferedInputStream; 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 TCPClient {public static void main(String[] args) throws IOException {File file = new File("D:\\temp\\1.jpg");//獲取文件的后綴String suffix = file.toString().substring(file.toString().lastIndexOf("."));Socket socket = new Socket("127.0.0.1",8088);BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));OutputStream os = socket.getOutputStream();byte[] bytes = new byte[1024];int len = 0;int i = 0;while((len = bis.read(bytes))!=-1) {if(i==0) {//將文件后綴寫入IO流os.write((suffix+"@").getBytes());}os.write(bytes,0,len);i++;}//結束輸出 socket.shutdownOutput();InputStream is = socket.getInputStream();//從服務端獲取回復len = is.read(bytes);System.out.println(new String(bytes,0,len));bis.close();socket.close();} } package com.oracle.TCPTest;import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.Random;public class TCPTest {public static void main(String[] args) throws IOException {ServerSocket serversocket = new ServerSocket(8088);int i = 0;//循環多線程上傳文件while(true) {System.out.println("等待上傳!<已上傳"+i+++">");//如果客戶端沒有發送請求,一直處于阻塞狀態Socket socket = serversocket.accept();new Thread(new Server(socket)).start();}} }class Server implements Runnable{private Socket socket;//定義有參構造public Server(Socket socket) {super();this.socket = socket;}public void run() {//創建上傳目錄的File對象File file = new File("D:\\temp\\upload");//判斷是否存在if(!file.exists()) {file.mkdirs();}try {InputStream ins = socket.getInputStream();byte[] bytes = new byte[1024];int len =0;// BufferedOutputStream bos =null;//時間戳long time = System.currentTimeMillis();int i = 0;while((len = ins.read(bytes))!=-1) {//定義6位隨機數String random = (new Random().nextDouble()+"").substring(2, 8);if(i==0) {//獲取文件后綴String str = new String(bytes);int index = str.indexOf("@");String suffix = str.substring(0, index);bos = new BufferedOutputStream(new FileOutputStream(file+File.separator+"oracle"+time+random+suffix));bos.write(bytes, index+1, len-index-1);}else {bos.write(bytes,0,len);} i++;} //上傳完畢后給服務端回復OutputStream out = socket.getOutputStream();out.write("上傳成功!".getBytes());bos.close();} catch (IOException e) {// TODO Auto-generated catch block e.printStackTrace();}} }
?
轉載于:https://www.cnblogs.com/miaoxingren/p/9558917.html
總結
以上是生活随笔為你收集整理的java -TCP通信的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 游戏编程入门之绘制动画的精灵(爆炸特效)
- 下一篇: 【UVA1638】杆子的排列