Java客户端 - 服务器和观察者

时间:2015-05-22 19:41:29

标签: java client-server observer-pattern

我正在为大学任务实现一个Java客户端 - 服务器应用程序,并且我坚持以下几点:我不得不使用客户端服务器,并且每当数据库中的数据发生更改时也会更新视图。我所做的是每当数据库发生变化时,我都会通过"更改数据来通知所有客户。消息,然后客户端应阅读并理解此消息,以便调用将更新其图形界面的方法。但是,或者我在客户端误读了阅读部分,或者由于某些错误,客户不会阅读“更改数据”和“#34;更改数据"消息,所以此时整个卡住了,视图没有更新。

以下是一些相关代码! 服务器类:

public class FinesPaymentServer implements Runnable {

private Database database;
private UserGateway userGateway;
private FineGateway fineGateway;
private DriverGateway driverGateway;
private Socket connection;
private int ID;
static ArrayList<Socket> clientsConnected;

/**
 * Constructor of the class connecting to the database and initializing the socket
 * @param database the database used
 * @param connection the socket for the server
 * @param ID the id
 */
private FinesPaymentServer(Database database, UserGateway userGateway, FineGateway fineGateway, DriverGateway driverGateway, Socket connection, int ID) {
    this.connection = connection;
    this.userGateway = userGateway;
    this.fineGateway = fineGateway;
    this.driverGateway = driverGateway;
    this.database = database;
    this.ID = ID;
}

/**
 * Run method of the threads for each socket on the server
 */
public void run() {
    try {
        while(true)
            readFromClient(connection);
    } catch (IOException | SQLException e) {
    System.out.println(e);
    }
}

 /**
 * Read method from the client
 * @param client the client socket from where to read
 * @throws IOException
 * @throws SQLException 
 */
public void readFromClient(Socket client) throws IOException, SQLException {
    BufferedInputStream is = new BufferedInputStream(client.getInputStream());
    InputStreamReader reader = new InputStreamReader(is);
    StringBuffer process = new StringBuffer();
    int character;
    while((character = reader.read()) != 13) {
        process.append((char)character);
    }
    System.out.println("[SERVER READ]: "+process);
    String[] words = process.toString().split("\\s+");
    switch (process.charAt(0)) {
        case 'a' : 
        {
            int type = database.verifyLogin(words[1], words[2]);
            sendMessage(client, ""+type + " ");
            break;
        }
        case 'b' :
        {
            String rs = userGateway.getUsers();
            sendMessage(client, rs);
            break;
        }
        case 'c' :
        {
            userGateway.createUser(words[1], words[2], words[3]);
            notifyClients();
            break;
        }
        case 'd' :
        {
            userGateway.updateUser(words[1], words[2], words[3]);
            notifyClients();
            break;
        }
        case 'e' :
        {
            userGateway.deleteUser(words[1]);
            notifyClients();
            break;
        }
    }
    try {
    Thread.sleep(1000);
    } catch (Exception e){}
    String time_stamp = new java.util.Date().toString();
    String returnCode = "Single Socket Server responded at " + time_stamp + (char) 13;
    sendMessage(client, returnCode);
}

/**
 * Method for sending messages from the server to the client
 * @param client the client socket where to send the message
 * @param message the message itself to be sent
 * @throws IOException 
 */
private void sendMessage(Socket client, String message) throws IOException {
    BufferedWriter writer = new BufferedWriter(
    new OutputStreamWriter(client.getOutputStream()));
    writer.write(message);
    System.out.println("[SERVER WRITE]: "+message);
    writer.flush();
}

public void notifyClients() throws IOException
{
    for(Socket s : clientsConnected)
    {
        sendMessage(s, "CHANGE IN DATA ");
    }
}

/**
 * @param args the command line arguments
 * @throws java.sql.SQLException
 */
public static void main(String[] args) throws SQLException {
    Database database = new Database();
    UserGateway userGateway = new UserGateway();
    FineGateway fineGateway = new FineGateway();
    DriverGateway driverGateway = new DriverGateway();
    clientsConnected = new ArrayList<>();
    // Setting a default port number.
    int portNumber = 2015;
    int count = 0;
    System.out.println("Starting the multiple socket server at port: " + portNumber);
    try {
    ServerSocket serverSocket = new ServerSocket(portNumber);
    System.out.println("Multiple Socket Server Initialized");
    //Listen for clients
    while(true) {
    Socket client = serverSocket.accept();
    clientsConnected.add(client);
    Runnable runnable = new FinesPaymentServer(database, userGateway, fineGateway, driverGateway, client, ++count);
    Thread thread = new Thread(runnable);
    thread.start();
    }
    } catch (Exception e) {}
}
}

客户端类:

public class FinesPaymentClient implements Runnable {

private String hostname = "localhost";
private int port = 2015;
Socket socketClient;
AdministratorModel adminModel;
PoliceModel policeModel;
PostModel postModel;

/**
 * Constructor of the class
 * @param hostname the host name of the connection
 * @param port the port of the connection
 * @throws UnknownHostException
 * @throws IOException 
 */
public FinesPaymentClient(String hostname, int port, AdministratorModel adminModel, PoliceModel policeModel, PostModel postModel) throws UnknownHostException, IOException
{
    this.hostname = hostname;
    this.port = port;
    this.adminModel = adminModel;
    this.policeModel = policeModel;
    this.postModel = postModel;
    connect();
}

/**
 * Method for connecting to the host by a socket
 * @throws UnknownHostException
 * @throws IOException 
 */
public void connect() throws UnknownHostException, IOException {
    System.out.println("Attempting to connect to " + hostname + ":" + port);
    socketClient = new Socket(hostname, port);
    System.out.println("Connection Established");
}

/**
 * Method for reading response from the server
 * @return the string read from the server
 * @throws IOException 
 */
public String readResponse() throws IOException {
    String userInput;
    BufferedReader stdIn = new BufferedReader(
    new InputStreamReader(socketClient.getInputStream()));
    System.out.println("[CLIENT READ]:");
    while ((userInput = stdIn.readLine()) != null) {
        System.out.println(userInput);
        return userInput;
    }
    return userInput;
}

/**
 * Method for closing connection between client and server
 * @throws IOException 
 */
public void closeConnection() throws IOException {
    socketClient.close();
}

/**
 * Method for writing messages to the server
 * @param message the message to be sent
 * @throws IOException 
 */
public void writeMessage(String message) throws IOException {
    String time_stamp = new java.util.Date().toString();
    // Please note that we placed a char(13) at the end of process...
    // we use this to let the server know we are at the end
    // of the data we are sending
    String process = message + (char) 13;
    BufferedWriter stdOut = new BufferedWriter(
    new OutputStreamWriter(socketClient.getOutputStream()));
    stdOut.write(process);
    System.out.println("[CLIENT WRITE]: "+process);
    // We need to flush the buffer to ensure that the data will be written
    // across the socket in a timely manner
    stdOut.flush();
}

@Override
public void run() {
    try {
        String response;
        while(true)
        {
            response = readResponse();
            System.out.println("HERE"+response.substring(0, 13));
            if(response.substring(0, 13).equals("CHANGE IN DATA"))
            {
                adminModel.setChange();
            }
        }
    } catch (IOException e) {
        System.out.println(e);
    }
}

/**
 * Main method of the application
 * @param arg the parameters given as arguments
 * @throws SQLException
 * @throws UnknownHostException
 * @throws IOException 
 */
public static void main(String arg[]) throws SQLException, UnknownHostException, IOException {
    AdministratorModel adminModel = new AdministratorModel();
    PoliceModel policeModel = new PoliceModel();
    PostModel postModel = new PostModel();
    FinesPaymentClient client = new FinesPaymentClient("localhost", 2015, adminModel, policeModel, postModel);
    Runnable client2 = new FinesPaymentClient("localhost", 2015, adminModel, policeModel, postModel);
    Thread thread = new Thread(client2);
    thread.start();
    Login login = new Login();
    ClientSide clientSide = new ClientSide(login, client, adminModel, policeModel, postModel);
}
}

ClientSide类:

public class ClientSide {
private final Login login;
private FinesPaymentClient client;
AdministratorModel adminModel;
PoliceModel policeModel;
PostModel postModel;

/**
 * Constructor instantiating needed classes
 * @param login an instance of the login class
 * @param client the client needing the control logic
 * @param adminModel
 * @param policeModel
 * @param postModel
 * @throws SQLException using classes connecting to a database sql exceptions can occur
 */
public ClientSide(Login login, FinesPaymentClient client, AdministratorModel adminModel, PoliceModel policeModel, PostModel postModel) throws SQLException
{
    this.login = login;
    this.client = client;
    this.adminModel = adminModel;
    this.policeModel = policeModel;
    this.postModel = postModel;
    login.addButtonListener(new ButtonListener());
}

/**
 * Listener for the login button. Reads, verifies and provides the interface according to logged in user type.
 */
class ButtonListener implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
        try 
        {
            client.writeMessage("a " + login.field1.getText()+ " " + login.field2.getText());
            String response = client.readResponse();
            if(response.charAt(0) == '1')
            {   
                login.setVisible(false);
                AdministratorGUI administratorGUI = new AdministratorGUI(adminModel, client);
                AdministratorController adminController = new AdministratorController(client, administratorGUI, adminModel);              
            }
            //if user is post office employee
            else if(response.charAt(0) == '2')
            {
                login.setVisible(false);
                PostGUI postGUI = new PostGUI();
                PostController postController = new PostController(client, postGUI, postModel);
            }
            //if user is police employee
            else if(response.charAt(0) == '3')
            {
                login.setVisible(false);
                PoliceGUI policeGUI = new PoliceGUI();
                PoliceController policeController = new PoliceController(client, policeGUI, policeModel);              
            }
            else
            {
                JOptionPane.showMessageDialog(null,"Login failed! Please try again!");
            }
        } 
        catch (IOException ex) 
        {
            Logger.getLogger(ClientSide.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
}

我99%确定错误是在客户端读取从服务器发送的消息作为通知,但我根本无法弄清楚如何检索该消息。现在我尝试使用客户端线程运行方法,但不起作用。其他类和其他功能工作得很好,这是我唯一的问题。你有什么想法可能是错误吗?我将不胜感激任何帮助。

0 个答案:

没有答案
相关问题