1. Trang chủ
  2. » Luận Văn - Báo Cáo

Đồ án lập trình mạng xây dựng ứng dụng chat client – server

74 0 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Đồ án lập trình mạng xây dựng ứng dụng chat client – server
Tác giả Phan Mạnh Tiến, Đỗ Viết Thanh, Nguyễn Thị Thanh Huệ, Nguyễn Thanh Hương, Nguyễn Thế Phong, Phạm Văn Thực
Trường học Trường Đại Học Mỏ - Địa Chất Hà Nội
Chuyên ngành Mạng Máy Tính
Thể loại đồ án
Năm xuất bản 2014
Thành phố Hà Nội
Định dạng
Số trang 74
Dung lượng 5,23 MB

Cấu trú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)

Nội dung

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

Tổng quan về đề tài

Cơ sở lý thuyết

 Cơ chế Socket trong Java

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

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

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

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 được tách ra làm 2 form: ChatFram (phần chát chính) và HistoryFram (nhật ký chát).

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)

2.2.2 Các lớp xử lý của chương trình

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

Hướng dẫn cài đặt

Chương trình bao gồm hai phần chính: Client và Server Để chương trình hoạt động, cần khởi động Server trước để lắng nghe các yêu cầu từ Client, sau đó mới khởi động các Client.

Chạy Server ta Run File ServerFrame là Main

Chạy Client ta Run File ChatFramme là Main

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

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

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

Để thực hiện chát riêng tư trên List Online, người dùng chỉ cần chọn người mà mình muốn trò chuyện Ví dụ, Đỗ Thanh đã chát riêng với Thanh Huệ, trong khi Thanh Huệ và Văn Thực cũng đã thực hiện chát riêng với Đỗ Thanh.

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

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

 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

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

Source code

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;

} 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;

} catch (Exception ex) { return false;

} public boolean checkLogin(String username, String password) { if (!userExists(username))

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);

((Node)textAgeList.item(0)).getNodeValue().trim());

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))

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);

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);

TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer();

DOMSource source = new DOMSource(doc);

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

} 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();

1.2 Message class package com.socket; import java.io.Serializable; public class Message implements Serializable{ private static final long serialVersionUID = 1L;

The Java class defines a Message with attributes: type, sender, content, and recipient It includes a constructor that initializes these attributes, allowing for the creation of message objects with specific characteristics This structure is essential for managing and sending messages in a programming context.

@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 { public SocketServer server; public Thread serverThread; public String filePath = "src\\com\\data\\Data.xml"; public ServerFrame() { initComponents(); this.setTitle("Server Chat"); txtThongBao.setEditable(false);

The code snippet initializes a graphical user interface for a server application called "jServer." It includes a button labeled "Start Server" that triggers an action when clicked, and a text area for displaying notifications The window is set to close on exit, ensuring a user-friendly experience.

The code snippet initializes a text area, `txtThongBao`, with 20 columns and a font size of 12 in Consolas It sets the number of rows to 5 and attaches the text area to a scroll pane for better visibility The layout is managed using `javax.swing.GroupLayout`, which organizes components in a horizontal group, ensuring a structured and user-friendly interface.

addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE,

addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE,

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

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

addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE,

}// 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){

} 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;

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 = ""; 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 {

} public int getID() { return ID;

@Override public void run() { ui.txtThongBao.append("\nServer Thread " + ID + " đang chạy "); while (true) { try {

Message msg = (Message) In.readObject(); server.handle(ID, msg);

System.out.println(ID + " Lỗi: " + ioe.getMessage()); server.remove(ID);

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());

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

} public void close() throws IOException { if (socket != null) { socket.close();

The `SocketServer` class implements the `Runnable` interface and manages multiple client connections through an array of `ServerThread` objects, supporting up to 50 clients It initializes a `ServerSocket` on port 9999 and establishes a user interface with `ServerFrame`, while also connecting to a database using the specified file path Upon successful startup, the server notifies users with a message indicating its operational status and the local IP address.

InetAddress.getLocalHost() + ", Port : " + server.getLocalPort()); start();

} catch (IOException ioe) { ui.txtThongBao.append("Không thể mở cổng : " + port); ui.RetryStart(0);

To enhance the functionality of the SocketServer, the method is modified to include a public parameter: `SocketServer(ServerFrame frame, int Port)` This implementation initializes an array of ServerThread objects to accommodate up to 50 clients, assigns the user interface from the provided frame, and sets the port number A database instance is created using the file path from the UI Within a try block, a ServerSocket is established on the specified port, and the actual local port is retrieved A message indicating the server's activation along with its IP address is appended to the UI's notification text area.

InetAddress.getLocalHost() + ", Port : " + server.getLocalPort()); start();

} catch (IOException ioe) { 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() { if (thread != null) { thread = null;

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

} 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);

{ if (msg.type.equals("login")) { if (findUserThread(msg.sender) == null)

// kiểm tra 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);

{ clients[findClient(ID)].send(new Message("login", "SERVER", "FALSE", msg.sender));

{ 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"))

{ 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);

} else { clients[findClient(ID)].send(new Message("signup", "SERVER",

{ clients[findClient(ID)].send(new Message("signup", "SERVER", "FALSE", msg.sender));

In response to an upload request, if the recipient is set to "All," the server will notify the requesting client that uploading to all users is not permitted, ensuring compliance with usage policies.

{ 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));

{ 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);

} 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];

@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) { for (int i = pos + 1; i < clientCount; i++) { clients[i - 1] = clients[i];

} catch (IOException ioe) { ui.txtThongBao.append("\nLỗi: " + ioe);

} 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 { ui.txtThongBao.append("\nĐã vượt quá số Client cho phép đăng nhập: " + clients.length);

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(); this.saveTo = saveTo; this.ui = ui;

@Override public void run() { try { socket = server.accept();

System.out.println("Download : "+socket.getRemoteSocketAddress());

Out = new FileOutputStream(saveTo); byte[] buffer = new byte[1024]; int count; while((count = In.read(buffer)) >= 0){

Out.flush(); ui.txtAreaChat.append("[Thông Báo] : Download thành công!\n"); if(Out != null){ Out.close(); } if(In != null){ In.close(); } if(socket != null){ socket.close(); }

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; 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);

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

Element _sender = doc.createElement("sender");

Element _content = doc.createElement("content");

Element _recipient = doc.createElement("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();

DOMSource source = new DOMSource(doc);

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

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) {

Element eElement = (Element) nNode; model.addRow(new Object[]{getTagValue("sender", eElement), getTagValue("content", eElement), getTagValue("recipient", eElement), getTagValue("time", eElement)});

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();

Class này có chức năng cho phép Client và Server gửi các Object qua lại với nhau, do đó cần phải được Serializable Cấu trúc của class này là giống nhau ở cả Client và Server.

2.4 SocketClient class package com.socket; import com.ui.ChatFrame; import java.io.*; import java.net.*; 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());

In = new ObjectInputStream(socket.getInputStream()); hist = ui.hist;

@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});

// Đăng nhập tk với loại login

Upon a successful login, the user interface enables the chat and file buttons while disabling the login and registration buttons A notification message, "[Notification]: Login successful!" is displayed in the chat area, and the username and password input fields are also disabled.

} else { ui.txtAreaChat.append("[Thông Báo] : Lỗi đăng nhập.\n");

// Kết nối vào server loại test

In the event that the message type is "test," the connection button is disabled while the login and registration buttons are enabled Additionally, the username and password fields are activated for user input, while the address and port fields are set to read-only.

In the event of a new user message, the system checks if the username is different from the current user's If it is, the program verifies whether the new username already exists in the user interface model This is accomplished through a loop that examines each element in the model to confirm the presence of the new username.

} if (!exists) { ui.model.addElement(msg.content);

If the message type is "signup" and the content indicates success, the UI enables the "Nhat Ky" button while disabling the "Dang Nhap" and "Dang Ky" buttons, and enables the "Chat" and "File" buttons, displaying a success notification in the chat area Conversely, if the signup fails, an error message is shown in the chat area.

In response to a sign-out message, if the username matches the current user, the chat interface updates to display a farewell message from the sender The connection button is re-enabled, while the chat button is disabled, and the address and port fields become editable Additionally, all elements in the model, starting from the second element, are removed to refresh the user interface.

} 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) {

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");

} else { ui.txtAreaChat.append("[Thông Báo] : Lỗi \n");

In the event of a connection failure, the user interface will display a notification indicating that there is no connection The connection button will be re-enabled, allowing users to edit the address and port fields Additionally, the chat and file buttons will be disabled to prevent further actions The model will also be cleared of any existing elements, starting from the second item.

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

} public void send(Message msg) { try {

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) {

} public void closeThread(Thread t) { t = null;

2.5 Upload class package com.socket; import com.ui.ChatFrame; import java.io.*; import java.net.*; 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);

@Override public void run() { try { byte[] buffer = new byte[1024]; int count; while((count = In.read(buffer)) >= 0){

The upload process has been successfully completed, as indicated by the message displayed in the chat area The file upload button and send file button are now enabled, and the uploaded file text area is visible Additionally, all input and output streams, as well as the socket connection, have been properly closed to ensure resource management.

2.6 ChatFrame class package com.ui; import com.socket.History; import com.socket.Message; import com.socket.SocketClient; 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); 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();

@Override public void windowClosed(WindowEvent e) {

@Override public void windowIconified(WindowEvent e) {

@Override public void windowDeiconified(WindowEvent 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);

The code initializes a graphical user interface (GUI) for a chat application, featuring components such as labels for host address and port, text fields for user input, and buttons for connecting and registering The interface includes a text area for chat messages, a list for online users, and functionality for file uploads Default settings are established with "localhost" as the host address and "9999" as the port The application is designed to facilitate user interaction through chat and file sharing, ensuring a seamless experience.

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

The registration form includes a disabled text field for the name and labels for "Password" and "Nick Name." The "Register" button is also disabled until certain conditions are met, and it is set to trigger an action event when clicked, executing the registration process.

Ngày đăng: 19/12/2024, 15:32

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN