Java Socket程式設計系列(四)開發支援多客戶端訪問的Server
例子來自Java官方教程,稍作調整。
上一篇介紹了單客戶端訪問的Server實現,這一篇實現的是多個客戶端請求服務端,根據服務端提示進行一系列操作。
協議類(和系列三一樣沒變):
package com.dylan.socket;
/**
* @author xusucheng
* @create 2017-12-24
**/
public class KnockKnockProtocol {
private static final int WAITING = 0;
private static final int SENTKNOCKKNOCK = 1;
private static final int SENTCLUE = 2;
private static final int ANOTHER = 3;
private static final int NUMJOKES = 5;
private int state = WAITING;
private int currentJoke = 0;
private String[] clues = { "Turnip", "Little Old Lady", "Atch", "Who", "Who" };
private String[] answers = { "Turnip the heat, it's cold in here!",
"I didn't know you could yodel!",
"Bless you!",
"Is there an owl in here?",
"Is there an echo in here?" };
public String processInput(String theInput) {
String theOutput = null;
if (state == WAITING) {
theOutput = "Knock! Knock!";
state = SENTKNOCKKNOCK;
} else if (state == SENTKNOCKKNOCK) {
if (theInput.equalsIgnoreCase("Who's there?")) {
theOutput = clues[currentJoke];
state = SENTCLUE;
} else {
theOutput = "You're supposed to say \"Who's there?\"! " +
"Try again. Knock! Knock!";
}
} else if (state == SENTCLUE) {
if (theInput.equalsIgnoreCase(clues[currentJoke] + " who?")) {
theOutput = answers[currentJoke] + " Want another? (y/n)";
state = ANOTHER;
} else {
theOutput = "You're supposed to say \"" +
clues[currentJoke] +
" who?\"" +
"! Try again. Knock! Knock!";
state = SENTKNOCKKNOCK;
}
} else if (state == ANOTHER) {
if (theInput.equalsIgnoreCase("y")) {
theOutput = "Knock! Knock!";
if (currentJoke == (NUMJOKES - 1))
currentJoke = 0;
else
currentJoke++;
state = SENTKNOCKKNOCK;
} else {
theOutput = "Bye.";
state = WAITING;
}
}
return theOutput;
}
}
伺服器端:
package com.dylan.socket;
import java.io.IOException;
import java.net.ServerSocket;
/**
* @author xusucheng
* @create 2017-12-24
**/
public class KKMultiServer {
private static final int PORT = 8858;
public static void main(String[] args) {
boolean listening = true;
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
while (listening) {
new KKMultiServerThread(serverSocket.accept()).start();
}
} catch (IOException e) {
System.err.println("Could not listen on port " + PORT);
System.exit(-1);
}
}
}
伺服器多執行緒類(核心):
package com.dylan.socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
/**
* @author xusucheng
* @create 2017-12-24
**/
public class KKMultiServerThread extends Thread{
private Socket socket = null;
public KKMultiServerThread(Socket socket) {
super("KKMultiServerThread");
this.socket = socket;
}
public void run() {
try (
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
) {
String inputLine, outputLine;
KnockKnockProtocol kkp = new KnockKnockProtocol();
outputLine = kkp.processInput(null);
out.println(outputLine);
while ((inputLine = in.readLine()) != null) {
outputLine = kkp.processInput(inputLine);
out.println(outputLine);
if (outputLine.equals("Bye."))
break;
}
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
客戶端:
package com.dylan.socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* @author xusucheng
* @create 2017-12-24
**/
public class KnockKnockClient {
private static final String HOST="127.0.0.1";
private static final int PORT=8858;
public static void main(String[] args) throws IOException {
/*if (args.length != 2) {
System.err.println(
"Usage: java EchoClient <host name> <port number>");
System.exit(1);
}
String hostName = args[0];
int portNumber = Integer.parseInt(args[1]);*/
try (
Socket kkSocket = new Socket(HOST, PORT);
PrintWriter out = new PrintWriter(kkSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(kkSocket.getInputStream()));
) {
BufferedReader stdIn =
new BufferedReader(new InputStreamReader(System.in));
String fromServer;
String fromUser;
while ((fromServer = in.readLine()) != null) {
System.out.println("Server: " + fromServer);
if (fromServer.equals("Bye."))
break;
fromUser = stdIn.readLine();
if (fromUser != null) {
System.out.println("Client: " + fromUser);
out.println(fromUser);
}
}
} catch (UnknownHostException e) {
System.err.println("Don't know about host " + HOST);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to " +
HOST);
System.exit(1);
}
}
}
相關文章
- Java Socket程式設計系列(三)開發支援單客戶端訪問的ServerJava程式設計客戶端Server
- Java Socket程式設計系列(二)開發帶回聲功能的Server和ClientJava程式設計Serverclient
- Hexo多客戶端同步問題Hexo客戶端
- Java Socket程式設計系列(一)開發一次性會話的Server和ClientJava程式設計會話Serverclient
- Python簡單的多客戶端聊天室程式Python客戶端
- 基於CMPP2.0的Socket客戶端(Java) - JAVA程式語言客戶端Java
- C++客戶端程式(socket)C++客戶端
- C#Socket伺服器與客戶端的開發(3)C#伺服器客戶端
- 「完整案例」基於Socket開發TCP傳輸客戶端TCP客戶端
- Python socket的客戶端Python客戶端
- IE客戶客戶端程式開發的利器Bindows客戶端
- Socket最簡單的客戶端與服務端通訊-Java客戶端服務端Java
- 遠端客戶端 訪問 ASM 例項客戶端ASM
- mysql賬戶新增遠端訪問MySql
- java的socket程式設計問題Java程式設計
- 客戶端的socket是否需要bind?客戶端
- java併發程式設計系列:牛逼的AQS(下)Java程式設計AQS
- java併發程式設計系列:牛逼的AQS(上)Java程式設計AQS
- 客戶端訪問POP3--SMTP客戶端
- 完善的Socket Server程式 (轉)Server
- java併發程式設計系列:java併發程式設計背景知識Java程式設計
- 客戶端GUI程式開發漫談客戶端GUI
- 純java開發的電子郵件客戶端Java客戶端
- 【JAVA 網路程式設計系列】Netty -- 基本編解碼方式的支援Java程式設計Netty
- server端雙socket 設計方式Server
- JAVA FTP客戶端問題JavaFTP客戶端
- Java併發程式設計系列之Semaphore詳解Java程式設計
- Docker部署mysql並提供客戶端訪問DockerMySql客戶端
- 客戶端 post ,get 訪問伺服器客戶端伺服器
- 如何用Java Socket實現一個簡單的Redis客戶端JavaRedis客戶端
- vnc遠端訪問,推薦四款免費又好用的vnc遠端訪問軟體VNC
- TCP程式設計之服務端和客戶端的開發TCP程式設計服務端客戶端
- Java服務端和客戶端開發輔助工具UtilsJava服務端客戶端
- java併發程式設計系列:wait/notify機制Java程式設計AI
- koa+mysql+vue+socket.io全棧開發之資料訪問篇MySqlVue全棧
- java區分訪問端來源Java
- 開發JAXR客戶端客戶端
- ExchangeServer2010客戶端的安全訪問Server客戶端