Java:使用 AWT 按钮与聊天服务器断开连接

huangapple go评论75阅读模式
英文:

Java: Using AWT button to disconnect from chat server

问题

我正在编写一个简单的多线程客户端/服务器聊天系统。项目要求如下:“只有在单击连接按钮时才能连接。断开连接按钮应断开连接。用户应能够随意连接、断开连接、重新连接。”基本上,我已经连接了并运行了连接按钮。然而,当我尝试断开连接时,我陷入了一个无限循环中,在客户端(在命令行上)无限地打印“Sock closed”,而服务器端无限地打印“Message read: null”。这导致我查看了所有的for(;;)循环,试图在其中关闭连接,但是我无法弄清楚如何在这些循环内关闭连接。请帮助我,这是我第一个套接字编程项目,我对这个问题感到非常困惑!谢谢大家。

客户端:

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.ArrayList;

public class ClientFrame extends Frame{
    // ...(省略其他代码)
} // 结束 ClientFrame

class ClientPanel extends Panel implements ActionListener, Runnable{
    // ...(省略其他代码)
} // 结束 ClientPanel

服务器:

import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.awt.*;

public class ThreadedServerWithPresence{
    public static void main(String[] args){
        // ...(省略其他代码)
    }
}

class ThreadedHandlerWithPresence extends Thread{
    // ...(省略其他代码)
}

请注意,这只是您提供的代码的翻译。如果您需要更多的帮助或解释,请随时提问。

英文:

I am programming a simple multi-threaded client/server chat system. Project requirements specify: "Connection only happens when the connect button is clicked. The disconnect button should disconnect the connection. A user should be able to connect, disconnect, re-connect at will." Basically, I have the connect button hooked-up and running. However, when I attempt to disconnect I get stuck in an infinite loop where the client side (on command line) infinitely prints "Sock closed", while the server side infinitely prints "Message read: null". This has lead me to look into all of my for(;;) loops to somehow close the connections within them, however I cannot figure out how to close the connection within those loops. Please help, this is my first socket programming project and I am super stumped on this one! Thanks all.

Client:

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.ArrayList;

public class ClientFrame extends Frame{
	public ClientFrame(){
		setSize(500,500);
		setTitle("Chat Client");
		addWindowListener(new WindowAdapter(){
			public void windowClosing(WindowEvent We){
				System.exit(0);
			}
		});
		add(new ClientPanel(), BorderLayout.CENTER);		
		setVisible(true);
	}
	public static void main(String[] args){
		new ClientFrame();
	}

} // end ClientFrame

class ClientPanel extends Panel implements ActionListener, Runnable{
	TextField tf;
	TextArea ta;
	List list;
	Button connect, disconnect;
	Socket socketToServer;
	PrintWriter pw;
	BufferedReader br;
	Thread t;
	String userName;

	public ClientPanel(){
		setLayout(new BorderLayout());
		tf = new TextField();
		ta = new TextArea();
		list = new List();
		connect = new Button("Connect");
		disconnect = new Button("Disconnect");
		Panel bPanel = new Panel();
		bPanel.add(connect);
		disconnect.setEnabled(false);
		bPanel.add(disconnect);
		
		tf.addActionListener(this);
		add(tf, BorderLayout.NORTH);
		add(ta, BorderLayout.CENTER);
		add(list, BorderLayout.EAST);
		add(bPanel, BorderLayout.SOUTH);
		
		connect.addActionListener(this);
		disconnect.addActionListener(this);
	
	} // end ClientPanel constructor


	public void actionPerformed(ActionEvent ae){
		if (ae.getSource() == tf){
			String temp = tf.getText();
			pw.println(userName+": "+temp);
			tf.setText("");
		} else if (ae.getSource() == connect){
			if(tf.getText() == null || tf.getText().equals("")){
					ta.append("Must enter a name to connect\n");
				}else {	
					userName = tf.getText();
					connect.setEnabled(false);
					disconnect.setEnabled(true);
					tf.setText("");		
					try{
						socketToServer = new Socket("127.0.0.1", 3000);
						pw = new PrintWriter(new OutputStreamWriter
								(socketToServer.getOutputStream()), true);
						br = new BufferedReader(new	InputStreamReader
								(socketToServer.getInputStream()));
					}catch(UnknownHostException uhe){
						System.out.println(uhe.getMessage());
					}catch(IOException ioe){
						System.out.println(ioe.getMessage());
					} 
				}

					t = new Thread(this);
					t.start();
					pw.println(userName);
					pw.println(userName +" has entered the chat.");
		}else if (ae.getSource()== disconnect){
			try{
				t.interrupt();
            	socketToServer.close();
        	}catch(IOException ioe){
            	System.out.println(ioe.getMessage());
        	}
		}
	} // end actionPerformed

	public void run(){
			for(;;){
				try{
					String temp = br.readLine();
					ta.append(temp + "\n");
				}catch(IOException ioe){
					System.out.println(ioe.getMessage());
				} 
			}
	} // end run

} // end ClientPanel

Server:

import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.awt.*;

public class ThreadedServerWithPresence{  
	public static void main(String[] args){  
		ArrayList<ThreadedHandlerWithPresence> handlers;
      		try{  	
			handlers = new ArrayList<ThreadedHandlerWithPresence>();
			ServerSocket s = new ServerSocket(3000);
         		for(;;){  
				Socket incoming = s.accept( );
				new ThreadedHandlerWithPresence(incoming, 
									handlers).start();

	 		}   
      		}catch (Exception e){  
				System.out.println(e);
      		}
   	} 
}

class ThreadedHandlerWithPresence extends Thread{  

	Socket incoming;
	ArrayList<ThreadedHandlerWithPresence> handlers;
	PrintWriter pw;
	BufferedReader br;
	String userName;

	public ThreadedHandlerWithPresence(Socket i,
	 	ArrayList<ThreadedHandlerWithPresence> handlers){ 
   		incoming = i;
		this.handlers = handlers;
		handlers.add(this);
   	}

	public void setUserName(String userName){
		this.userName = userName;
	}

	public String getUserName(){
		return userName;
	}
   
   	public void run(){  
		try{ 	
			br = new BufferedReader(new InputStreamReader
							(incoming.getInputStream()));

			pw = new PrintWriter(new OutputStreamWriter
							(incoming.getOutputStream()),true);
           
			String firstLine = br.readLine();
			setUserName(firstLine);

			for(;;){
            	
            	String temp = br.readLine();

				System.out.println("Message read: " + temp);
		
				for(int i = 0; i < handlers.size(); i++){
					handlers.get(i).pw.println(temp);
				}
			}		    
      		}catch (Exception e){  
			System.out.println(e);
      		}finally{
				handlers.remove(this); 
			} 
   	}
}

答案1

得分: 0

Client

你的run方法没有处理中断,所以for循环不会结束,它会继续尝试接收消息。

你需要添加一个可中断并且抛出InterruptedException的动作,在这种情况下,Thread.sleep可能是一个很好的选择,还可以减少CPU使用(你不需要每一刻都检查新消息)。

try {
    for (; ; ) {
        try {
            String temp = br.readLine();
            ta.append(temp + "\n");
        } catch (IOException ioe) {
            System.out.println(ioe.getMessage());
        }
        Thread.sleep(10);
    }
} catch (InterruptedException e) {
    System.out.println("Disconnected.");
}

Server

br.readLine()返回null时,表示连接已被客户端关闭,你应该停止接收消息。

String temp = br.readLine();

if(temp == null)
    break;
英文:

Client

Your run method does not handle interruptions so the for loop does not end and it continues trying to receive messages.

You must add an action that can be interrupted and throws InterruptedException, Thread.sleep would be a good candidate in this case, also reducing CPU usage (You do not need to check for new messages every single moment).

    try {
        for (; ; ) {
            try {
                String temp = br.readLine();
                ta.append(temp + "\n");

            } catch (IOException ioe) {
                System.out.println(ioe.getMessage());

            }
            Thread.sleep(10);
        }
    } catch (InterruptedException e) {
        System.out.println("Disconnected.");
    }

Server

When br.readLine() returns null, that indicates the connection is closed by the client and you should stop receiving messages.

        String temp = br.readLine();

        if(temp == null)
            break;

huangapple
  • 本文由 发表于 2020年7月25日 04:55:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/63081353.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定