JAVA通訊(一)——輸入資料到客戶端
前面我們介紹了通訊技術的基礎知識,今天我們嘗試來用JAVA來建立一個簡單的伺服器,這個伺服器將實現接收客戶機傳送過來的資訊,並把資訊再傳回給客戶機。伺服器指的是等待別人來連線的機器。客戶機,指的是主動連結別人的機器。
一、JAVA中伺服器和客戶機的資訊傳輸過程
建議大家在學習JAVA的通訊之前先把JAVA中的檔案的讀取和輸出先搞懂。(可以參考我的另一篇部落格《JAVA檔案讀取和寫入(內附簡單的程式碼實現)》)。因為伺服器和客戶機的通訊其實就是檔案的獲取和傳送的一種特殊形式。我們以前所瞭解的檔案操作,大多數都是自取自用。就是從自己那裡取出要用的檔案,處理完成後生成一個新檔案件再存到自己那裡。InputStream就是讀取操作,從自己那裡取出要操作的檔案。而OutputStream就是寫出操作,把處理好的資訊寫出給自己。而伺服器和客戶機的通訊,從客戶機來看,就是客戶機傳送檔案給伺服器或者從伺服器那裡獲取檔案,從伺服器來看,就是伺服器傳送檔案給客戶機或者從客戶機那裡獲取檔案。
以往所理解的檔案操作如下——自娛自樂型
伺服器和客戶機所進行的通訊操作如下——實時互動型
二、涉及到的API類
1.ServerSocket 用來建立一個伺服器。操作物件是某一臺主機的某個埠埠
2.Socket 建立一個接受伺服器資訊的中間物件,這個物件就是客戶機和伺服器進行互動的中介。
它有兩個重要的方法,一個是getInputStream()——獲取客戶機傳送過來的資訊,一個是GetOutputStream()——傳送給客戶機的資訊。也就是說,我們向輸入流InputStream寫入的資料會被髮送到客戶端,而我們從輸出流OutputStream讀取的是客戶端傳送過來的資料。
三、原始碼
package communicatetest1;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
//建立一個測試類
public class communicateTest {
public static void main(String[] args) throws IOException {
//建立一個伺服器物件
ServerSocket server=new ServerSocket(9000);
//輸出伺服器的埠資訊
System.out.println("伺服器建立成功,埠號為:"+server.getLocalPort());
//建立一個Socket物件來連線,這裡不需要新建一個物件,它只要直接引用server即可
Socket socket=server.accept();
//利用socket來接收輸出輸入流的資料
//這裡有一點需要注意,我們向輸入流InputStream寫入的資料會被髮送到客戶端,
//而我們從輸出流OutputStream讀取的是客戶端傳送過來的資料
OutputStream output=socket.getOutputStream();
InputStream input=socket.getInputStream();
//接著開始進行通訊測試
String s="Hello,Welcome to My ServerSocket!";
//這條訊息是當客戶機連線上我們建立的伺服器時,伺服器傳送給客戶機的一條資訊
//也就是我們要向客戶機傳送訊息,那麼我們應該用的是OutputStream
//首先我們要先將傳送資訊轉化為byte型別,因為輸出流的寫入方法write()中的引數是byte型別
byte[] dataout=s.getBytes();
//接著呼叫輸出流的寫入方法,把資訊傳送給客戶機
output.write(dataout);
//然後讓這條資訊在命令列中顯示出來,以便我們檢測資訊是否真的已經被髮送出去
output.flush();
//關閉連線
socket.close();
}
}
四、執行命令列連線伺服器
通過前面的程式碼我們已經成功地把埠9000設定為開放的伺服器,接下來我們就用本地的其他埠作為客戶端去連線它,實現把訊息傳送給客戶機。
開啟命令列,輸入telnet localhost 9000
回車後,出現如下介面,說明連線成功。並且客戶機
這時如果我們繼續嘗試在命令列中連線9000埠,會出現如下報錯資訊:
這是因為我們程式碼最後的那條close()指令。在我們成功連線伺服器並給客戶機傳送完訊息後,這個埠伺服器就被重新關閉了。因此我們連線不上。如果想要重新連線,則需要重新執行一下JAVA程式碼。
如果我們想讓這個伺服器每次在關閉後又能重新開啟,只需要加上一個while迴圈。程式碼如下:
while(true) {
ServerSocket server=new ServerSocket(9000);
System.out.println("伺服器建立成功,埠號為:"+server.getLocalPort());
Socket socket=server.accept();
OutputStream output=socket.getOutputStream();
InputStream input=socket.getInputStream();
String s="Hello,Welcome to My ServerSocket!";
byte[] dataout=s.getBytes();
//接著呼叫輸出流的寫入方法,把資訊傳送給客戶機
output.write(dataout);
output.flush();
socket.close();
}
這個程式碼會報錯,第二次進入迴圈時會說這個埠已經被佔用了。原因是.close()方法它只是關閉了埠的開放狀態,但是這個埠還是會作為一個伺服器存在,因為我們的程式還沒有結束。只有當我們的程式終止了,這個埠才會重新被初始化。因此當我們第二次又要重新把這個埠設定為伺服器時它就會報錯。(伺服器的生命週期和程式一致,程式結束伺服器才會被關閉)解決方案:移動一下while的位置。改動後如下:
ServerSocket server=new ServerSocket(9000);
System.out.println("伺服器建立成功,埠號為:"+server.getLocalPort());
while(true) {
Socket socket=server.accept();
OutputStream output=socket.getOutputStream();
InputStream input=socket.getInputStream();
String s="Hello,Welcome to My ServerSocket!";
byte[] dataout=s.getBytes();
//接著呼叫輸出流的寫入方法,把資訊傳送給客戶機
output.write(dataout);
output.flush();
socket.close();
}
這時再去執行就不會有錯了。命令執行如下。再次輸入連線指令,命令列同樣會跳轉到這個介面:
五、注意點
1.同一臺主機上即可完成通訊的操作,因為通訊的物件是兩個埠,我們可以把同一臺主機的某一個埠建立為伺服器,然後再用一個埠作為客戶機去連線它。
2.同一個埠只能給一個程式通訊用,因此這段程式碼在第二次執行的時候有時會報出埠已被佔用的錯誤,這時只需要更改一下埠號在執行即可。
相關文章
- Socket最簡單的客戶端與服務端通訊-Java客戶端服務端Java
- 實現客戶端與服務端的HTTP通訊客戶端服務端HTTP
- java web 通過request獲取客戶端IPJavaWeb客戶端
- 基於WebSocket的modbus通訊(二)- 客戶端Web客戶端
- java websocket 客戶端JavaWeb客戶端
- JAVA通訊(二)——實現客戶機和伺服器通訊Java伺服器
- 關於客戶端資訊流思考客戶端
- 匯川AM401的TCP客戶端通訊TCP客戶端
- 從PHP客戶端看MongoDB通訊協議TDPHP客戶端MongoDB協議
- Zookeeper Java 客戶端搭建Java客戶端
- [Redis 客戶端整合] Java 中常用Redis客戶端比較Redis客戶端Java
- TCP通訊客戶端和服務端簡單程式碼實現TCP客戶端服務端
- 如何建立一個Java遊戲客戶端Java遊戲客戶端
- Kubernetes官方java客戶端之一:準備Java客戶端
- spring boot 獲取客戶端ip資訊Spring Boot客戶端
- Redis:我是如何與客戶端進行通訊的Redis客戶端
- TCP協議服務端和客戶端的連線與通訊TCP協議服務端客戶端
- 基於node的tcp客戶端和服務端的簡單通訊TCP客戶端服務端
- socket實現服務端多執行緒,客戶端重複輸入服務端執行緒客戶端
- zookeeper的Java客戶端APIJava客戶端API
- 使用Java客戶端將資料載入到Grakn知識圖中Java客戶端
- Qt TCP通訊客戶端斷開連線有哪些方法QTTCP客戶端
- php原生socket實現客戶端與服務端資料傳輸PHP客戶端服務端
- HarmonyOS IPC Kit進階:客戶端與服務端的基礎通訊客戶端服務端
- [jaeger] 二、客戶端使用 (Java版本)客戶端Java
- 騰訊 客戶端開發 QT客戶端QT
- Nebula Graph 原始碼解讀系列|客戶端的通訊秘密——fbthrift原始碼客戶端
- Golang 實現客戶端與伺服器端UDP協議連線通訊Golang客戶端伺服器UDP協議
- Java與WCF互動(一):Java客戶端呼叫WCF服務 (轉)Java客戶端
- Nebula Graph 原始碼解讀系列|客戶端的通訊祕密——fbthrift原始碼客戶端
- 技術分享 | MySQL Binlog 通過 MySQL 客戶端匯入資料庫效率低的原因MySql客戶端資料庫
- Java HTTP 客戶端的比較 - reflectoringJavaHTTP客戶端
- Tars-Java客戶端原始碼分析Java客戶端原始碼
- 看視訊必備:YouTube客戶端客戶端
- 使用Java客戶端傳送訊息和消費的應用Java客戶端
- java netty 實現 websocket 服務端和客戶端雙向通訊 實現心跳和斷線重連 完整示例JavaNettyWeb服務端客戶端
- SecureFX for Mac(跨平臺檔案傳輸客戶端)Mac客戶端
- RMAN之客戶端互動(一)客戶端