JAVA通訊(一)——輸入資料到客戶端

Alexwym發表於2018-07-21

前面我們介紹了通訊技術的基礎知識,今天我們嘗試來用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.同一個埠只能給一個程式通訊用,因此這段程式碼在第二次執行的時候有時會報出埠已被佔用的錯誤,這時只需要更改一下埠號在執行即可。

相關文章