Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 74

BỘ GIÁO DỤC VÀ ĐÀO TẠO

TRƯỜNG ĐẠI HỌC MỎ - ĐỊA CHẤT HÀ NỘI

KHOA CÔNG NGHỆ THÔNG TIN

Đồ án lập trình mạng


Xây dựng ứng dụng Chat Client – Server

Giảng Viên Hướng Dẫn: Phan Mạnh Tiến


Nhóm: Đỗ Viết Thanh 1121050299
Nguyễn Thị Thanh Huệ 1121050218
Nguyễn Thanh Hương 1121050228
Nguyễn Thế Phong 1121050073
Phạm Văn Thực 1121050103
Lớp: Mạng Máy Tính K56

Hà Nội, Ngày 18 Tháng 5 Năm 2014


Đồ án: ứng dụng chát Client – Server 2|Page

Mục Lục
I. Tổng quan về đề tài ..................................................................................................... 3
1. Cơ sở lý thuyết ....................................................................................................... 3
2. Phân tích và thiết kế hệ thống ................................................................................ 3
2.1 Phân tích yêu cầu bài toán .................................................................................. 3
2.2 Thiết kế chương trình ......................................................................................... 3
II. Hướng dẫn cài đặt và chạy Demo chương trình .......................................................... 7
1. Hướng dẫn cài đặt .................................................................................................. 7
2. Chạy Demo Chương trình ...................................................................................... 7
III. Kết Luận và hướng phát triển .................................................................................. 13
1. Những kết quả đạt được ....................................................................................... 13
2. Những vấn đề tồn tại ............................................................................................ 13
3. Hướng phát triển .................................................................................................. 13
IV. Source code ............................................................................................................. 14
1. Chương trình bên Server ...................................................................................... 14
1.1 Database class ................................................................................................... 14
1.2 Message class ................................................................................................... 19
1.3 ServerFrame class ............................................................................................. 19
1.4 SocketServer class ............................................................................................ 23
2. Chương trình bên Client....................................................................................... 35
2.1 Download class ................................................................................................. 35
2.2 History class ..................................................................................................... 37
2.3 Message class ................................................................................................... 40
2.4 SocketClient class ............................................................................................. 40
2.5 Upload class ...................................................................................................... 48
2.6 ChatFrame class ................................................................................................ 50
2.7 HistoryFrame class ........................................................................................... 69
Tài Liệu tham khảo ............................................................................................................ 74

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 3|Page

I. Tổng quan về đề tài


1. Cơ sở lý thuyết
 Giao thức TCP/IP
 Mô hình Client/Server
 Cơ chế Socket trong Java
2. Phân tích và thiết kế hệ thống
2.1 Phân tích yêu cầu bài toán
Yêu cầu bài toán: Xây dựng chương trình Chát theo mô hình Client – Server sử
dụng Java Socket
Phân tích:
 Xây dựng chương trình bên Server
 Tạo một TCP Socket và gắn vào một cổng
 Kết nối Database để lưu trữ dữ liệu người dùng như: username, password
 Xây dựng một chương trình Server đa tuyến (Thread Server) để cho phép
nhiều Client kết nối đến Server
 Luôn luôn chờ và lắng nghe yêu cầu kết nối từ Client
 Chấp nhận kết nối và tạo ra các Thread (Socket) tương ứng
 Truyền nhận thông tin qua các luồng nhận/gửi dữ liệu của socket
 Cập nhật trạng thái đăng nhập, đăng xuất của các Client và gửi về các
Client
 Thiết kế giao diện Server
 Xử lý 1 số công việc khác …
 Xây dựng chương trình bên Client
 Tạo một TCP Socket với địa chỉ IP và số cổng mà chương trình Server
đang chạy
 Thiết lập kết nối và trao đổi với Server: đăng nhập, đăng xuất …;
 Gửi, Nhận thông điệp với tất cả mọi người trong phòng chát
 Chức năng xem lại lịch sử đã chát
 Chức năng upload, Download File
 Thiết kế giao diện Client
2.2 Thiết kế chương trình
2.2.1 Thiết kế giao diện
Giao diện của Server
Giao diện của Server hết sức đơn giản. Thiết kế cơ bản gồm nút Start. Phần Port,
select Database đã được mặc định chọn sẵn trong code.

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 4|Page

Server cập nhật trạng thái của các Client và in thông tin ngay tại trên Server và đồng
thời gửi xuống cho các Client

Hình 2.1: Server đang hoạt động


Giao diện bên Client
Giao diện bên Client được tách ra làm 2 form: ChatFram (phần chát chính) và
HistoryFram (nhật ký chát).

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 5|Page

Hình 2.2 Client đã kết nối đến Server


 ChatFram là giao diện tổng hợp của việc kết nối, đăng nhập và Chát.
 Host Address và Port của Server mặc định
 Phần List Online: để hiển thị các nick đang online
 Khung chát chính: tất cả thông báo đến từ Server, chương trình và các tin nhắn
từ thành viên khác đều được hiển thị ở đây
 Gửi tin nhắn: Có thể chát Room qua List Online chọn thuộc tính All. Và chát
riêng khi chọn thành viên muốn chát
 Nhật ký: hiển thị lịch sử đã chát qua 1 form mới là HistoryFram
 Upload File: cho phép gửi tập tin cho người dùng #. Cấm gửi lên cho tất cả
mọi người (tránh tắc nghẽn)

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 6|Page

Hình 2.3 Nhật ký chát


2.2.2 Các lớp xử lý của chương trình
Phía bên Server

Phía bên Client

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 7|Page

II. Hướng dẫn cài đặt và chạy Demo chương trình


1. Hướng dẫn cài đặt
Chương trình gồm 2 phần chính là : Client và Server. Muốn chương trình chạy được
thì ta phải chạy Server trước để lắng nghe các Client. Sau đó chạy các Client
Chạy Server ta Run File ServerFrame là Main
Chạy Client ta Run File ChatFramme là Main
2. Chạy Demo Chương trình
Thử nghiệm chạy chương trình lần lượt theo các bước  kết quả được hiển thị
qua các hình

Hình 2.1 Kết nối lỗi khi Server chưa chạy

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 8|Page

Hình 2.2 Chạy chương trình Server

Hính 2.3 Chạy Client Kết nối và đăng nhập thành công
 Sau khi Server đã được bật thì đã kết nối được thành công
 Tiến hành kết nối và đăng nhập thêm nhiều Client khác

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 9|Page

Hình 2.4 Chát Room và chat Private


 Chát Room thì tại List Online ta chọn All và tiến hành chát với mọi người
 Chát Private thì tại List Online ta chọn người muốn chát và tiến hành chát. Như
trong hình thì Đỗ Thanh chát private đến Thanh Huệ. Và Thanh Huệ, Văn
Thực chát Private cho Đỗ Thanh.

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 10 | P a g e

Hình 2.5 Hiển thị nhật ký chát của Thế Phong

Hình 2.6 Thông báo đến các Client khi có Nick đăng xuất

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 11 | P a g e

Hình 2.7 Thông báo trên Server khi có Client thoát, tiến hành giải phóng tài nguyên
và tiếp tục chờ đợi các Client

Hình 2.8 Server gửi thông báo cho Thế Phong không cho phép gửi tập tin cho tất cả
mọi người

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 12 | P a g e

 Tiếp theo sẽ sử dụng kịch bản: Thế Phong gửi File cho Đỗ Thanh. TH1 Đỗ Thanh
từ chối Download, TH2 Đỗ Thanh Download

Hình 2.9 Thông báo khi Thế Phong gửi cho Đỗ Thanh tệp tin.

Hình 2.10 Thông báo Đỗ Thanh không chấp nhận tập tin

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 13 | P a g e

Hình 2.11 Đỗ Thanh chấp nhận Download và thông báo đến 2 người đó

III. Kết Luận và hướng phát triển


1. Những kết quả đạt được
 Mô phỏng thành công mô hình Client – Server trong mạng LAN
 Thực hiện đầy đủ yêu cầu bài ra: Đăng nhập, đăng xuất, List OnLine, Chat
Room, Chat Private.
 Một số chức năng thực hiện thêm: Select Database dạng XML, Nhật ký Chat,
UpLoad File và Download File.
2. Những vấn đề tồn tại
 Chương trình còn đơn giản
 Giao diện sơ sài
3. Hướng phát triển
 Hoàn thiện giao diện đẹp phù hợp với người dùng
 Phát triển trên mạng rộng ngoài mạng LAN

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 14 | P a g e

IV. Source code


1. Chương trình bên Server

1.1 Database class


package com.socket;

import java.io.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.*;

public class Database {

public String filePath="";

public Database(String filePath) {


this.filePath = filePath;

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 15 | P a g e

public boolean userExists(String username) {

try {
File fXmlFile = new File(filePath);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
// Bình thường hóa văn bản
doc.getDocumentElement().normalize();

NodeList nList = doc.getElementsByTagName("user");


//Duyệt
for (int i = 0; i < nList.getLength(); i++)
{
Node nNode = nList.item(i);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
if (getTagValue("username", eElement).equals(username)) {
return true;
}
}
}
return false;
} catch (Exception ex) {

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 16 | P a g e

return false;
}
}

public boolean checkLogin(String username, String password) {

if (!userExists(username))
{
return false;
}

try {
File fXmlFile = new File(filePath);
DocumentBuilderFactory db = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = db.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();

NodeList nList = doc.getElementsByTagName("user");

for (int i = 0; i < nList.getLength(); i++)


{
//NodeList ageList = firstPersonElement.getElementsByTagName("age");
//Element ageElement = (Element)ageList.item(0);
//NodeList textAgeList = ageElement.getChildNodes();
//System.out.println("Age : " +
((Node)textAgeList.item(0)).getNodeValue().trim());

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 17 | P a g e

Node nNode = nList.item(i);


if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
if (getTagValue("username", eElement).equals(username) &&
getTagValue("password", eElement).equals(password))
{
return true;
}
}
}
System.out.println("Hippie");
return false;
} catch (Exception ex) {
return false;
}
}

public void addUser(String username, String password) {

try {
DocumentBuilderFactory db = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = db.newDocumentBuilder();
Document doc = dBuilder.parse(filePath);
// Tạo 1 node
Node data = doc.getFirstChild();
// Thêm 1 user

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 18 | P a g e

Element newuser = doc.createElement("user");


Element newusername = doc.createElement("username");
newusername.setTextContent(username);
Element newpassword = doc.createElement("password");
newpassword.setTextContent(password);
// Xác nhận
newuser.appendChild(newusername);
newuser.appendChild(newpassword);
data.appendChild(newuser);
//Tạo vào file xml
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(filePath));
transformer.transform(source, result);

} catch (Exception ex) {


}
}

public static String getTagValue(String sTag, Element eElement) {


NodeList nlList =
eElement.getElementsByTagName(sTag).item(0).getChildNodes();
Node nValue = (Node) nlList.item(0);
return nValue.getNodeValue();
}
}

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 19 | P a g e

1.2 Message class


package com.socket;

import java.io.Serializable;

public class Message implements Serializable{

private static final long serialVersionUID = 1L;


//Loại , người gửi, nội dung, người nhận
public String type, sender, content, recipient;

public Message(String type, String sender, String content, String recipient){


this.type = type; this.sender = sender; this.content = content; this.recipient =
recipient;
}

@Override
public String toString(){
return "{type='"+type+"', sender='"+sender+"', content='"+content+"',
recipient='"+recipient+"'}";
}
}
1.3 ServerFrame class
package com.socket;

import javax.swing.UIManager;

public class ServerFrame extends javax.swing.JFrame {

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 20 | P a g e

public SocketServer server;


public Thread serverThread;
public String filePath = "src\\com\\data\\Data.xml";

public ServerFrame() {
initComponents();
this.setTitle("Server Chat");
txtThongBao.setEditable(false);
}

@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {

btnStart = new javax.swing.JButton();


jScrollPane1 = new javax.swing.JScrollPane();
txtThongBao = new javax.swing.JTextArea();

setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("jServer");

btnStart.setText("Start Server");
btnStart.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnStartActionPerformed(evt);

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 21 | P a g e

}
});

txtThongBao.setColumns(20);
txtThongBao.setFont(new java.awt.Font("Consolas", 0, 12)); // NOI18N
txtThongBao.setRows(5);
jScrollPane1.setViewportView(txtThongBao);

javax.swing.GroupLayout layout = new


javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE,
561, Short.MAX_VALUE)
.addContainerGap())
.addGroup(layout.createSequentialGroup()
.addGap(239, 239, 239)
.addComponent(btnStart)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE,
Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 22 | P a g e

.addGap(16, 16, 16)


.addComponent(btnStart)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE,
287, Short.MAX_VALUE)
.addContainerGap())
);

pack();
}// </editor-fold>

private void btnStartActionPerformed(java.awt.event.ActionEvent evt) {


server = new SocketServer(this);
btnStart.setEnabled(false);
}

public void RetryStart(int port){


if(server != null){ server.stop(); }
server = new SocketServer(this, port);
}

public static void main(String args[]) {

try{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(Exception ex){

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 23 | P a g e

java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new ServerFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton btnStart;
private javax.swing.JScrollPane jScrollPane1;
public javax.swing.JTextArea txtThongBao;
// End of variables declaration
}
1.4 SocketServer class
package com.socket;

import java.io.*;
import java.net.*;

class ServerThread extends Thread {

public SocketServer server = null;


public Socket socket = null;
public int ID = -1;
public String username = "";

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 24 | P a g e

public ObjectInputStream In = null;


public ObjectOutputStream Out = null;
public ServerFrame ui;

public ServerThread(SocketServer _server, Socket _socket) {


super();
server = _server;
socket = _socket;
ID = socket.getPort();
ui = _server.ui;
}

public void send(Message msg) {


try {
Out.writeObject(msg);
Out.flush();
} catch (IOException ex) {
}
}

public int getID() {


return ID;
}

@SuppressWarnings("deprecation")
@Override

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 25 | P a g e

public void run() {


ui.txtThongBao.append("\nServer Thread " + ID + " đang chạy...");
while (true) {
try {
Message msg = (Message) In.readObject();
server.handle(ID, msg);
} catch (IOException ioe) {
System.out.println(ID + " Lỗi: " + ioe.getMessage());
server.remove(ID);
} catch (ClassNotFoundException ioe) {
System.out.println(ID + " Lỗi: " + ioe.getMessage());
server.remove(ID);
}
}
}

// Mỗi Thread khởi động ==> không phải viết lại pt Stream
public void open() throws IOException {
Out = new ObjectOutputStream(socket.getOutputStream());
Out.flush();
In = new ObjectInputStream(socket.getInputStream());
}

public void close() throws IOException {


if (socket != null) {
socket.close();

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 26 | P a g e

}
if (In != null) {
In.close();
}
if (Out != null) {
Out.close();
}
}
}

public final class SocketServer implements Runnable {

public ServerThread clients[];


public ServerSocket server = null;
public Thread thread = null;
public int clientCount = 0, port = 9999;
public ServerFrame ui;
public Database db;

public SocketServer(ServerFrame frame) {

clients = new ServerThread[50];


ui = frame;
db = new Database(ui.filePath);

try {

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 27 | P a g e

server = new ServerSocket(port);


port = server.getLocalPort();
ui.txtThongBao.append("Server bắt đầu hoạt động... IP : " +
InetAddress.getLocalHost() + ", Port : " + server.getLocalPort());
start();
} catch (IOException ioe) {
ui.txtThongBao.append("Không thể mở cổng : " + port);
ui.RetryStart(0);
}
}

// Viết lại pt thêm tham số Port


public SocketServer(ServerFrame frame, int Port) {

clients = new ServerThread[50];


ui = frame;
port = Port;
db = new Database(ui.filePath);

try {
server = new ServerSocket(port);
port = server.getLocalPort();
ui.txtThongBao.append("Server bắt đầu hoạt động... IP : " +
InetAddress.getLocalHost() + ", Port : " + server.getLocalPort());
start();
} catch (IOException ioe) {

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 28 | P a g e

ui.txtThongBao.append("\nKhông thể kết nối cổng " + port + ": " +


ioe.getMessage());
}
}
// Luôn luôn lắng nghe Client
@Override
public void run() {
while (true) {
try {
ui.txtThongBao.append("\nChờ Client ...");
addThread(server.accept());
} catch (IOException ioe) {
ui.txtThongBao.append("\nServer lỗi: \n");
ui.RetryStart(0);
}
}
}

public void start() {


if (thread == null) {
thread = new Thread(this);
thread.start();
}
}

@SuppressWarnings("deprecation")
public void stop() {

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 29 | P a g e

if (thread != null) {
thread = null;
}
}

private int findClient(int ID) {


for (int i = 0; i < clientCount; i++) {
if (clients[i].getID() == ID) {
return i;
}
}
return -1;
}

public synchronized void handle(int ID, Message msg) {


// Thông báo đến các Client có máy out
if (msg.content.equals(".bye"))
{
ThongBao("signout", "SERVER", msg.sender);
remove(ID);
} else
{
if (msg.type.equals("login")) {
if (findUserThread(msg.sender) == null)
{
// kiểm tra

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 30 | P a g e

if (db.checkLogin(msg.sender, msg.content))
{
clients[findClient(ID)].username = msg.sender;
clients[findClient(ID)].send(new Message("login", "SERVER", "TRUE",
msg.sender));
ThongBao("newuser", "SERVER", msg.sender);
SendUserList(msg.sender);
} else
{
clients[findClient(ID)].send(new Message("login", "SERVER", "FALSE",
msg.sender));
}
} else
{
clients[findClient(ID)].send(new Message("login", "SERVER", "FALSE",
msg.sender));
}
} else if (msg.type.equals("message"))
{
if (msg.recipient.equals("All")) {
ThongBao("message", msg.sender, msg.content);
} else {
findUserThread(msg.recipient).send(new Message(msg.type, msg.sender,
msg.content, msg.recipient));
clients[findClient(ID)].send(new Message(msg.type, msg.sender,
msg.content, msg.recipient));
}
} else if (msg.type.equals("test"))

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 31 | P a g e

{
clients[findClient(ID)].send(new Message("test", "SERVER", "OK",
msg.sender));
} else if (msg.type.equals("signup"))
{
if (findUserThread(msg.sender) == null)
{
if (!db.userExists(msg.sender)) {
db.addUser(msg.sender, msg.content);
clients[findClient(ID)].username = msg.sender;
clients[findClient(ID)].send(new Message("signup", "SERVER",
"TRUE", msg.sender));
clients[findClient(ID)].send(new Message("login", "SERVER", "TRUE",
msg.sender));
ThongBao("newuser", "SERVER", msg.sender);
SendUserList(msg.sender);
} else {
clients[findClient(ID)].send(new Message("signup", "SERVER",
"FALSE", msg.sender));
}
} else
{
clients[findClient(ID)].send(new Message("signup", "SERVER", "FALSE",
msg.sender));
}
} else if (msg.type.equals("upload_req")) {
if (msg.recipient.equals("All")) {

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 32 | P a g e

clients[findClient(ID)].send(new Message("message", "SERVER", "Không


cho phép tải lên cho tất cả mọi người!", msg.sender));
} else
{
findUserThread(msg.recipient).send(new Message("upload_req",
msg.sender, msg.content, msg.recipient));
}
} else if (msg.type.equals("upload_res"))
{
if (!msg.content.equals("NO"))
{
String IP =
findUserThread(msg.sender).socket.getInetAddress().getHostAddress();
findUserThread(msg.recipient).send(new Message("upload_res", IP,
msg.content, msg.recipient));
} else
{
findUserThread(msg.recipient).send(new Message("upload_res",
msg.sender, msg.content, msg.recipient));
}
}
}
}

public void ThongBao(String type, String sender, String content) {


Message msg = new Message(type, sender, content, "All");
for (int i = 0; i < clientCount; i++) {
clients[i].send(msg);

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 33 | P a g e

}
}

public void SendUserList(String toWhom) {


for (int i = 0; i < clientCount; i++) {
findUserThread(toWhom).send(new Message("newuser", "SERVER",
clients[i].username, toWhom));
}
}

public ServerThread findUserThread(String usr) {


for (int i = 0; i < clientCount; i++)
{
if (clients[i].username.equals(usr)) {
return clients[i];
}
}
return null;
}

@SuppressWarnings("deprecation")
public synchronized void remove(int ID) {
int pos = findClient(ID);
if (pos >= 0) {
ServerThread toTerminate = clients[pos];
ui.txtThongBao.append("\nXóa bỏ Client: " + ID + " at " + pos);
if (pos < clientCount - 1) {

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 34 | P a g e

for (int i = pos + 1; i < clientCount; i++) {


clients[i - 1] = clients[i];
}
}
clientCount--;
try {
toTerminate.close();
} catch (IOException ioe) {
ui.txtThongBao.append("\nLỗi: " + ioe);
}
toTerminate.stop();
}
}

private void addThread(Socket socket) {


if (clientCount < clients.length) {
ui.txtThongBao.append("\nThêm Client: " + socket);
clients[clientCount] = new ServerThread(this, socket);
try {
clients[clientCount].open();
clients[clientCount].start();
clientCount++;
} catch (IOException ioe) {
ui.txtThongBao.append("\nLỗi: " + ioe);
}
} else {

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 35 | P a g e

ui.txtThongBao.append("\nĐã vượt quá số Client cho phép đăng nhập: " +


clients.length);
}
}
}
2. Chương trình bên Client
2.1 Download class
package com.socket;

import com.ui.ChatFrame;
import java.io.*;
import java.net.*;

public class Download implements Runnable{

public ServerSocket server;


public Socket socket;
public int port;
public String saveTo = "";
public InputStream In;
public FileOutputStream Out;
public ChatFrame ui;

public Download(String saveTo, ChatFrame ui){


try {
server = new ServerSocket(0);
port = server.getLocalPort();

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 36 | P a g e

this.saveTo = saveTo;
this.ui = ui;
}
catch (IOException ex) {
}
}

@Override
public void run() {
try {
socket = server.accept();
System.out.println("Download : "+socket.getRemoteSocketAddress());

In = socket.getInputStream();
Out = new FileOutputStream(saveTo);

byte[] buffer = new byte[1024];


int count;

while((count = In.read(buffer)) >= 0){


Out.write(buffer, 0, count);
}

Out.flush();

ui.txtAreaChat.append("[Thông Báo] : Download thành công!\n");

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 37 | P a g e

if(Out != null){ Out.close(); }


if(In != null){ In.close(); }
if(socket != null){ socket.close(); }
}
catch (Exception ex) {
}
}
}
2.2 History class
package com.socket;

import java.io.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.*;
import com.ui.HistoryFrame;
import javax.swing.table.DefaultTableModel;

public class History {

public String filePath;

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 38 | P a g e

public History(String filePath){


this.filePath = filePath;
}

public void addMessage(Message msg, String time){

try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(filePath);

Node data = doc.getFirstChild();

Element message = doc.createElement("message");


Element _sender = doc.createElement("sender");
_sender.setTextContent(msg.sender);
Element _content = doc.createElement("content");
_content.setTextContent(msg.content);
Element _recipient = doc.createElement("recipient");
_recipient.setTextContent(msg.recipient);
Element _time = doc.createElement("time"); _time.setTextContent(time);

message.appendChild(_sender); message.appendChild(_content);
message.appendChild(_recipient); message.appendChild(_time);
data.appendChild(message);

TransformerFactory transformerFactory = TransformerFactory.newInstance();


Transformer transformer = transformerFactory.newTransformer();

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 39 | P a g e

DOMSource source = new DOMSource(doc);


StreamResult result = new StreamResult(new File(filePath));
transformer.transform(source, result);

}
catch(Exception ex){
System.out.println("Exceptionmodify xml");
}
}

public void FillTable(HistoryFrame frame){

DefaultTableModel model = (DefaultTableModel) frame.jTable1.getModel();

try{
File fXmlFile = new File(filePath);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();

NodeList nList = doc.getElementsByTagName("message");

for (int temp = 0; temp < nList.getLength(); temp++) {


Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 40 | P a g e

Element eElement = (Element) nNode;


model.addRow(new Object[]{getTagValue("sender", eElement),
getTagValue("content", eElement), getTagValue("recipient", eElement),
getTagValue("time", eElement)});
}
}
}
catch(Exception ex){
System.out.println("Filling Exception");
}
}

public static String getTagValue(String sTag, Element eElement) {


NodeList nlList =
eElement.getElementsByTagName(sTag).item(0).getChildNodes();
Node nValue = (Node) nlList.item(0);
return nValue.getNodeValue();
}
}
2.3 Message class
Giống với bên Server.Đây là class làm nhiện vụ để Client và Server gửi các Object
cho nhau nên được Serializable và ở cả Client và Server là như nhau
2.4 SocketClient class
package com.socket;

import com.ui.ChatFrame;
import java.io.*;
import java.net.*;

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 41 | P a g e

import java.util.Date;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.table.DefaultTableModel;

public class SocketClient implements Runnable {

public int port;


public String serverAddr;
public Socket socket;
public ChatFrame ui;
public ObjectInputStream In;
public ObjectOutputStream Out;
public History hist;

public SocketClient(ChatFrame frame) throws IOException {


ui = frame;
this.serverAddr = ui.serverAddr;
this.port = ui.port;
socket = new Socket(InetAddress.getByName(serverAddr), port);

Out = new ObjectOutputStream(socket.getOutputStream());


Out.flush();
In = new ObjectInputStream(socket.getInputStream());

hist = ui.hist;

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 42 | P a g e

@Override
public void run() {
while (true) {
try {
Message msg = (Message) In.readObject();
System.out.println("Nhận vào : " + msg.toString());
//Gửi tin nhắn dưới loại message
if (msg.type.equals("message")) {
if (msg.recipient.equals(ui.username)) {
ui.txtAreaChat.append("[" + msg.sender + " > Me] : " + msg.content +
"\n");
} else {
ui.txtAreaChat.append("[" + msg.sender + " > " + msg.recipient + "] : " +
msg.content + "\n");
}
// Lưu vào lịch sử
if (!msg.content.equals(".bye") && !msg.sender.equals(ui.username)) {
String msgTime = (new Date()).toString();

try {
hist.addMessage(msg, msgTime);
DefaultTableModel table = (DefaultTableModel)
ui.historyFrame.jTable1.getModel();
table.addRow(new Object[]{msg.sender, msg.content, "Me",
msgTime});
} catch (Exception ex) {

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 43 | P a g e

}
}
// Đăng nhập tk với loại login
} else if (msg.type.equals("login")) {
if (msg.content.equals("TRUE")) {
ui.btnNhatKy.setEnabled(true);
ui.btnDangNhap.setEnabled(false);
ui.btnDangKy.setEnabled(false);
ui.btnChat.setEnabled(true);
ui.btnFile.setEnabled(true);
ui.txtAreaChat.append("[Thông Báo] : Đăng nhập thành công!\n");
ui.txtname.setEnabled(false);
ui.txtPass.setEnabled(false);
} else {
ui.txtAreaChat.append("[Thông Báo] : Lỗi đăng nhập.\n");
}
// Kết nối vào server loại test
} else if (msg.type.equals("test")) {
ui.btnKetNoi.setEnabled(false);
ui.btnDangNhap.setEnabled(true);
ui.btnDangKy.setEnabled(true);
ui.txtname.setEnabled(true);
ui.txtPass.setEnabled(true);
ui.txtAddress.setEditable(false);
ui.txtPort.setEditable(false);
} else if (msg.type.equals("newuser")) {

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 44 | P a g e

if (!msg.content.equals(ui.username)) {
boolean exists = false;
for (int i = 0; i < ui.model.getSize(); i++) {
if (ui.model.getElementAt(i).equals(msg.content)) {
exists = true;
break;
}
}
if (!exists) {
ui.model.addElement(msg.content);
}
}
} else if (msg.type.equals("signup")) {
if (msg.content.equals("TRUE")) {
ui.btnNhatKy.setEnabled(true);
ui.btnDangNhap.setEnabled(false);
ui.btnDangKy.setEnabled(false);
ui.btnChat.setEnabled(true);
ui.btnFile.setEnabled(true);
ui.txtAreaChat.append("[Thông Báo] : Đăng ký thành công!\n");
} else {
ui.txtAreaChat.append("[Thông Báo] : Lỗi đăng ký.\n");
}
} else if (msg.type.equals("signout")) {
if (msg.content.equals(ui.username)) {
ui.txtAreaChat.append("[" + msg.sender + " > Me] : Tạm biệt\n");

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 45 | P a g e

ui.btnKetNoi.setEnabled(true);
ui.btnChat.setEnabled(false);
ui.txtAddress.setEditable(true);
ui.txtPort.setEditable(true);

for (int i = 1; i < ui.model.size(); i++) {


ui.model.removeElementAt(i);
}

ui.clientThread.stop();
} else {
ui.model.removeElement(msg.content);
ui.txtAreaChat.append("[Thông Báo] : thành viên " + msg.content + " đã
đăng xuất\n");
}
} else if (msg.type.equals("upload_req")) {

if (JOptionPane.showConfirmDialog(ui,"Bạn có đồng ý nhận tập tin '" +


msg.content + "' từ " + msg.sender + " ?","Thông
Báo",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE)==JOptio
nPane.YES_OPTION)
{
JFileChooser jf = new JFileChooser();
jf.setSelectedFile(new File(msg.content));
int returnVal = jf.showSaveDialog(ui);

String saveTo = jf.getSelectedFile().getPath();


if (saveTo != null && returnVal == JFileChooser.APPROVE_OPTION) {

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 46 | P a g e

Download dwn = new Download(saveTo, ui);


Thread t = new Thread(dwn);
t.start();
//send(new Message("upload_res",
(""+InetAddress.getLocalHost().getHostAddress()), (""+dwn.port), msg.sender));
send(new Message("upload_res", ui.username, ("" + dwn.port),
msg.sender));
} else {
send(new Message("upload_res", ui.username, "NO", msg.sender));
}
} else {
send(new Message("upload_res", ui.username, "NO", msg.sender));
}
} else if (msg.type.equals("upload_res")) {
if (!msg.content.equals("NO")) {
int port = Integer.parseInt(msg.content);
String addr = msg.sender;

ui.btnFile.setEnabled(false);
ui.btnGuiFile.setEnabled(false);
Upload upl = new Upload(addr, port, ui.file, ui);
Thread t = new Thread(upl);
t.start();
} else {
ui.txtAreaChat.append("[Thông Báo] : " + msg.sender + " đã từ chối
Download\n");
}

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 47 | P a g e

} else {
ui.txtAreaChat.append("[Thông Báo] : Lỗi \n");
}
} catch (Exception ex) {
ui.txtAreaChat.append("[Thông Báo] : Không có kết nối\n");
ui.btnKetNoi.setEnabled(true);
ui.txtAddress.setEditable(true);
ui.txtPort.setEditable(true);
ui.btnChat.setEnabled(false);
ui.btnFile.setEnabled(false);
ui.btnFile.setEnabled(false);

for (int i = 1; i < ui.model.size(); i++) {


ui.model.removeElementAt(i);
}

ui.clientThread.stop();
ex.printStackTrace();
}
}
}

public void send(Message msg) {


try {
Out.writeObject(msg);
Out.flush();

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 48 | P a g e

System.out.println("Gửi đi : " + msg.toString());

if (msg.type.equals("message") && !msg.content.equals(".bye")) {


String msgTime = (new Date()).toString();
try {
hist.addMessage(msg, msgTime);
DefaultTableModel table = (DefaultTableModel)
ui.historyFrame.jTable1.getModel();
table.addRow(new Object[]{"Me", msg.content, msg.recipient, msgTime});
} catch (Exception ex) {
}
}
} catch (IOException ex) {
}
}

public void closeThread(Thread t) {


t = null;
}
}
2.5 Upload class
package com.socket;

import com.ui.ChatFrame;
import java.io.*;
import java.net.*;

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 49 | P a g e

public class Upload implements Runnable{

public String addr;


public int port;
public Socket socket;
public FileInputStream In;
public OutputStream Out;
public File file;
public ChatFrame ui;

public Upload(String addr, int port, File filepath, ChatFrame frame){


super();
try {
file = filepath; ui = frame;
socket = new Socket(InetAddress.getByName(addr), port);
Out = socket.getOutputStream();
In = new FileInputStream(filepath);
}
catch (Exception ex) {
}
}

@Override
public void run() {
try {
byte[] buffer = new byte[1024];

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 50 | P a g e

int count;

while((count = In.read(buffer)) >= 0){


Out.write(buffer, 0, count);
}
Out.flush();

ui.txtAreaChat.append("[Thông báo] : Tập tin tải lên thành công!\n");


ui.btnFile.setEnabled(true);
ui.btnGuiFile.setEnabled(true);
ui.txtUpFile.setVisible(true);

if(In != null){ In.close(); }


if(Out != null){ Out.close(); }
if(socket != null){ socket.close(); }
}
catch (Exception ex) {
}
}

}
2.6 ChatFrame class
package com.ui;

import com.socket.History;
import com.socket.Message;
import com.socket.SocketClient;

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 51 | P a g e

import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.io.IOException;
import javax.swing.DefaultListModel;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.UIManager;

public class ChatFrame extends javax.swing.JFrame {

public SocketClient client;


public int port;
public String serverAddr, username, password;
public Thread clientThread;
public DefaultListModel model;
public File file;
public String historyFile = "src\\com\\data\\History.xml";
public HistoryFrame historyFrame;
public History hist;

public ChatFrame() {
initComponents();
this.setTitle("Chương Trình Chát");
model.addElement("All");
listOnline.setSelectedIndex(0);

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 52 | P a g e

this.addWindowListener(new WindowListener() {

@Override
public void windowOpened(WindowEvent e) {
}

@Override
public void windowClosing(WindowEvent e) {
try {
client.send(new Message("message", username, ".bye", "SERVER"));
clientThread.stop();
} catch (Exception ex) {
}
}

@Override
public void windowClosed(WindowEvent e) {
}

@Override
public void windowIconified(WindowEvent e) {
}

@Override
public void windowDeiconified(WindowEvent e) {

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 53 | P a g e

@Override
public void windowActivated(WindowEvent e) {
}

@Override
public void windowDeactivated(WindowEvent e) {
}
});

hist = new History(historyFile);


historyFrame = new HistoryFrame(hist);
historyFrame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
historyFrame.setVisible(false);
}

@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {

jLabel1 = new javax.swing.JLabel();


txtAddress = new javax.swing.JTextField();
jLabel2 = new javax.swing.JLabel();
txtPort = new javax.swing.JTextField();
btnKetNoi = new javax.swing.JButton();

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 54 | P a g e

txtname = new javax.swing.JTextField();


jLabel3 = new javax.swing.JLabel();
jLabel4 = new javax.swing.JLabel();
btnDangKy = new javax.swing.JButton();
txtPass = new javax.swing.JPasswordField();
jSeparator1 = new javax.swing.JSeparator();
jScrollPane1 = new javax.swing.JScrollPane();
txtAreaChat = new javax.swing.JTextArea();
jScrollPane2 = new javax.swing.JScrollPane();
listOnline = new javax.swing.JList();
jLabel5 = new javax.swing.JLabel();
txtChat = new javax.swing.JTextField();
btnChat = new javax.swing.JButton();
btnDangNhap = new javax.swing.JButton();
jSeparator2 = new javax.swing.JSeparator();
txtUpFile = new javax.swing.JTextField();
btnFile = new javax.swing.JButton();
btnGuiFile = new javax.swing.JButton();
jLabel6 = new javax.swing.JLabel();
btnNhatKy = new javax.swing.JButton();

setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

jLabel1.setText("Host Address : ");

txtAddress.setText("localhost");

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 55 | P a g e

jLabel2.setText("Host Port : ");

txtPort.setText("9999");
txtPort.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtPortActionPerformed(evt);
}
});

btnKetNoi.setText("Kết Nối");
btnKetNoi.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnKetNoiActionPerformed(evt);
}
});

txtname.setEnabled(false);

jLabel3.setText("Password :");

jLabel4.setText("Nick Name");

btnDangKy.setText("Đăng Ký");
btnDangKy.setEnabled(false);
btnDangKy.addActionListener(new java.awt.event.ActionListener() {

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 56 | P a g e

public void actionPerformed(java.awt.event.ActionEvent evt) {


btnDangKyActionPerformed(evt);
}
});

txtPass.setEnabled(false);

txtAreaChat.setEditable(false);
txtAreaChat.setColumns(20);
txtAreaChat.setFont(new java.awt.Font("Consolas", 0, 12)); // NOI18N
txtAreaChat.setRows(5);
jScrollPane1.setViewportView(txtAreaChat);

listOnline.setModel((model = new DefaultListModel()));


jScrollPane2.setViewportView(listOnline);

jLabel5.setText("Message : ");

txtChat.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtChatActionPerformed(evt);
}
});

btnChat.setText("Gửi");
btnChat.setEnabled(false);

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 57 | P a g e

btnChat.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnChatActionPerformed(evt);
}
});

btnDangNhap.setText("Đăng nhập");
btnDangNhap.setEnabled(false);
btnDangNhap.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnDangNhapActionPerformed(evt);
}
});

btnFile.setText("...");
btnFile.setEnabled(false);
btnFile.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnFileActionPerformed(evt);
}
});

btnGuiFile.setText("Up File");
btnGuiFile.setEnabled(false);
btnGuiFile.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 58 | P a g e

btnGuiFileActionPerformed(evt);
}
});

jLabel6.setText("File :");

btnNhatKy.setText("Nhật Ký");
btnNhatKy.setEnabled(false);
btnNhatKy.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnNhatKyActionPerformed(evt);
}
});

javax.swing.GroupLayout layout = new


javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSeparator2)

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 59 | P a g e

.addComponent(jSeparator1,
javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING,
layout.createSequentialGroup()
.addComponent(jScrollPane1)
.addGap(18, 18, 18)
.addComponent(jScrollPane2,
javax.swing.GroupLayout.PREFERRED_SIZE, 108,
javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addGap(23, 23, 23)
.addComponent(jLabel6)

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(txtUpFile,
javax.swing.GroupLayout.PREFERRED_SIZE, 378,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(btnFile,
javax.swing.GroupLayout.PREFERRED_SIZE, 27,
javax.swing.GroupLayout.PREFERRED_SIZE)

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnGuiFile,
javax.swing.GroupLayout.PREFERRED_SIZE, 77,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING,
layout.createSequentialGroup()
.addComponent(jLabel5)

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 60 | P a g e

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtChat)
.addGap(18, 18, 18)
.addComponent(btnChat,
javax.swing.GroupLayout.PREFERRED_SIZE, 108,
javax.swing.GroupLayout.PREFERRED_SIZE))))
.addGroup(layout.createSequentialGroup()
.addGap(23, 23, 23)

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(layout.createSequentialGroup()
.addGap(453, 453, 453)
.addComponent(btnNhatKy,
javax.swing.GroupLayout.PREFERRED_SIZE, 81,
javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(javax.swing.GroupLayout.Alignment.LEADING,
layout.createSequentialGroup()

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel1)
.addComponent(jLabel4))

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(txtname)
.addComponent(txtAddress))
.addGap(18, 18, 18)

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 61 | P a g e

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jLabel2)
.addComponent(jLabel3))

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(txtPort)
.addComponent(txtPass))

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING,
false)
.addComponent(btnKetNoi,
javax.swing.GroupLayout.Alignment.TRAILING,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING,
layout.createSequentialGroup()
.addComponent(btnDangNhap)

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnDangKy,
javax.swing.GroupLayout.PREFERRED_SIZE, 81,
javax.swing.GroupLayout.PREFERRED_SIZE)))))))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 62 | P a g e

.addGroup(layout.createSequentialGroup()
.addContainerGap()

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE
)
.addComponent(jLabel1)
.addComponent(txtAddress, javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel2)
.addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnKetNoi))

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE
)
.addComponent(txtname, javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel3)
.addComponent(jLabel4)
.addComponent(btnDangKy)
.addComponent(txtPass, javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnDangNhap))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED,
11, Short.MAX_VALUE)

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 63 | P a g e

.addComponent(btnNhatKy)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE,
10, javax.swing.GroupLayout.PREFERRED_SIZE)

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING,
false)
.addComponent(jScrollPane1)
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE,
264, Short.MAX_VALUE))

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE
)
.addComponent(btnChat)
.addComponent(jLabel5)
.addComponent(txtChat, javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE))

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE,
10, javax.swing.GroupLayout.PREFERRED_SIZE)

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE,
false)

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 64 | P a g e

.addComponent(btnGuiFile, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btnFile, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jLabel6)
.addComponent(txtUpFile, javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap())
);

pack();
}// </editor-fold>

private void btnKetNoiActionPerformed(java.awt.event.ActionEvent evt) {


serverAddr = txtAddress.getText();
port = Integer.parseInt(txtPort.getText());

if (!serverAddr.isEmpty() && !txtPort.getText().isEmpty()) {


try {
client = new SocketClient(this);
clientThread = new Thread(client);
clientThread.start();
client.send(new Message("test", "testUser", "testContent", "SERVER"));
} catch (IOException ex) {
txtAreaChat.append("[Thông Báo] : Không tìm thấy Server\n");
}
}

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 65 | P a g e

private void btnDangNhapActionPerformed(java.awt.event.ActionEvent evt) {


this.setTitle(txtname.getText());
username = txtname.getText();
password = txtPass.getText();

if (!username.isEmpty() && !password.isEmpty()) {


client.send(new Message("login", username, password, "SERVER"));
}
}

private void btnChatActionPerformed(java.awt.event.ActionEvent evt) {


String msg = txtChat.getText();
String target = listOnline.getSelectedValue().toString();

if (!msg.isEmpty() && !target.isEmpty()) {


txtChat.setText("");
client.send(new Message("message", username, msg, target));
}
}

private void btnDangKyActionPerformed(java.awt.event.ActionEvent evt) {


this.setTitle(txtname.getText());
username = txtname.getText();
password = txtPass.getText();

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 66 | P a g e

if (!username.isEmpty() && !password.isEmpty()) {


client.send(new Message("signup", username, password, "SERVER"));
}
}

private void btnFileActionPerformed(java.awt.event.ActionEvent evt) {


JFileChooser fileChooser = new JFileChooser();
fileChooser.showDialog(this, "Chọn");
file = fileChooser.getSelectedFile();

if (file != null) {
if (!file.getName().isEmpty()) {
btnGuiFile.setEnabled(true);
String str;

if (txtUpFile.getText().length() > 30) {


String t = file.getPath();
str = t.substring(0, 20) + " [...] " + t.substring(t.length() - 20, t.length());
} else {
str = file.getPath();
}
txtUpFile.setText(str);
}
}
}

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 67 | P a g e

private void btnGuiFileActionPerformed(java.awt.event.ActionEvent evt) {


long size = file.length();
if (size < 120 * 1024 * 1024) {
client.send(new Message("upload_req", username, file.getName(),
listOnline.getSelectedValue().toString()));
} else {
txtAreaChat.append("[Thông Báo] : Tập tin quá lớn\n");
}
}

private void btnNhatKyActionPerformed(java.awt.event.ActionEvent evt) {


historyFrame.setLocation(this.getLocation());
historyFrame.setVisible(true);
}

private void txtChatActionPerformed(java.awt.event.ActionEvent evt) {


// TODO add your handling code here:
btnChatActionPerformed(null);
}

private void txtPortActionPerformed(java.awt.event.ActionEvent evt) {


// TODO add your handling code here:
}

public static void main(String args[]) {


try {

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 68 | P a g e

UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new ChatFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify
public javax.swing.JButton btnChat;
public javax.swing.JButton btnDangKy;
public javax.swing.JButton btnDangNhap;
public javax.swing.JButton btnFile;
public javax.swing.JButton btnGuiFile;
public javax.swing.JButton btnKetNoi;
public javax.swing.JButton btnNhatKy;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
private javax.swing.JLabel jLabel5;
private javax.swing.JLabel jLabel6;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 69 | P a g e

private javax.swing.JSeparator jSeparator1;


private javax.swing.JSeparator jSeparator2;
public javax.swing.JList listOnline;
public javax.swing.JTextField txtAddress;
public javax.swing.JTextArea txtAreaChat;
public javax.swing.JTextField txtChat;
public javax.swing.JPasswordField txtPass;
public javax.swing.JTextField txtPort;
public javax.swing.JTextField txtUpFile;
public javax.swing.JTextField txtname;
// End of variables declaration
}
2.7 HistoryFrame class
package com.ui;

import com.socket.History;

public class HistoryFrame extends javax.swing.JFrame {

public History hist;

public HistoryFrame() {
initComponents();
}

public HistoryFrame(History hist){


initComponents();

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 70 | P a g e

this.hist = hist;
hist.FillTable(this);
}

@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {

jLabel1 = new javax.swing.JLabel();


jScrollPane1 = new javax.swing.JScrollPane();
jTable1 = new javax.swing.JTable();

setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("Chat History");

jLabel1.setText("History : ");

jTable1.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {

},
new String [] {
"Sender", "Message", "To", "Time"
}
){
Class[] types = new Class [] {

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 71 | P a g e

java.lang.String.class, java.lang.String.class, java.lang.String.class,


java.lang.String.class
};
boolean[] canEdit = new boolean [] {
false, false, false, false
};

public Class getColumnClass(int columnIndex) {


return types [columnIndex];
}

public boolean isCellEditable(int rowIndex, int columnIndex) {


return canEdit [columnIndex];
}
});
jScrollPane1.setViewportView(jTable1);
jTable1.getColumnModel().getColumn(1).setPreferredWidth(200);

javax.swing.GroupLayout layout = new


javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 72 | P a g e

.addGroup(layout.createSequentialGroup()
.addComponent(jLabel1)
.addGap(0, 0, Short.MAX_VALUE))
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE,
485, Short.MAX_VALUE))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE,
289, Short.MAX_VALUE)
.addContainerGap())
);

pack();
}// </editor-fold>

public static void main(String args[]) {


/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional)
">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look
and feel.

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 73 | P a g e

* For details see


http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info :
javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {

java.util.logging.Logger.getLogger(HistoryFrame.class.getName()).log(java.util.logging.
Level.SEVERE, null, ex);
} catch (InstantiationException ex) {

java.util.logging.Logger.getLogger(HistoryFrame.class.getName()).log(java.util.logging.
Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {

java.util.logging.Logger.getLogger(HistoryFrame.class.getName()).log(java.util.logging.
Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {

java.util.logging.Logger.getLogger(HistoryFrame.class.getName()).log(java.util.logging.
Level.SEVERE, null, ex);
}
//</editor-fold>

Nhóm 2 – Mạng máy tính K56


Đồ án: ứng dụng chát Client – Server 74 | P a g e

/* Create and display the form */


java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new HistoryFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JLabel jLabel1;
private javax.swing.JScrollPane jScrollPane1;
public javax.swing.JTable jTable1;
// End of variables declaration
}

Tài Liệu tham khảo


http://vi.wikipedia.org/wiki/Client-server
http://www.softechaptech.com/forums/viewtopic.php?f=83&t=95
http://quyetdo289.wordpress.com/2013/03/04/doc-file-xml-trong-java-dom-xml-parser/
https://www.youtube.com/watch?v=9iTl_H8kVzM&list=PLlSyE2TKmdTSWUOKFoQg
rJaWPd_cUbV0V
http://congdongjava.com/forum/

Nhóm 2 – Mạng máy tính K56

You might also like