更新時間:2022-04-01 11:05:26 來源:動力節(jié)點 瀏覽5102次
Java 有大量有用的網(wǎng)絡(luò)庫供您使用。在本文中,我將向您展示如何制作一個可以在您的計算機上運行的簡單 Java 服務(wù)器。我們的服務(wù)器會做一些事情。我們連接的那一刻,它會打印字符串“Hello!”,它還應(yīng)該讓我們選擇通過輸入“Peace”來終止連接。本教程的目標是向您展示一些有用的 Java 庫來實現(xiàn)這一點!在創(chuàng)建服務(wù)器時,實際上需要考慮 4 個主要步驟。
在實現(xiàn)服務(wù)器的核心細節(jié)之前,我們需要找到一種方法來確定我們將如何連接到服務(wù)器。這很重要,因為它引入了三個核心網(wǎng)絡(luò)概念;ip-address,端口和套接字。不要害怕這些術(shù)語,我會盡力在下面解釋它們。
IP 地址——在最簡單的形式中,IP 地址只是表示網(wǎng)絡(luò)中特定計算機地址的一種奇特方式。這由一個特定的數(shù)字表示,例如 192.168.11.11。這是一個唯一的 ID,互聯(lián)網(wǎng)上的所有其他機器都可以通過它來識別您的計算機。在我們的例子中,我們將在我們的機器上運行我們的服務(wù)器,這意味著連接不必通過互聯(lián)網(wǎng)再回到我們的機器,相反,操作系統(tǒng)足夠智能,可以在我們的機器內(nèi)路由請求,而無需與網(wǎng)絡(luò)交互。對于這種情況,有一個專門用于此的特殊 IP 地址;127.0.0.1 或有時稱為 localhost。如果您在 Linux 終端中鍵入ip address,您將看到計算機上的網(wǎng)絡(luò)設(shè)備列表。第一個是環(huán)回設(shè)備,此設(shè)備允許您計算機中的任何服務(wù)與您機器中的其他服務(wù)進行通信,您的操作系統(tǒng)將使用環(huán)回地址 127.0.0.1 在您的機器內(nèi)路由它,而不是通過網(wǎng)絡(luò)發(fā)送它。
端口- 一旦我們有了相關(guān)計算機的地址,我們就需要能夠連接到該計算機上我們想要的服務(wù)。這就是端口的用武之地。端口就像在提供某些服務(wù)的計算機上運行的進程,所以一旦您確定了正確的計算機(使用 IP 地址),我們必須選擇端口才能連接到該計算機中的正確服務(wù)。
套接字- 到目前為止,我們可以使用 ip 地址在網(wǎng)絡(luò)/互聯(lián)網(wǎng)中定位計算機。我們可以使用端口識別我們想要連接到的計算機中的哪個服務(wù),但是我們?nèi)匀恍枰谝慌_計算機和我們的目標計算機之間建立連接。這就是套接字的用武之地。套接字可以在網(wǎng)絡(luò)中的兩臺計算機之間實現(xiàn)完全的雙向通信。如您所料,套接字需要目標計算機的地址和端口才能創(chuàng)建連接
現(xiàn)在我們已經(jīng)掌握了網(wǎng)絡(luò)的基礎(chǔ)知識,讓我們來創(chuàng)建服務(wù)器吧!讓我們從創(chuàng)建連接開始。記住連接是使用套接字創(chuàng)建的。
EC-1:創(chuàng)建連接
公共靜態(tài)無效 連接服務(wù)器() {
嘗試(服務(wù)器套接字服務(wù)器套接字= new ServerSocket(9991)) {
套接字連接套接字=服務(wù)器套接字。接受();
在 EC-1 中,我們創(chuàng)建了一個方法connectToServer,在這個方法中,我們有一個不完整的嘗試語句,它執(zhí)行以下操作:
(1)創(chuàng)建一個ServerSocket
(2)指定此服務(wù)將在其上運行的端口 9991
(3)接受 ServerSocket 連接!
和沙贊!我們已經(jīng)建立了我們的聯(lián)系,并且至少建立了聯(lián)系的基礎(chǔ)。我們還沒有連接到任何東西。在 Java 中,aServerSocket只是等待連接,一旦連接,接收一些任意輸入,處理該輸入,然后返回響應(yīng)!在我們的例子中,我們的服務(wù)器只會回顯您選擇輸入的任何內(nèi)容!根據(jù) 的定義ServerSocket,它需要等待連接,在EC-1中,最后一行接受該連接,我們將其保存在一個名為connectionSocketthat 的變量中,該變量的類型為Socket。
太棒了,所以我們已經(jīng)完成了連接框架的鋪設(shè)。讓我們的服務(wù)器交互,允許它在我們連接時進行通信!
為了與我們的服務(wù)器來回交互,我們需要一種方法來使用我們剛剛在 EC-1 中設(shè)置的連接來來回傳輸信息。一種很好的方法是使用IOStreams,在我們的例子中是 JavaInputStream和OutputStream類。這些將允許進出服務(wù)器的雙向通信。讓我們在EC-1中實現(xiàn)它
EC-2:實現(xiàn) IOStream
...
InputStream inputToServer = connectionSocket .getInputStream();
OutputStream outputFromServer = connectionSocket .getOutputStream();
在EC-2中,我們創(chuàng)建了InputStream一個從上面創(chuàng)建的輸入connectionSocket,我們還創(chuàng)建OutputStream一個從connectionSocket. 輸入流代表我們將發(fā)送到服務(wù)器的內(nèi)容,所以它是inputToServer,而輸出代表服務(wù)器的輸出。
EC-3:將 IOStreams 轉(zhuǎn)化為實際可用數(shù)據(jù)
...
Scanner scanner = new Scanner( inputToServer , "UTF-8");
PrintWriter serverPrintOut = new PrintWriter(new OutputStreamWriter( outputFromServer , "UTF-8"), true);
serverPrintOut .println("你好!輸入和平退出。");
在EC-3中,我們采用IOStreams在EC-2中創(chuàng)建的并使用它們。我們首先創(chuàng)建一個Scanner,掃描器將接收服務(wù)器的輸入并將其轉(zhuǎn)換為服務(wù)器可以讀取的形式。然后我們創(chuàng)建一個PrintWriter,PrintWriter它將從服務(wù)器獲取輸出并將其打印在我們的屏幕上。創(chuàng)建Scanner和PrintWriter是必不可少的,因為EC-2IOStreams中的單獨僅表示傳輸中的數(shù)據(jù),它們不會打印或?qū)?shù)據(jù)轉(zhuǎn)換為服務(wù)器和用戶理解的格式。為了讓我們看到我們已經(jīng)連接到服務(wù)器,服務(wù)器應(yīng)該通過打印 Hello! 來通知我們。連接時給我們。
回顧一下,我們現(xiàn)在可以連接到我們的服務(wù)器(EC-1) ,通過IOStreams (EC-2)從服務(wù)器發(fā)送和接收信息,并且可以將流轉(zhuǎn)換為服務(wù)器和用戶的相關(guān)輸出(EC-3)。
服務(wù)器可以做很多事情,但它仍然不能做一些基本的事情,比如向我們實際打印數(shù)據(jù),甚至在客戶端請求時終止連接。我們將在這里實現(xiàn)邏輯。
EC-4: 服務(wù)器邏輯
boolean done = false;
while(! done &&掃描儀.hasNextLine()) {
字符串行=掃描儀.nextLine();
serverPrintOut .println("<您的姓名>服務(wù)器回顯:" + line );
if( line .toLowerCase().trim().equals("peace")) {
done = true;
}
}
在EC-4中,我們需要一種方法來檢查客戶端是否完成了連接。我們首先創(chuàng)建一個boolean名為的標志done并將其設(shè)置為false. 然后我們創(chuàng)建一個 while 循環(huán),它熱切地觀察done值是否變?yōu)?true,它還會檢查EC-3Scanner中創(chuàng)建的是否仍然正常運行并且可以接受輸入。
我們服務(wù)器的作用是打印回我們輸入的任何內(nèi)容,Scanner該類檢查用戶是否發(fā)送了新行,我們使用該輸入作為服務(wù)器的輸出,前綴為“Echo from <Your Name Here> Server: ”.
最后,我們需要找到一種方法來根據(jù)客戶端請求實際終止連接。因此,如果客戶端鍵入單詞“peace”,代碼會將 done 標志更改為 true,while 循環(huán)條件將不再滿足,它將終止循環(huán)和應(yīng)用程序。
所以我們現(xiàn)在已經(jīng)制作了簡單的 Hello 服務(wù)器,這是一個包含所有代碼在一個方法中的要點!
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
/**
* Written by Martin Ombura Jr. <@martinomburajr>
*/
public class MyServer {
public static void main(String[] args) {
connectToServer();
}
public static void connectToServer() {
//Try connect to the server on an unused port eg 9991. A successful connection will return a socket
try(ServerSocket serverSocket = new ServerSocket(9991)) {
Socket connectionSocket = serverSocket.accept();
//Create Input&Outputstreams for the connection
InputStream inputToServer = connectionSocket.getInputStream();
OutputStream outputFromServer = connectionSocket.getOutputStream();
Scanner scanner = new Scanner(inputToServer, "UTF-8");
PrintWriter serverPrintOut = new PrintWriter(new OutputStreamWriter(outputFromServer, "UTF-8"), true);
serverPrintOut.println("Hello World! Enter Peace to exit.");
//Have the server take input from the client and echo it back
//This should be placed in a loop that listens for a terminator text e.g. bye
boolean done = false;
while(!done && scanner.hasNextLine()) {
String line = scanner.nextLine();
serverPrintOut.println("Echo from <Your Name Here> Server: " + line);
if(line.toLowerCase().trim().equals("peace")) {
done = true;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
是時候投入我們所有的工作并運行這段代碼了。
(1)如何連接
1)從您的 Java IDE 或命令行運行此 Java 應(yīng)用程序服務(wù)器代碼。
2)為了讓您連接到服務(wù)器,您需要一個可以讓您執(zhí)行此操作的工具。在 Linux 和 Mac 上,隨意使用netcat或telnet任何其他您想要的連接協(xié)議,如果您沒有它們,請在谷歌搜索如何在您的操作系統(tǒng)版本上安裝它們。對于 Windows,有幾個工具以及winrs. 命令如下
NetCat:這是一種流行的網(wǎng)絡(luò)實用程序,用于連接到網(wǎng)站、服務(wù)器等。
數(shù)控 127.0.0.1 9991
Telnet: Telnet 是一種舊的雙向互聯(lián)網(wǎng)連接協(xié)議。它非常簡單,將通過未加密的連接發(fā)送數(shù)據(jù)。這意味著您在傳遞敏感信息時應(yīng)避免使用它。但是對于這個簡單的例子,它是有效的。
遠程登錄 127.0.0.1 9991
Curl: Curl 與上面的兩個有點不同,因為它將以網(wǎng)頁格式連接到服務(wù)器。這樣做的缺點是,一旦連接,可能不容易將文本直接發(fā)送到 curl,因此您無法通過鍵入“再見”來終止連接。
telnet 127.0.0.1 9991
(2)一旦連接
一旦連接!你應(yīng)該有一些看起來像這樣的東西。
隨意玩耍并輸入內(nèi)容,
輸入“peace”關(guān)閉連接
當你玩它的時候,嘗試重新啟動連接,添加更多連接等。你會注意到這些重要的點:
(1)這個服務(wù)器只能處理一個連接,所以到它的多個連接將被取消。在以后的文章中,我們將讓這個服務(wù)器并發(fā),允許它處理多個連接。
(2)如果客戶端,即你,終止連接,套接字關(guān)閉,連接中斷,程序結(jié)束,這意味著你不能在不重新啟動應(yīng)用程序的情況下再次連接到服務(wù)器。
本文的目的是玩轉(zhuǎn) Java 使用的一些很酷的網(wǎng)絡(luò)特性!如您所見,可能性是無窮無盡的。我們可以以一種可能基于我們提供的輸入數(shù)據(jù)執(zhí)行數(shù)學計算的方式對我們的服務(wù)器進行編碼,或者我們的服務(wù)器可以是數(shù)據(jù)庫之間的中介,它會執(zhí)行諸如檢索、驗證、操作或清理數(shù)據(jù)庫信息之類的操作輸入。機會無窮無盡!
相關(guān)閱讀