Dears,

This blog is moved to a new blog at:

The new update will be found at that new blog, please follow it!
This blog is no more updated.
Thanks for your visit!

Friday, August 23, 2013

Socket programming with UDP protocol

Objective
In this topic, we will develop a login application based on Client-Server model with UDP protocol. The program is constructed on the MVC model for both client and server sides.

The application will be organized as follow:
- At the server side, the server manages a database which contains a table containing the user data, including username and password for each one
- the server does not need a graphical interface, so we could use console interface for it
- At the client side, the client have to provide a graphical interface which enables user to enter his username/password to login

Class diagrams
At the client side, there are three classes:
- User: this is an model class which contains at least two attributes: username, and password. This class is commonly used on both client and server side.
- ClientView: a graphical view class enabling user to enter username/password to login and then, displaying the results of login to the user
- ClientControl: a control class which gets username/password form view class and send them to server to check whether it is correct, and then receives the results from the server to send to view class to display.



 At the server side, as we could commonly use model class (User) with client side, there are only two classes:
- ServerView: a text (console) simple view class to display the real status of server
- ServerControl: a control class which listens the data going from client side, check it when received to see whether it is correct and then, return the results to the corresponding client.

 
 The sequence of activities is represented as following sequence diagram:

 

 1: an user (actor) enters his username and password on the ClientView interface
2: ClientView packs these two attributes into an object of User class
3: ClientView sends this object to ClientControl
4: ClientControl sends this object to ServerControl via UDP protocol
5: ServerControl checks the login data
6: ServerControl returns the results to ClientControl
7: ClientControl sends these results to ClientView
8: ClientView displays the login result to the user


User.java
package udp.client;
import java.io.Serializable;

public class User implements Serializable{
    private String userName;
    private String password;
   
    public User(){      
    }
   
    public User(String username, String password){
        this.userName = username;
        this.password = password;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getUserName() {
        return userName;
    }

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


ClientView.java
package udp.client;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

public class ClientView extends JFrame implements ActionListener{
    private JTextField txtUsername;
    private JPasswordField txtPassword;
    private JButton btnLogin;
   
    public ClientView(){
        super("UDP Login MVC");
      
        txtUsername = new JTextField(15);
        txtPassword = new JPasswordField(15);
        txtPassword.setEchoChar('*');
        btnLogin = new JButton("Login");
      
        JPanel content = new JPanel();
        content.setLayout(new FlowLayout());
        content.add(new JLabel("Username:"));
        content.add(txtUsername);
        content.add(new JLabel("Password:"));
        content.add(txtPassword);
        content.add(btnLogin);
                
        this.setContentPane(content);
        this.pack();
      
        this.addWindowListener(new WindowAdapter(){
            public void windowClosing(WindowEvent e){
                System.exit(0);
            }
        });
    }

    public void actionPerformed(ActionEvent e) {
    }
   
    public User getUser(){
        User model = new User(txtUsername.getText(), txtPassword.getText());
        return model;      
    }
   
    public void showMessage(String msg){
        JOptionPane.showMessageDialog(this, msg);
    }
   
    public void addLoginListener(ActionListener log) {
          btnLogin.addActionListener(log);
        }
}


ClientControl.java
 package udp.client;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;


public class ClientControl {
    private ClientView view;
    private int serverPort = 5555;
    private int clientPort = 6666;
    private String serverHost = "localhost";
    private DatagramSocket myClient;
  
    public ClientControl(ClientView view){
        this.view = view;
        this.view.addLoginListener(new LoginListener());
    }
  
    class LoginListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            openConnection();
          
            User user = view.getUser();
            sendData(user);
          
            String result = receiveData();
            if(result.equals("ok"))
                view.showMessage("Login succesfully!");
            else
                view.showMessage("Invalid username and/or password!");
              
            closeConnection();
        }
    }
  
    private void openConnection(){
        try {
            myClient = new DatagramSocket(clientPort);
        } catch (Exception ex) {
            view.showMessage(ex.getStackTrace().toString());
        }
    }
  
    private void closeConnection(){
        try {
            myClient.close();
        } catch (Exception ex) {
            view.showMessage(ex.getStackTrace().toString());
        }
    }
  
    private void sendData(User user){
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(user);
            oos.flush();          
          
            InetAddress IPAddress = InetAddress.getByName(serverHost);              
            byte[] sendData = baos.toByteArray();
            DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, serverPort);
            myClient.send(sendPacket);
          
        } catch (Exception ex) {
            view.showMessage(ex.getStackTrace().toString());
        }
    }
  
    private String receiveData(){
        String result = "";
        try {          
            byte[] receiveData = new byte[1024];
            DatagramPacket receivePacket = new    DatagramPacket(receiveData, receiveData.length);
            myClient.receive(receivePacket);
          
            ByteArrayInputStream bais = new ByteArrayInputStream(receiveData);
            ObjectInputStream ois = new ObjectInputStream(bais);
            result = (String)ois.readObject();
        } catch (Exception ex) {
            view.showMessage(ex.getStackTrace().toString());
        }
        return result;
    }






    public static void main(String[] args) {
        ClientView view = new ClientView();
        ClientControl control = new ClientControl(view);
        view.setVisible(true);
    }
}


ServerView.java
package udp.server;

public class ServerView {
    public ServerView(){       
    }
   
    public void showMessage(String msg){
        System.out.println(msg);
    }   
}


ServerControl.java
package udp.server;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import udp.client.User;


public class ServerControl {
    private ServerView view;
    private Connection con;
    private DatagramSocket myServer;
    private int serverPort = 5555;
    private DatagramPacket receivePacket = null;
   
    public ServerControl(ServerView view){
        this.view = view;
        getDBConnection("loginDB", "root", "123456");
        openServer(serverPort);
        view.showMessage("UDP server is running...");
       
        while(true){
            listenning();
        }
    }
   
    private void getDBConnection(String dbName, String username, String password){
        String dbUrl = "jdbc:mysql://localhost:3306/" + dbName;
        String dbClass = "com.mysql.jdbc.Driver";

        try {
            Class.forName(dbClass);
            con = DriverManager.getConnection (dbUrl, username, password);
        }catch(Exception e) {
            view.showMessage(e.getStackTrace().toString());
        }
    }
   
    private void openServer(int portNumber){
        try {
            myServer = new DatagramSocket(portNumber);
        }catch(IOException e) {
            view.showMessage(e.toString());
        }
    }
   
    private void listenning(){
        User user = receiveData();

        String result = "false";
        if(checkUser(user)){
            result = "ok";
        }
       
        sendData(result);        
    }
   
    private void sendData(String result){
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(result);
            oos.flush();           
           
            InetAddress IPAddress = receivePacket.getAddress();
            int clientPort = receivePacket.getPort();
            byte[] sendData = baos.toByteArray();
            DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, clientPort);
            myServer.send(sendPacket);
           
        } catch (Exception ex) {
            view.showMessage(ex.getStackTrace().toString());
        }
    }
   
    private User receiveData(){
        User user = null;
        try {           
            byte[] receiveData = new byte[1024];
            receivePacket = new    DatagramPacket(receiveData, receiveData.length);
            myServer.receive(receivePacket);
           
            ByteArrayInputStream bais = new ByteArrayInputStream(receiveData);
            ObjectInputStream ois = new ObjectInputStream(bais);
            user = (User)ois.readObject();
           
        } catch (Exception ex) {
            view.showMessage(ex.getStackTrace().toString());
        }
        return user;
    }

   
    private boolean checkUser(User user) {
        String query = "Select * FROM users WHERE username ='" + user.getUserName()
                + "' AND password ='" + user.getPassword() + "'";

        try {
            Statement stmt = con.createStatement();
            ResultSet rs = stmt.executeQuery(query);

            if (rs.next()) {
              return true;
            }
        }catch(Exception e) {
            view.showMessage(e.getStackTrace().toString());
        }    
        return false;
      }
}


Deploying
- Create a database named "LoginDB" in a DBMS at the server side, in which, create a table containing two columns: username, password
- run the ServerControl first
- then run the ClientControl.