Objective
In this topic, we will develop a full application of TCP/IP 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 customer data
– The server has a graphical interface to manipulate the server socket such as start, stop, and show the connections from clients.
– At the client side, There are graphical interfaces: one is the main interface to manipulate the connection to the server: connect, disconnect, choose the function… Other enables user to search and edit information of a customer.
Class diagrams
At the third side, there are entity classes (They could be implemented in a separated project and then, exported to a .jar file to be imported into the client project and the server project):
- Customer: this is an model class containing all necessary customer attributes. This class is commonly used on both client and server side.
- ObjectWrapper: this is a kind of exchange data between client-server. This wraps an entity and a performative which indicates the requirement type from client or the result type from the server to distinguish the current service/function on each connection.
- IPAddress: the entity containing the information about the host and the port of a server
At the client side, there are following classes (some relationship among classes are omitted, these classes could also be implemented in a separated TCP client project) ):
- ClientMainFrm: the main client interface to manipulate the connection to the server: connect, disconnect, choose the function…
- SearchCustomerFrm: a graphical view class enabling user to search and choose the customer to update.
- EditCustomerFrm: the form to edit information of the chosen customer
- ClientCtr: a control class to connect and exchange the data to/from server side.
- ClientListening: a class to receive all data from server. Normally, when a client send data to the server to process, it need only wait for the result returned from the server, that’s enough. However, in this application, when there is a new connection from client side or there is a client disconnected to server, the server will inform the current number of client connection to all connected clients. This is not predictable, so we need create a thread at the client side to ready receive all data from the server in anytime. Therefore, in this listening thread, when receiving a message from the server, this thread has to base on the message performative to detect that message is sent to which client function in the list “myFunction” of the ClientCtr class to call the method receiveDataProcessing() of the respective form to display the result on the form.

At the server side, there are some other classes (these classes could also be implemented in a separated TCP server project) :
- At the DAO level, there are two classes of DAO and CustomerDAO which has two method: searchCustomer() to search all customer whose name contains the input string, and editCustomer() to update the data of the given input customer.
- At the business control level, there are also three classes:
- ServerCtr to manage the server socket. This will create a ServerListening thread inside its constructor.
- ServerListening is a Thread inherited class to listening the connection from client. This will create a ServerProcessing thread when there is a new connection from a client.
- ServerProcessing is a thread-based class to serve e connection from client. In this processing thread, we have to be based on the performative of the incoming message to call the respective function from the DAO level. The performative value is defined as some constant in the ObjectWrapper class (see in the code at the bottom).
- At the view level, there is the ServerMainFrm to manipulate the server socket: open, close, and display information a bout it.
The sequence of activities is represented as following sequence diagram:
- Step 1-10 : the server opens server socket at the server side
- Step 11-31: a client connect to the server, server create the processing thread for the client (16-18) and inform the number of client connections to all connected clients (23-28).
- Step 32-57: client user choose the search customer by name, the client wraps the keyword into an wrapper object (39-41) and then, send the keyword to server (42-44), the server searches in the DB (45-50), wraps the results (51-53) and return the results to the client (54), the client show it to the user (55-57).
- Step 58-83: client user choose a customer to update, the client wraps (65-70) and then, send the modified object to server (71-73), the server updates it into the DB (74-76) and then, wraps (77-79) and return the results to the client (80). The client show the success message to the user (81-83).

Complete code
Class: Customer.java
package model;
import java.io.Serializable;
public class Customer implements Serializable{
private static final long serialVersionUID = 20210811004L;
private int id;
private String name;
private String idCard;
private String address;
private String tel;
private String email;
private String note;
public Customer() {
super();
}
public Customer(String name, String idCard, String address, String tel, String email, String note) {
super();
this.name = name;
this.idCard = idCard;
this.address = address;
this.tel = tel;
this.email = email;
this.note = note;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIdCard() {
return idCard;
}
public void setIdCard(String idCard) {
this.idCard = idCard;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
}
Class: ObjectWrapper.java
package model;
import java.io.Serializable;
public class ObjectWrapper implements Serializable{
private static final long serialVersionUID = 20210811011L;
public static final int LOGIN_USER = 1;
public static final int REPLY_LOGIN_USER = 2;
public static final int EDIT_CUSTOMER = 3;
public static final int REPLY_EDIT_CUSTOMER = 4;
public static final int SEARCH_CUSTOMER_BY_NAME = 5;
public static final int REPLY_SEARCH_CUSTOMER = 6;
public static final int SERVER_INFORM_CLIENT_NUMBER = 7;
private int performative;
private Object data;
public ObjectWrapper() {
super();
}
public ObjectWrapper(int performative, Object data) {
super();
this.performative = performative;
this.data = data;
}
public int getPerformative() {
return performative;
}
public void setPerformative(int performative) {
this.performative = performative;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
Class: IPAddress.java
package model;
import java.io.Serializable;
public class IPAddress implements Serializable{
private static final long serialVersionUID = 20210811012L;
private String host;
private int port;
public IPAddress() {
super();
}
public IPAddress(String host, int port) {
super();
this.host = host;
this.port = port;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
}
Class: ClientCtr.java
package tcp.client.control;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import jdbc.dao.UserDAO;
import model.IPAddress;
import model.ObjectWrapper;
import model.User;
import tcp.client.view.LoginFrm;
import tcp.client.view.SearchCustomerFrm;
import tcp.client.view.ClientMainFrm;
import tcp.client.view.EditCustomerFrm;
public class ClientCtr {
private Socket mySocket;
private ClientMainFrm view;
private ClientListening myListening; // thread to listen the data from the server
private ArrayList<ObjectWrapper> myFunction; // list of active client functions
private IPAddress serverAddress = new IPAddress("localhost",8888); // default server host and port
public ClientCtr(ClientMainFrm view){
super();
this.view = view;
myFunction = new ArrayList<ObjectWrapper>();
}
public ClientCtr(ClientMainFrm view, IPAddress serverAddr) {
super();
this.view = view;
this.serverAddress = serverAddr;
myFunction = new ArrayList<ObjectWrapper>();
}
public boolean openConnection(){
try {
mySocket = new Socket(serverAddress.getHost(), serverAddress.getPort());
myListening = new ClientListening();
myListening.start();
view.showMessage("Connected to the server at host: " + serverAddress.getHost() + ", port: " + serverAddress.getPort());
} catch (Exception e) {
//e.printStackTrace();
view.showMessage("Error when connecting to the server!");
return false;
}
return true;
}
public boolean sendData(Object obj){
try {
ObjectOutputStream oos = new ObjectOutputStream(mySocket.getOutputStream());
oos.writeObject(obj);
} catch (Exception e) {
//e.printStackTrace();
view.showMessage("Error when sending data to the server!");
return false;
}
return true;
}
/*
public Object receiveData(){
Object result = null;
try {
ObjectInputStream ois = new ObjectInputStream(mySocket.getInputStream());
result = ois.readObject();
} catch (Exception e) {
//e.printStackTrace();
view.showMessage("Error when receiving data from the server!");
return null;
}
return result;
}*/
public boolean closeConnection(){
try {
if(myListening != null)
myListening.stop();
if(mySocket !=null) {
mySocket.close();
view.showMessage("Disconnected from the server!");
}
myFunction.clear();
} catch (Exception e) {
//e.printStackTrace();
view.showMessage("Error when disconnecting from the server!");
return false;
}
return true;
}
public ArrayList<ObjectWrapper> getActiveFunction() {
return myFunction;
}
class ClientListening extends Thread{
public ClientListening() {
super();
}
public void run() {
try {
while(true) {
ObjectInputStream ois = new ObjectInputStream(mySocket.getInputStream());
Object obj = ois.readObject();
if(obj instanceof ObjectWrapper) {
ObjectWrapper data = (ObjectWrapper)obj;
if(data.getPerformative() == ObjectWrapper.SERVER_INFORM_CLIENT_NUMBER)
view.showMessage("Number of client connecting to the server: " + data.getData());
else {
for(ObjectWrapper fto: myFunction)
if(fto.getPerformative() == data.getPerformative()) {
switch(data.getPerformative()) {
case ObjectWrapper.REPLY_LOGIN_USER:
LoginFrm loginView = (LoginFrm)fto.getData();
loginView.receivedDataProcessing(data);
break;
case ObjectWrapper.REPLY_EDIT_CUSTOMER:
EditCustomerFrm ecv = (EditCustomerFrm)fto.getData();
ecv.receivedDataProcessing(data);
break;
case ObjectWrapper.REPLY_SEARCH_CUSTOMER:
SearchCustomerFrm scv = (SearchCustomerFrm)fto.getData();
scv.receivedDataProcessing(data);
break;
}
}
//view.showMessage("Received an object: " + data.getPerformative());
}
}
}
} catch (Exception e) {
e.printStackTrace();
view.showMessage("Error when receiving data from the server!");
view.resetClient();
}
}
}
}
Class: ClientMainFrm.java
package tcp.client.view;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Rectangle;
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.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import model.IPAddress;
import model.ObjectWrapper;
import tcp.client.control.ClientCtr;
public class ClientMainFrm extends JFrame implements ActionListener{
private JMenuBar mnbMain;
private JMenu mnUser;
private JMenu mnClient;
private JMenuItem mniLogin;
private JMenuItem mniEditClient;
private JTextField txtServerHost;
private JTextField txtServerPort;
private JButton btnConnect;
private JButton btnDisconnect;
private JTextArea mainText;
private ClientCtr myControl;
public ClientMainFrm(){
super("TCP client view");
JPanel mainPanel = new JPanel();
mainPanel.setLayout(null);
mnbMain = new JMenuBar();
mnUser = new JMenu("User");
mniLogin = new JMenuItem("Login");
mniLogin.addActionListener(this);
mnUser.add(mniLogin);
mnbMain.add(mnUser);
mnClient = new JMenu("Customer");
mniEditClient = new JMenuItem("Edit customer");
mniEditClient.addActionListener(this);
mnClient.add(mniEditClient);
mnbMain.add(mnClient);
this.setJMenuBar(mnbMain);
mniLogin.setEnabled(false);
mniEditClient.setEnabled(false);
JLabel lblTitle = new JLabel("Client TCP/IP");
lblTitle.setFont(new java.awt.Font("Dialog", 1, 20));
lblTitle.setBounds(new Rectangle(150, 20, 200, 30));
mainPanel.add(lblTitle, null);
JLabel lblHost = new JLabel("Server host:");
lblHost.setBounds(new Rectangle(10, 70, 150, 25));
mainPanel.add(lblHost, null);
txtServerHost = new JTextField(50);
txtServerHost.setBounds(new Rectangle(170, 70, 150, 25));
mainPanel.add(txtServerHost,null);
JLabel lblPort = new JLabel("Server port:");
lblPort.setBounds(new Rectangle(10, 100, 150, 25));
mainPanel.add(lblPort, null);
txtServerPort = new JTextField(50);
txtServerPort.setBounds(new Rectangle(170, 100, 150, 25));
mainPanel.add(txtServerPort,null);
btnConnect = new JButton("Connect");
btnConnect.setBounds(new Rectangle(10, 150, 150, 25));
btnConnect.addActionListener(this);
mainPanel.add(btnConnect,null);
btnDisconnect = new JButton("Disconnect");
btnDisconnect.setBounds(new Rectangle(170, 150, 150, 25));
btnDisconnect.addActionListener(this);
btnDisconnect.setEnabled(false);
mainPanel.add(btnDisconnect,null);
JScrollPane jScrollPane1 = new JScrollPane();
mainText = new JTextArea("");
jScrollPane1.setBounds(new Rectangle(10, 200, 610, 240));
mainPanel.add(jScrollPane1, BorderLayout.CENTER);
jScrollPane1.getViewport().add(mainText, null);
//mainPanel.add(mainText,null);
this.setContentPane(mainPanel);
this.pack();
this.setSize(new Dimension(640, 480));
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
this.addWindowListener( new WindowAdapter(){
public void windowClosing(WindowEvent e) {
if(myControl != null) {
myControl.closeConnection();
}
System.exit(0);
}
});
}
@Override
public void actionPerformed(ActionEvent ae) {
// TODO Auto-generated method stub
if(ae.getSource() instanceof JButton) {
JButton btn = (JButton)ae.getSource();
if(btn.equals(btnConnect)) {// connect button
if(!txtServerHost.getText().isEmpty() && (txtServerHost.getText().trim().length() > 0) &&
!txtServerPort.getText().isEmpty() && (txtServerPort.getText().trim().length() > 0)) {//custom port
int port = Integer.parseInt(txtServerPort.getText().trim());
myControl = new ClientCtr(this, new IPAddress(txtServerHost.getText().trim(), port));
// new ClientCtr(this, port);
}else {
myControl = new ClientCtr(this);
}
if(myControl.openConnection()) {
btnDisconnect.setEnabled(true);
btnConnect.setEnabled(false);
mniLogin.setEnabled(true);
mniEditClient.setEnabled(true);
}else {
resetClient();
}
}else if(btn.equals(btnDisconnect)) {// disconnect button
resetClient();
}
}else if(ae.getSource() instanceof JMenuItem) {
JMenuItem mni = (JMenuItem)ae.getSource();
if(mni.equals(mniLogin)) {// login function
}else if(mni.equals(mniEditClient)) {// Search client to edit
for(ObjectWrapper func: myControl.getActiveFunction())
if(func.getData() instanceof SearchCustomerFrm) {
((SearchCustomerFrm)func.getData()).setVisible(true);
return;
}
SearchCustomerFrm scv = new SearchCustomerFrm(myControl);
scv.setVisible(true);
}
}
}
public void showMessage(String s){
mainText.append("\n"+s);
mainText.setCaretPosition(mainText.getDocument().getLength());
}
public void resetClient() {
if(myControl != null) {
myControl.closeConnection();
myControl.getActiveFunction().clear();
myControl = null;
}
btnDisconnect.setEnabled(false);
btnConnect.setEnabled(true);
mniLogin.setEnabled(false);
mniEditClient.setEnabled(false);
}
public static void main(String[] args) {
ClientMainFrm view = new ClientMainFrm();
view.setVisible(true);
}
}
Class: SearchCustomerFrm.java
package tcp.client.view;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
import model.Customer;
import model.ObjectWrapper;
import tcp.client.control.ClientCtr;
public class SearchCustomerFrm extends JFrame implements ActionListener{
private ArrayList<Customer> listClient;
private JTextField txtKey;
private JButton btnSearch;
private JTable tblResult;
private ClientCtr mySocket;
public SearchCustomerFrm(ClientCtr socket){
super("Search customer to edit");
mySocket = socket;
listClient = new ArrayList<Customer>();
JPanel pnMain = new JPanel();
pnMain.setSize(this.getSize().width-5, this.getSize().height-20);
pnMain.setLayout(new BoxLayout(pnMain,BoxLayout.Y_AXIS));
pnMain.add(Box.createRigidArea(new Dimension(0,10)));
JLabel lblHome = new JLabel("Search a customer to edit");
lblHome.setAlignmentX(Component.CENTER_ALIGNMENT);
lblHome.setFont (lblHome.getFont ().deriveFont (20.0f));
pnMain.add(lblHome);
pnMain.add(Box.createRigidArea(new Dimension(0,20)));
JPanel pn1 = new JPanel();
pn1.setLayout(new BoxLayout(pn1,BoxLayout.X_AXIS));
pn1.setSize(this.getSize().width-5, 20);
pn1.add(new JLabel("Client name: "));
txtKey = new JTextField();
pn1.add(txtKey);
btnSearch = new JButton("Search");
btnSearch.addActionListener(this);
pn1.add(btnSearch);
pnMain.add(pn1);
pnMain.add(Box.createRigidArea(new Dimension(0,10)));
JPanel pn2 = new JPanel();
pn2.setLayout(new BoxLayout(pn2,BoxLayout.Y_AXIS));
tblResult = new JTable();
JScrollPane scrollPane= new JScrollPane(tblResult);
tblResult.setFillsViewportHeight(false);
scrollPane.setPreferredSize(new Dimension(scrollPane.getPreferredSize().width, 250));
tblResult.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
int column = tblResult.getColumnModel().getColumnIndexAtX(e.getX()); // get the coloum of the button
int row = e.getY() / tblResult.getRowHeight(); // get the row of the button
// *Checking the row or column is valid or not
if (row < tblResult.getRowCount() && row >= 0 && column < tblResult.getColumnCount() && column >= 0) {
//search and delete all existing previous view
ObjectWrapper existed = null;
for(ObjectWrapper func: mySocket.getActiveFunction())
if(func.getData() instanceof EditCustomerFrm) {
((EditCustomerFrm)func.getData()).dispose();
existed = func;
}
if(existed != null)
mySocket.getActiveFunction().remove(existed);
//create new instance
(new EditCustomerFrm(mySocket, listClient.get(row))).setVisible(true);
dispose();
}
}
});
pn2.add(scrollPane);
pnMain.add(pn2);
this.add(pnMain);
this.setSize(600,300);
this.setLocation(200,10);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
mySocket.getActiveFunction().add(new ObjectWrapper(ObjectWrapper.REPLY_SEARCH_CUSTOMER, this));
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
JButton btnClicked = (JButton)e.getSource();
if(btnClicked.equals(btnSearch)){
if((txtKey.getText() == null)||(txtKey.getText().length() == 0))
return;
//send data to the server
mySocket.sendData(new ObjectWrapper(ObjectWrapper.SEARCH_CUSTOMER_BY_NAME, txtKey.getText().trim()));
}
}
/**
* Treatment of search result received from the server
* @param data
*/
public void receivedDataProcessing(ObjectWrapper data) {
if(data.getData() instanceof ArrayList<?>) {
listClient = (ArrayList<Customer>)data.getData();
String[] columnNames = {"Id", "Name", "idCard", "Address", "Email", "Tel", "Note"};
String[][] value = new String[listClient.size()][columnNames.length];
for(int i=0; i<listClient.size(); i++){
value[i][0] = listClient.get(i).getId() +"";
value[i][1] = listClient.get(i).getName();
value[i][2] = listClient.get(i).getIdCard();
value[i][3] = listClient.get(i).getAddress();
value[i][4] = listClient.get(i).getEmail();
value[i][5] = listClient.get(i).getTel();
value[i][6] = listClient.get(i).getNote();
}
DefaultTableModel tableModel = new DefaultTableModel(value, columnNames) {
@Override
public boolean isCellEditable(int row, int column) {
//unable to edit cells
return false;
}
};
tblResult.setModel(tableModel);
}else {
tblResult.setModel(null);
}
}
}
Class: EditCustomerFrm.java
package tcp.client.view;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import model.Customer;
import model.ObjectWrapper;
import tcp.client.control.ClientCtr;
public class EditCustomerFrm extends JFrame implements ActionListener{
private Customer client;
private JTextField txtId, txtName, txtIdcard, txtAddress, txtEmail, txtTel, txtNote;
private JButton btnUpdate, btnReset;
private ClientCtr mySocket;
public EditCustomerFrm(ClientCtr socket, Customer client){
super("Edit a customer");
mySocket = socket;
this.client = client;
JPanel pnMain = new JPanel();
pnMain.setSize(this.getSize().width-5, this.getSize().height-20);
pnMain.setLayout(new BoxLayout(pnMain,BoxLayout.Y_AXIS));
pnMain.add(Box.createRigidArea(new Dimension(0,10)));
JLabel lblHome = new JLabel("Edit a customer information");
lblHome.setAlignmentX(Component.CENTER_ALIGNMENT);
lblHome.setFont (lblHome.getFont ().deriveFont (20.0f));
pnMain.add(lblHome);
pnMain.add(Box.createRigidArea(new Dimension(0,20)));
txtId = new JTextField(15);
txtId.setEditable(false);
txtName = new JTextField(15);
txtIdcard = new JTextField(15);
txtAddress = new JTextField(15);
txtEmail = new JTextField(15);
txtTel = new JTextField(15);
txtNote = new JTextField(15);
btnUpdate = new JButton("Update");
btnReset = new JButton("Reset");
JPanel content = new JPanel();
content.setLayout(new GridLayout(8,2));
content.add(new JLabel("Customer ID:")); content.add(txtId);
content.add(new JLabel("Name:")); content.add(txtName);
content.add(new JLabel("Idcard:")); content.add(txtIdcard);
content.add(new JLabel("Address:")); content.add(txtAddress);
content.add(new JLabel("Email:")); content.add(txtEmail);
content.add(new JLabel("Tel:")); content.add(txtTel);
content.add(new JLabel("Note:")); content.add(txtNote);
content.add(btnUpdate); content.add(btnReset);
pnMain.add(content);
btnUpdate.addActionListener(this);
btnReset.addActionListener(this);
initForm();
this.setContentPane(pnMain);
this.setSize(600,300);
this.setLocation(200,10);
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
mySocket.getActiveFunction().add(new ObjectWrapper(ObjectWrapper.REPLY_EDIT_CUSTOMER, this));
}
private void initForm(){
if(client != null){
txtId.setText(client.getId()+"");
txtName.setText(client.getName());
txtIdcard.setText(client.getIdCard());
txtAddress.setText(client.getAddress());
txtEmail.setText(client.getEmail());
txtTel.setText(client.getTel());
txtNote.setText(client.getNote());
}
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
JButton btnClicked = (JButton)e.getSource();
if(btnClicked.equals(btnReset)){
initForm();
return;
}
if(btnClicked.equals(btnUpdate)){
client.setName(txtName.getText());
client.setIdCard(txtIdcard.getText());
client.setAddress(txtAddress.getText());
client.setEmail(txtEmail.getText());
client.setTel(txtTel.getText());
client.setNote(txtNote.getText());
//send data to the server
mySocket.sendData(new ObjectWrapper(ObjectWrapper.EDIT_CUSTOMER, client));
}
}
/**
* Treatment of search result received from the server
* @param data
*/
public void receivedDataProcessing(ObjectWrapper data) {
if(data.getData().equals("ok")) {
JOptionPane.showMessageDialog(this, "Update succesfully!");
/*for(DataTO func: mySocket.getActiveFunction())
if(func.getData().equals(this))
mySocket.getActiveFunction().remove(func);*/
this.dispose();
}
else {
JOptionPane.showMessageDialog(this, "Error when updating!");
}
}
}
Class: DAO.java
package jdbc.dao;
import java.sql.Connection;
import java.sql.DriverManager;
public class DAO {
public static Connection con;
public DAO(){
if(con == null){
String dbUrl = "jdbc:mysql://localhost:3307/hotel?autoReconnect=true&useSSL=false";
String dbClass = "com.mysql.jdbc.Driver";
try {
Class.forName(dbClass);
con = DriverManager.getConnection (dbUrl, "root", "xxx");
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
Class: CustomerDAO.java
package jdbc.dao;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import model.Customer;
public class CustomerDAO extends DAO{
/**
* search all clients in the tblClient whose name contains the @key
* using PreparedStatement - recommended for professional coding
* @param key
* @return list of client whose name contains the @key
*/
public ArrayList<Customer> searchCustomer(String key){
ArrayList<Customer> result = new ArrayList<Customer>();
String sql = "SELECT * FROM tblclient WHERE name LIKE ?";
try{
PreparedStatement ps = con.prepareStatement(sql);
ps.setString(1, "%" + key + "%");
ResultSet rs = ps.executeQuery();
while(rs.next()){
Customer client = new Customer();
client.setId(rs.getInt("id"));
client.setName(rs.getString("name"));
client.setIdCard(rs.getString("idcard"));
client.setAddress(rs.getString("address"));
client.setTel(rs.getString("tel"));
client.setEmail(rs.getString("email"));
client.setNote(rs.getString("note"));
result.add(client);
}
}catch(Exception e){
e.printStackTrace();
}
return result;
}
/**
* update the @client
* @param client
*/
public boolean editCustomer(Customer client){
String sql = "UPDATE tblclient SET name=?, idcard =?, address=?, tel=?, email=?, note=? WHERE id=?";
try{
PreparedStatement ps = con.prepareStatement(sql);
ps.setString(1, client.getName());
ps.setString(2, client.getIdCard());
ps.setString(3, client.getAddress());
ps.setString(4, client.getTel());
ps.setString(5, client.getEmail());
ps.setString(6, client.getNote());
ps.setInt(7, client.getId());
ps.executeUpdate();
}catch(Exception e){
e.printStackTrace();
return false;
}
return true;
}
}
Class: ServerCtr.java
package tcp.server.control;
import java.io.EOFException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import jdbc.dao.CustomerDAO;
import jdbc.dao.UserDAO;
import model.Customer;
import model.IPAddress;
import model.ObjectWrapper;
import model.User;
import tcp.server.view.ServerMainFrm;
public class ServerCtr {
private ServerMainFrm view;
private ServerSocket myServer;
private ServerListening myListening;
private ArrayList<ServerProcessing> myProcess;
private IPAddress myAddress = new IPAddress("localhost",8888); //default server host and port
public ServerCtr(ServerMainFrm view){
myProcess = new ArrayList<ServerProcessing>();
this.view = view;
openServer();
}
public ServerCtr(ServerMainFrm view, int serverPort){
myProcess = new ArrayList<ServerProcessing>();
this.view = view;
myAddress.setPort(serverPort);
openServer();
}
private void openServer(){
try {
myServer = new ServerSocket(myAddress.getPort());
myListening = new ServerListening();
myListening.start();
myAddress.setHost(InetAddress.getLocalHost().getHostAddress());
view.showServerInfor(myAddress);
//System.out.println("server started!");
view.showMessage("TCP server is running at the port " + myAddress.getPort() +"...");
}catch(Exception e) {
e.printStackTrace();;
}
}
public void stopServer() {
try {
for(ServerProcessing sp:myProcess)
sp.stop();
myListening.stop();
myServer.close();
view.showMessage("TCP server is stopped!");
}catch(Exception e) {
e.printStackTrace();
}
}
public void publicClientNumber() {
ObjectWrapper data = new ObjectWrapper(ObjectWrapper.SERVER_INFORM_CLIENT_NUMBER, myProcess.size());
for(ServerProcessing sp : myProcess) {
sp.sendData(data);
}
}
/**
* The class to listen the connections from client, avoiding the blocking of accept connection
*
*/
class ServerListening extends Thread{
public ServerListening() {
super();
}
public void run() {
view.showMessage("server is listening... ");
try {
while(true) {
Socket clientSocket = myServer.accept();
ServerProcessing sp = new ServerProcessing(clientSocket);
sp.start();
myProcess.add(sp);
view.showMessage("Number of client connecting to the server: " + myProcess.size());
publicClientNumber();
}
}catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* The class to treat the requirement from client
*
*/
class ServerProcessing extends Thread{
private Socket mySocket;
//private ObjectInputStream ois;
//private ObjectOutputStream oos;
public ServerProcessing(Socket s) {
super();
mySocket = s;
}
public void sendData(Object obj) {
try {
ObjectOutputStream oos= new ObjectOutputStream(mySocket.getOutputStream());
oos.writeObject(obj);
}catch(Exception e) {
e.printStackTrace();
}
}
public void run() {
try {
while(true) {
ObjectInputStream ois = new ObjectInputStream(mySocket.getInputStream());
ObjectOutputStream oos= new ObjectOutputStream(mySocket.getOutputStream());
Object o = ois.readObject();
if(o instanceof ObjectWrapper){
ObjectWrapper data = (ObjectWrapper)o;
switch(data.getPerformative()) {
case ObjectWrapper.LOGIN_USER:
User user = (User)data.getData();
UserDAO ud = new UserDAO();
if(ud.checkLogin(user)){
oos.writeObject(new ObjectWrapper(ObjectWrapper.REPLY_LOGIN_USER,"ok"));
}
else
oos.writeObject(new ObjectWrapper(ObjectWrapper.REPLY_LOGIN_USER,"false"));
break;
case ObjectWrapper.EDIT_CUSTOMER:
Customer cl = (Customer)data.getData();
CustomerDAO cd = new CustomerDAO();
boolean ok = cd.editCustomer(cl);
if(ok){
oos.writeObject(new ObjectWrapper(ObjectWrapper.REPLY_EDIT_CUSTOMER,"ok"));
}
else
oos.writeObject(new ObjectWrapper(ObjectWrapper.REPLY_EDIT_CUSTOMER,"false"));
break;
case ObjectWrapper.SEARCH_CUSTOMER_BY_NAME:
String key = (String)data.getData();
cd = new CustomerDAO();
ArrayList<Customer> result = cd.searchCustomer(key);
oos.writeObject(new ObjectWrapper(ObjectWrapper.REPLY_SEARCH_CUSTOMER,result));
break;
}
}
//ois.reset();
//oos.reset();
}
}catch (EOFException | SocketException e) {
//e.printStackTrace();
myProcess.remove(this);
view.showMessage("Number of client connecting to the server: " + myProcess.size());
publicClientNumber();
try {
mySocket.close();
}catch(Exception ex) {
ex.printStackTrace();
}
this.stop();
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
Class: ServerMainFrm.java
package tcp.server.view;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import model.IPAddress;
import tcp.server.control.ServerCtr;
import tcp.server.control.SimpleServerCtr;
public class ServerMainFrm extends JFrame implements ActionListener{
private JTextField txtServerHost, txtServerPort;
private JButton btnStartServer, btnStopServer;
private JTextArea mainText;
private ServerCtr myServer;
//private SimpleServerCtr myServer;
public ServerMainFrm(){
super("TCP server view");
JPanel mainPanel = new JPanel();
mainPanel.setLayout(null);
JLabel lblTitle = new JLabel("Server TCP/IP");
lblTitle.setFont(new java.awt.Font("Dialog", 1, 20));
lblTitle.setBounds(new Rectangle(150, 15, 200, 30));
mainPanel.add(lblTitle, null);
JLabel lblHost = new JLabel("Server host:");
lblHost.setBounds(new Rectangle(10, 70, 150, 25));
mainPanel.add(lblHost, null);
txtServerHost = new JTextField(50);
txtServerHost.setBounds(new Rectangle(170, 70, 150, 25));
txtServerHost.setText("localhost");
txtServerHost.setEditable(false);
mainPanel.add(txtServerHost,null);
JLabel lblPort = new JLabel("Server port:");
lblPort.setBounds(new Rectangle(10, 100, 150, 25));
mainPanel.add(lblPort, null);
txtServerPort = new JTextField(50);
txtServerPort.setBounds(new Rectangle(170, 100, 150, 25));
mainPanel.add(txtServerPort,null);
btnStartServer = new JButton("Start server");
btnStartServer.setBounds(new Rectangle(10, 150, 150, 25));
btnStartServer.addActionListener(this);
mainPanel.add(btnStartServer,null);
btnStopServer = new JButton("Stop server");
btnStopServer.setBounds(new Rectangle(170, 150, 150, 25));
btnStopServer.addActionListener(this);
btnStopServer.setEnabled(false);
mainPanel.add(btnStopServer,null);
JScrollPane jScrollPane1 = new JScrollPane();
mainText = new JTextArea("");
jScrollPane1.setBounds(new Rectangle(10, 200, 610, 240));
mainPanel.add(jScrollPane1, BorderLayout.CENTER);
jScrollPane1.getViewport().add(mainText, null);
//mainPanel.add(mainText,null);
this.setContentPane(mainPanel);
this.pack();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(new Dimension(640, 480));
this.setResizable(false);
}
public void showServerInfor(IPAddress addr) {
txtServerHost.setText(addr.getHost());
txtServerPort.setText(addr.getPort()+"");
}
@Override
public void actionPerformed(ActionEvent ae) {
// TODO Auto-generated method stub
if(ae.getSource() instanceof JButton) {
JButton clicked = (JButton)ae.getSource();
if(clicked.equals(btnStartServer)) {// start button
if(!txtServerPort.getText().isEmpty() && (txtServerPort.getText().trim().length() > 0)) {//custom port
int port = Integer.parseInt(txtServerPort.getText().trim());
myServer = //new SimpleServerCtr(this, port);
new ServerCtr(this, port);
}else {// default port
myServer = //new SimpleServerCtr(this);
new ServerCtr(this);
}
btnStopServer.setEnabled(true);
btnStartServer.setEnabled(false);
}else if(clicked.equals(btnStopServer)) {// stop button
if(myServer != null) {
myServer.stopServer();
myServer = null;
}
btnStopServer.setEnabled(false);
btnStartServer.setEnabled(true);
txtServerHost.setText("localhost");
}
}
}
public void showMessage(String s){
mainText.append("\n"+s);
mainText.setCaretPosition(mainText.getDocument().getLength());
}
public static void main(String[] args) {
ServerMainFrm view = new ServerMainFrm();
view.setVisible(true);
}
}