我創建了一個基於服務器的聊天程序,該程序有多個工作線程,每個線程處理套接字上的客戶端。它有一個服務器套接字將客戶端傳遞給工作線程。Java使用客戶端套接字的多個線程
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(4001);
System.out.println("Listening server");
while (true) {
Socket socket = serverSocket.accept();
System.out.println("Connected");
Random rand= new Random();
int port=4001+rand.nextInt(5);
Worker worker = new Worker(port);
executor.execute(worker);
System.out.println("Thread started");
new PrintWriter(socket.getOutputStream(), true).println(port);
socket.close();
System.out.println("Closed");
// break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
public class Worker implements Runnable {
private int port;
public Worker(int i) {
port=i;
}
@Override
public void run() {
worker();
}
private static Socket socket;
private static PrintWriter out;
private static BufferedReader in;
private void worker() {
try {
ServerSocket serverSocket = new ServerSocket(port);
socket = serverSocket.accept();
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
System.out.println("Received: " + line);
switch (line) {
case ("Button Press"):
System.out.println("Handled button");
out.println("Button acknowledged");
break;
case ("Give me some data"):
System.out.println("Handled data");
out.println("Have some data");
break;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
out.close();
in.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
這工作得很好,然而,問題是當我有由客戶端的自動請求來檢查消息和用戶提供的相同類型的某些輸入。這會導致衝突,因爲實際方法需要運行幾秒鐘,並且如果接收到更多輸入,則請求將不會被處理,因爲它位於方法的中間。例如:
private static BufferedReader in;
private static PrintWriter out;
public static void main(String[] args) {
Main main=new Main();
main.createWindow();
try {
Socket init = new Socket(InetAddress.getLocalHost(), 4001);
int port
=Integer.parseInt
(new BufferedReader
(new InputStreamReader(init.getInputStream())).readLine());
init.close();
Socket socket=new Socket(InetAddress.getLocalHost(), port);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while(true){
try {
Thread.sleep(5000);
out.println("Give me some data");
if(in.readLine().equals("Have some data")){
System.out.println("Data recieved");
}else{
System.out.println("Data not recieved");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void createWindow(){
JFrame frame =new JFrame("This is a button");
Container pane=getContentPane();
JButton button=new JButton("This is a button");
button.addActionListener(this);
pane.add(button);
frame.setTitle("Messaging");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(pane);
frame.setVisible(true);
frame.setSize(400, 350);
}
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Button press");
try {
out.println("Button Press");
if(in.readLine().equals("Button acknowledged")){
System.out.println("Button complete");
}else{
System.out.println("Button fail");
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
如果按鈕被按下,而服務器獲取數據它衝突和錯誤的響應發送。那麼我會如何處理這個問題呢?如果我創建一個單獨的套接字來處理自動檢查,這是服務器必須處理的線程數量的兩倍。有更好的解決方案嗎? 請你可以嘗試解釋,因爲這對我來說是一個新的領域。
你的第一個問題是這些變量都不應該是靜態的,而那些指向特定客戶端的變量應該在'Worker'類中,而不是服務器類中。 – EJP
是的服務器工人類中的變量可能不應該是靜態的,但這是因爲這是我在5分鐘內扔在一起的東西,以提供我的問題的一個例子。 而引用特定客戶端的變量不在工作者類中,就我所見,它只是服務器套接字,最初的套接字和線程池。那麼哪些不是在那裏?但正如我已經說過的那樣,這只是一些快速拼湊在一起的代碼,試圖幫助解決我的問題,所以它不會是完美的。 – Nightfortress