[英]Java Socket Issue: Message Can Only Be Passed For One Time
最近,我正在嘗試一項練習,該練習要求基於tcp套接字設計具有兩個客戶端的服務器。 連接后,SenderClient應該將用戶鍵入的消息發送到Server,然后Server應該將該消息轉發到ReceiverClient。 它像是:
SenderClient->服務器-> ReceiverClient
僅當用戶在發件人中鍵入“退出”時,所有程序才會被終止,否則它們始終在偵聽消息。
現在,我遇到了一個問題:當我在Eclipse Luna中運行這三個程序時,我發現消息只能從SenderClient-> Server-> ReceiverClient成功傳遞一次。 之后,該消息將在服務器處被阻止。 你們還可以在計算機上運行這三個程序來查看奇怪的現象嗎? 謝謝,在這里真的需要幫助。
import java.io.*;
import java.net.*;
public class Server {
public static void main (String args[]) {
InputStream is = null;
InputStreamReader isr = null;
BufferedReader br = null;
OutputStream os = null;
PrintWriter pw = null;
String info = null;
try {
// listening to port
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("Server is listening to port 8888...");
while (true) {
// respond to clients
Socket receiverSocket = serverSocket.accept();
System.out.println("receiver client connected!");
Socket senderSocket = serverSocket.accept();
System.out.println("sender client connected!");
// get input stream, read messages from sender
is = senderSocket.getInputStream();
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
info = br.readLine();
// close all resources when user types "quit"
if (info.equalsIgnoreCase("quit")) {
// close resources when user types "quit"
is.close();
isr.close();
br.close();
os.close();
pw.close();
serverSocket.close();
System.out.println("Server terminated!");
break;
}
// print out the message
if (info != null) {
System.out.println("Sender -> Server: " + info);
}
// get output stream, forward messages to receiver
os = receiverSocket.getOutputStream();
pw = new PrintWriter(os);
pw.println(info);
pw.flush();
} // end while
} catch (IOException e) {
e.printStackTrace();
} // end try...catch
} // end main method
} // end class Server
import java.io.*;
import java.net.*;
public class ReceiverClient {
public static void main (String args[]) {
InputStream is = null;
BufferedReader br = null;
String info = null;
try {
while (true) {
// create receiver socket with host and port number
Socket receiverSocket = new Socket("localhost", 8888);
// get input stream, read the information
is = receiverSocket.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
info = br.readLine();
// close all resources when user types "quit"
if (info.equalsIgnoreCase("quit")) {
is.close();
br.close();
System.out.println("Receiver client terminated!");
break;
}
// print out the message
if (info != null) {
System.out.println("Sender -> Server -> Receiver: " + info);
}
receiverSocket.close();
} // end while
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} // end try...catch
} // end main method
} // end class ReceiverClient
import java.io.*;
import java.net.*;
public class SenderClient {
public static void main (String args[]) {
OutputStream os = null;
PrintWriter pw = null;
BufferedReader br = null;
String userInput = null;
try {
while (true) {
// create sender socket with host and port number
Socket senderSocket = new Socket("localhost", 8888);
// get message from user input
System.out.println("Please input a message:");
br = new BufferedReader(new InputStreamReader(System.in));
userInput = br.readLine();
// get output stream, send message to server
os = senderSocket.getOutputStream();
pw = new PrintWriter(os);
pw.println(userInput);
pw.flush();
senderSocket.close();
// close all resources when user types "quit"
if (userInput.equalsIgnoreCase("quit")) {
os.close();
pw.close();
System.out.println("Sender client terminated!");
break;
}
} // end while
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} // end try...catch
} // end main method
} // end class SenderClient
Socket receiverSocket = serverSocket.accept();
ServerSocket
的accept()
方法是一項阻止操作:它等待傳入的連接,直到此代碼運行的線程等待。 第一次正確執行循環,因為您有兩個客戶端連接到服務器。 第二次執行循環時,您等待另一個傳入的客戶端。 一種解決方案是通過實現java.lang.Runnable
接口在單獨的線程中處理消息,該接口是在新啟動的線程上運行的代碼:
class ClientConnection implements Runnable{
private Socket sender;
private Socket receiver;
public ClientConnection(Socket sender, Socket receiver){
this.sender = sender;
this.receiver = receiver;
}
@Override
public void run(){
is = sender.getInputStream();
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
OutputStream os = receiver.getOutputStream();
PrintWriter pw = new PrintWriter(os);
boolean clientQuit = false;
while(!clientQuit){
info = br.readLine();
if (info.equalsIgnoreCase("quit")) {
// close resources when user types "quit"
is.close();
isr.close();
br.close();
os.close();
pw.close();
serverSocket.close();
System.out.println("Server terminated!");
clientQuit = true;
} else{
pw.println(info);
pw.flush;
}
}
}
}
每當服務器獲得兩個傳入連接時,它都會啟動一個新的Thread
來處理該連接,然后繼續接受新的傳入連接:
while (true) {
// respond to clients
Socket receiverSocket = serverSocket.accept();
System.out.println("receiver client connected!");
Socket senderSocket = serverSocket.accept();
System.out.println("sender client connected!");
ClientConnection connection = new ClientConnection(senderSocket, receiverSocket);
Thread connectionThread = new Thread(connection);
connectionThread.start();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.