这是thenewboston的java即时通讯程序的(稍微)修改版本。
但似乎有问题。 如果我在同一设备上运行服务器和客户端它正常工作,但如果客户端在另一台PC(本地)上则无法连接。
P.S我对网络,流和套接字知之甚少,所以请记住这一点。
编辑:一切都已修复,使用了客户端错误的IP地址!//SERVER
public class Server {
private JFrame frame;
private JTextField userText;
private JTextArea textArea;
private ObjectOutputStream output;
private ObjectInputStream input;
private ServerSocket server;
private Socket connection;
private boolean userTerminatedConnection = false;
private static final int PORT = 6789;
public static void main(String[] args) {
Server window = new Server();
window.frame.setVisible(true);
window.startServer();
}
public Server() {
initialize();
}
private void initialize() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e1){}
frame = new JFrame("SERVER");
frame.setBounds(300, 300, 318, 338);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
userText = new JTextField();
frame.getContentPane().add(userText, BorderLayout.SOUTH);
userText.setEditable(false);
userText.setColumns(10);
userText.addActionListener(new
ActionListener(){
@Override
public void actionPerformed(ActionEvent arg0) {
sendMessage(arg0.getActionCommand());
userText.setText(null);
}
}
);
textArea = new JTextArea();
textArea.setEditable(false);
textArea.setFont(new Font("Monospaced", Font.PLAIN, 15));
frame.getContentPane().add(new JScrollPane(textArea), BorderLayout.CENTER);
}
public void startServer(){
try{
server = new ServerSocket(PORT);
System.out.println(InetAddress.getLocalHost().getHostAddress());
while(true){
try{
waitForConnection();
setupStreams();
whileChatting();
}catch(EOFException e){
showMessage("\nSERVER TERMINATED CONNECTION");
}finally{
closeAll();
}
}
}catch(Exception e){
e.printStackTrace();
}
}
private void whileChatting() throws IOException{
String message ="You are now connected !";
sendMessage(message);
ableToType(true);
do{
try{
message = (String) input.readObject();
showMessage("\n"+message);
}catch(ClassNotFoundException e){
showMessage("\n UNRECOGNISED OBJECT");
}catch(SocketException ex){
userTerminatedConnection = true;
}
}while(!message.endsWith("ENDCONN") && !userTerminatedConnection);
userTerminatedConnection = false;
}
private void setupStreams() throws IOException{
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
}
private void waitForConnection() throws IOException {
showMessage("Waiting for connection...\n");
connection = server.accept();
showMessage("Now connected to "+connection.getInetAddress().getHostName());
}
private void closeAll() {
showMessage("\nClosing connection \n");
ableToType(false);
try{
input.close();
output.close();
connection.close();
}catch(IOException e){
}
}
private void ableToType(final boolean b) {
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
userText.setEditable(b);
}
}
);
}
private void sendMessage(String string) {
try{
output.writeObject("SERVER - "+string);
output.flush();
showMessage("\nSERVER - "+string);
}catch(IOException e){
textArea.append("\nCANT SEND");
}
}
private void showMessage(final String string) {
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
textArea.append(string);
}
}
);
}
}
//CLIENT
public class Client {
private JFrame frame;
private JTextField userText;
private JTextArea chatBox;
private ObjectOutputStream output;
private ObjectInputStream input;
private String message;
private String serverIP;
private Socket connection;
private boolean isConnected = false;
private String clientName = "CLIENT";
public static void main(String[] args) throws IOException {
Client window = new Client();
window.frame.setVisible(true);
window.clientName = JOptionPane.showInputDialog(null, "Enter client nickname");
String ipEntered = JOptionPane.showInputDialog(null, "Enter the ip address to establish connection !");
if(ipEntered.equals("localhost")||ipEntered.equals("")){
ipEntered = "127.0.0.1";
}
if(window.clientName.equals("")){
window.clientName = "CLIENT";
}
if(window.clientName.toCharArray().length > 15){
window.clientName = "CLIENT";
}
window.setHostIp(ipEntered);
window.startClient();
}
public Client() {
initialize();
}
private void setHostIp(String host){
serverIP = host;
}
private void initialize() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e1){}
frame = new JFrame("Client");
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent arg0) {
if(isConnected)
closeAll();
}
});
frame.setBounds(100, 100, 318, 338);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
chatBox = new JTextArea();
chatBox.setFont(new Font("Monospaced", Font.PLAIN, 15));
frame.getContentPane().add(new JScrollPane(chatBox), BorderLayout.CENTER);
userText = new JTextField();
userText.setFont(new Font("Tahoma", Font.PLAIN, 11));
userText.setEditable(false);
frame.getContentPane().add(userText, BorderLayout.SOUTH);
userText.setColumns(10);
userText.addActionListener(
new ActionListener(){
@Override
public void actionPerformed(ActionEvent arg0) {
sendData(arg0.getActionCommand());
userText.setText("");
}
}
);
}
private void startClient() throws IOException{
try{
connectToServer();
setupStreams();
whileChatting();
isConnected = true;
}catch(EOFException ex){
showMessage("\nClient terminated connection");
}finally{
if(isConnected)
closeAll();
else
System.exit(0);
}
}
private void connectToServer() throws IOException{
showMessage("\nAttempting connection");
connection = new Socket(InetAddress.getByName(serverIP),6789);
showMessage("\nConnected to :"+connection.getInetAddress().getHostName());
}
private void setupStreams() throws IOException {
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
}
private void whileChatting() throws IOException{
ableToType(true);
do{
try{
message = (String) input.readObject();
showMessage("\n"+message);
}catch(ClassNotFoundException e){
showMessage("UNRECOGNISED OBJECT");
}
}while(!message.equals("SERVER - ENDCONN"));
}
private void closeAll() {
showMessage("\nClosing stuff");
ableToType(false);
try{
output.close();
input.close();
connection.close();
}catch(IOException e){
}
System.exit(0);
}
private void sendData(String mess) {
try{
output.writeObject(clientName+" - "+mess);
showMessage("\n"+clientName+" - "+mess);
}catch(IOException e){
chatBox.append("\nSomething went wrong");
}
}
private void showMessage(String string) {
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
chatBox.append(string);
}
}
);
}
private void ableToType(final boolean b) {
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
userText.setEditable(b);
}
}
);
}
}
答案 0 :(得分:0)
问题是这个方法:waitForConnection();
最终会阻塞整个流程,以便它可以等待传入连接并在它们到来时处理它们。
您需要做的是确保传入连接的等待和处理是在单独的线程上完成的,以确保您不会阻止当前的应用程序。
编辑:
.accept()
方法阻止主线程,直到新连接到达。通常做的事情(取决于您正在构建的服务器的类型)是.accept
部分是在一个单独的线程中完成的。你需要这样做,以便在另一个线程上完成等待,并且你不会阻止你的主线程。
现在,有些情况出现了响应可能需要时间。为了解决这个问题,响应的构造和传输也是在一个单独的线程中完成的,以便现在影响新的请求。
如果这不是一个要求(您可以等待几秒钟以获得回复,或者如果您可以相对较快地构建响应,或者您将拥有相对较少的客户端数量)那么您可以不进行创建一个新线程来满足传入的请求,并创建一个等待传入连接的线程。