JAVA通訊(二)——實現客戶機和伺服器通訊
前面一篇部落格我們簡單地理清了JAVA建立伺服器,以及客戶機連線伺服器的流程,今天我們繼續往下學習,實現客戶機和伺服器的通訊。由於基本概念我們已經在前一篇部落格說清楚了,這裡我們就不再進行贅述。(不清楚的可以先閱讀下我的前一篇部落格JAVA通訊(一)——輸入資料到客戶端)
具體程式碼
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(9005);
//輸出伺服器的埠資訊
System.out.println("伺服器建立成功,埠號為:"+server.getLocalPort());
while(true) {
//建立一個Socket物件來連線,這裡不需要新建一個物件,它只要直接引用server即可
Socket socket=server.accept();
//利用socket來接收輸出輸入流的資料
//這裡有一點需要注意,OutputStream是向客戶機輸出資訊,而InputStream是讀取客戶機傳送過來的資訊
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();
//接收每一個來自客戶機的字元
int ascii=input.read();
//如果接收到回車字元就結束迴圈
while(ascii!=13) {
char accept=(char) ascii;
//輸出客戶機發出的,伺服器收到的每一個字元
System.out.print(accept);
ascii=input.read();
}
//關閉連線
socket.close();
}
}
}
我們在前一篇部落格程式碼的基礎上再加上一段程式碼。利用InputStream的read()方法來實現把資訊傳送到伺服器。需要注意的是read()方法得到的是字元的ascii碼,因此我們要用int的變數接收,再把它轉化為char型字元。
二、執行命令列如下
輸入telnet localhost 9006 後,連線如下
我們嘗試輸入一些字元,會看到如下介面
每次在命令列中輸入一個字元,伺服器就會接收到一個字元。而不是我們想象中的寫完一句話,按回車後才會傳送給伺服器。但是這種傳送形式不是很適用於我們的日常生活。而且它是不能進行刪除的。因為我們每寫完一個字元,它就馬上被髮送到伺服器了。當你按下刪除鍵時,它會被識別成一個字元傳送給伺服器。
三、設定讀取傳送規則
如果要實現客戶機和伺服器的正常通訊我們就必須為它們設定一定的讀取規則,而不能一個個字元地讀取。比如我們可以規定Enter鍵為一條完整訊息的結束。每次讀取到Enter鍵時伺服器再一次性地接收訊息。當功能逐漸增多時,我們最好把它封裝成一個類,而不要總是在主函式裡面測試。程式碼修改如下:
package communicatetest2;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
//定義一個通訊類
public class ServerChat {
OutputStream output;//輸出流
InputStream input;//輸入流
ServerSocket server;//設定一個伺服器物件屬性
//定義一個建立伺服器的方法
private void setUpServer(int port) throws IOException {
//將輸入的埠設定為伺服器
server=new ServerSocket(port);
//輸出當前伺服器的埠號
System.out.println("伺服器建立成功,埠號:"+server.getLocalPort());
//定義一個作為中介的接收物件Socket
Socket socket=server.accept();
//為輸入輸出流賦值
output=socket.getOutputStream();
input=socket.getInputStream();
//開始通訊
//傳送資訊給客戶機
String outS="Hello,welcome to my ServerSocket!\r\n";
out(outS);
//傳送資訊給伺服器
ReadString();
}
//定義一個輸出資訊到客戶機的方法
private void out(String outS) throws IOException {
//將字串轉化為byte陣列
byte[] dataout=outS.getBytes();
//呼叫write()將資訊傳送客戶機
output.write(dataout);
//強制輸出到命令列的介面中
output.flush();
}
//定義一個傳送字串給伺服器的方法
public void ReadString() throws IOException {
String inputS="";
//讀取第一個字元
int AsciiNumber=input.read();
while(AsciiNumber!=13) {
//將ascii碼轉化為相應的char型字元
inputS+=(char)AsciiNumber;
//接收下一個字元
AsciiNumber=input.read();
}
System.out.println(inputS);
output.close();
}
//主函式入口
public static void main(String[] args) throws IOException {
//建立一個通訊類的物件
ServerChat server=new ServerChat();
server.setUpServer(9009);
}
}
命令列執行結果如下
如此一下我們就可以實現回車後再進行顯示了。但是實質上他還是一個一個字元地傳輸,只不過當伺服器接收到字元時,我們不立即將其顯示出來,而是等接受完整句話,我們才把它顯示出來。但是它現在還有一個問題,那就是隻能傳送一句話,這就很難受了。誰說話只說一句呀,因此我們還要對它進行改進。當我們接收完一句話時不要立即關閉客戶端和伺服器的連線,而是等到使用者輸入“bye”的時候再斷開連線。相關部分的程式碼更改如下:
public void ReadString() throws IOException {
String inputS="";
while(!inputS.equals("bye")) {
//讀取第一個字元
int AsciiNumber=input.read();
while(AsciiNumber!=13) {
//將ascii碼轉化為相應的char型字元
inputS+=(char)AsciiNumber;
//接收下一個字元
AsciiNumber=input.read();
}
System.out.println(inputS);
}
//關閉連線
output.close();
}
執行命令列結果如下
現在我們就可以進行多條資訊的交流啦~
當然現在我們只允許伺服器和一個客戶機進行交流,當有一個客戶機在和伺服器在一起交流時,如果第二個客戶機嘗試和伺服器進行連線,就會出現如下報錯。
原因很簡單,當前我們的只是一個單執行緒的程式,當有一個客戶機在和伺服器進行通訊時,這個執行緒就已經被佔用了。後期我會繼續推出一篇部落格來講解JAVA多執行緒通訊的實現,支援多人聊天。
相關文章
- C++實現客戶端與伺服器的通訊(二):Base64編解碼C++客戶端伺服器
- java實現UDP通訊JavaUDP
- 基於WebSocket的modbus通訊(二)- 客戶端Web客戶端
- 實現客戶端與服務端的HTTP通訊客戶端服務端HTTP
- JAVA通訊(一)——輸入資料到客戶端Java客戶端
- Golang 實現客戶端與伺服器端UDP協議連線通訊Golang客戶端伺服器UDP協議
- 使用Java實現WebSocket通訊JavaWeb
- Java實現TCP通訊程式JavaTCP
- java netty 實現 websocket 服務端和客戶端雙向通訊 實現心跳和斷線重連 完整示例JavaNettyWeb服務端客戶端
- TCP通訊客戶端和服務端簡單程式碼實現TCP客戶端服務端
- JAVA通訊(三)——實現多人聊天Java
- 網路通訊2:TCP通訊實現TCP
- C/S(socket、執行緒 實現多個客戶端、伺服器端簡易通訊)執行緒客戶端伺服器
- Java的通過管道來實現執行緒通訊Java執行緒
- python實現兩臺不同主機之間進行通訊(客戶端和服務端)——SocketPython客戶端服務端
- Socket最簡單的客戶端與服務端通訊-Java客戶端服務端Java
- 匿名管道通訊實現
- iOS實現XMPP通訊(二)XMPP程式設計iOS程式設計
- 通過 App Groups 實現程式間通訊APP
- C# 實現socket通訊程式(伺服器端)C#伺服器
- 簡單的Java實現Netty進行通訊JavaNetty
- 匯川AM401的TCP客戶端通訊TCP客戶端
- 從PHP客戶端看MongoDB通訊協議TDPHP客戶端MongoDB協議
- Binder通訊機制與IPC通訊.md
- angular + express 實現websocket通訊AngularExpressWeb
- golang實現子程式通訊Golang
- TCP協議服務端和客戶端的連線與通訊TCP協議服務端客戶端
- Java基礎(Socket通訊和NIO)Java
- RocketMQ(二):RPC通訊MQRPC
- 如何優雅的實現訊息通訊?
- 052、overlay如何實現跨主機通訊?(2019-03-19 週二)
- Kubernetes 實戰 —— 05. 服務:讓客戶端發現 pod 並與之通訊(下)客戶端
- CentOS 7安裝etcd和flannel實現docker跨物理機通訊CentOSDocker
- Java Websocket實現即時通訊功能入門教程JavaWeb
- Thinking in Java--使用NIO實現非阻塞Socket通訊ThinkingJava
- Java實現RS485串列埠通訊Java串列埠
- Redis:我是如何與客戶端進行通訊的Redis客戶端
- 簡單區分WiFi通訊和WLAN通訊WiFi