2.1 Phân tích yêu cầu bài toánYê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 So
Trang 1BỘ 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
Nguyễn Thị Thanh Huệ 1121050218 Nguyễn Thanh Hương 1121050228 Nguyễn Thế Phong 1121050073 Phạm Văn Thực 1121050103
Hà Nội, Ngày 18 Tháng 5 Năm 2014
Trang 2Đồ án: ứng dụng chát Client – Server 2 | P a g e
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
Trang 32.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
Trang 4Đồ án: ứng dụng chát Client – Server 4 | P a g e
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)
Trang 5Đồ án: ứng dụng chát Client – Server 5 | P a g e
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)
Trang 6Đồ án: ứng dụng chát Client – Server 6 | P a g e
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
Trang 7Chạ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
Trang 8Đồ án: ứng dụng chát Client – Server 8 | P a g e
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
Trang 9Đồ án: ứng dụng chát Client – Server 9 | P a g e
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
Trang 10Đồ á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
Trang 11Đồ á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
Trang 12Đồ á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
Trang 13Đồ á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
Trang 14Đồ án: ứng dụng chát Client – Server 14 | P a g e
IV Source code
1 Chương trình bên Server
public class Database {
public String filePath="";
public Database(String filePath) {
this.filePath = filePath;
Trang 15Đồ á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
Trang 16Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("user");
for (int i = 0; i < nList.getLength(); i++)
Trang 17Đồ á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) &&
Document doc = dBuilder.parse(filePath);
// Tạo 1 node
Node data = doc.getFirstChild();
// Thêm 1 user
Trang 18Đồ án: ứng dụng chát Client – Server 18 | P a g e
Element newuser = doc.createElement("user");
Element newusername = doc.createElement("username");
//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));
Trang 19private 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+"',
Trang 20Đồ á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";
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);
Trang 22Đồ á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,
public void RetryStart(int port){
if(server != null){ server.stop(); }
server = new SocketServer(this, port);
catch(Exception ex){
Trang 23// Variables declaration - do not modify
private javax.swing.JButton btnStart;
private javax.swing.JScrollPane jScrollPane1;
public javax.swing.JTextArea txtThongBao;
// End of variables declaration
class ServerThread extends Thread {
public SocketServer server = null;
public Socket socket = null;
public int ID = -1;
public String username = "";
Trang 24Đồ á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) {
Trang 25Đồ á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());
Trang 26public 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 {
Trang 27Đồ á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());
// Viết lại pt thêm tham số Port
public SocketServer(ServerFrame frame, int Port) {
clients = new ServerThread[50];
ui.txtThongBao.append("Server bắt đầu hoạt động IP : " +
InetAddress.getLocalHost() + ", Port : " + server.getLocalPort());
start();
} catch (IOException ioe) {
Trang 29private int findClient(int ID) {
for (int i = 0; i < clientCount; i++) {
public synchronized void handle(int ID, Message msg) {
// Thông báo đến các Client có máy out
Trang 32public 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);
Trang 33Đồ á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++)
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) {
Trang 34ui.txtThongBao.append("\nThêm Client: " + socket);
clients[clientCount] = new ServerThread(this, socket);
Trang 35public ServerSocket server;
public Socket socket;
public int port;
public String saveTo = "";
public InputStream In;
public FileOutputStream Out;
public ChatFrame ui;
Trang 37Đồ á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(); }
Trang 38Document doc = docBuilder.parse(filePath);
Node data = doc.getFirstChild();
Element message = doc.createElement("message");
Element _sender = doc.createElement("sender");
Trang 39Đồ á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));
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) {
Trang 40Đồ á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),
Trang 41public 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;
Trang 42Message msg = (Message) In.readObject();
System.out.println("Nhận vào : " + msg.toString());
//Gửi tin nhắn dưới loại message
Trang 44Đồ á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++) {
Trang 45{
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) {