Form chính nhận số port do người dùng nhập vào.
Sau khi nhấn nút Start, hàm startServer của class ChatServer sẽ khởi tạo thread serverThread, thread này sẽ mở ra 1 socket và listen ở cổng đã được chỉ định.
Ngoài ra khi server chạy, sẽ có 2 thread khác được chạy là clientChecker và dataRouter.
Khi có 1 client kết nối vào, serverThread sẽ mở ra 1 client thread, mỗi client thread sẽ chịu trách nhiệm gửi và nhận dữ liệu từ 1 client.
Trong quá trình giao tiếp với client, client thread sẽ nắm giữ 1 kết nối, và phát sinh ra 1 thread khác chỉ có nhiệm vụ duy nhất là nhận và xử lý dữ liệu. Thread này là inProcessor. Như vậy, inProcessor sẽ luôn lắng nghe và nhận dữ liệu về, và thread client chỉ gửi dữ liệu đi.
Các client được quản lý bằng dãy và dãy này là ClientList. Trong cấu hình server, chúng tôi để số client tối đa là 20, nếu muốn tăng số lượng, có thể điều chỉnh bằng cách thay đổi hằng MAX_CLIENT trong lớp ServerThread.
Dữ liệu gửi tới được inProcessor xử lý, nếu có yêu cầu gửi message đến client khác, message sẽ được gửi đến thread dataRouter qua hàm bringTo();
Vì cấu trúc dùng để lưu giữ dãy client là cấu trúc array, mặt khác, trong quá trình sử dụng luôn có người dùng login, logout nên việc xóa dữ liệu về những client đã log out là cần thiết. Nếu không sẽ không đủ tài nguyên để cung cấp cho 1 lượng user lớn và quá trình chạy lâu dài. Thread clientChecker cứ mỗi 1s sẽ kiểm tra xem user nào đã logout và xóa dữ liệu về client đó trong ClientList, tức là dừng thread và xóa hẳn con trỏ trong dãy ClientList.
Ngoài ra, để dễ dàng cho việc thể hiện các user đang online trên giao diện của server, class ChatServer có 1 danh sách ClientNameList chỉ dùng để lưu danh sách các người dùng đang online, và danh sách được cập nhật qua các hàm clientListAdd và clientListRemove.
Mỗi khi có người dùng kết nối vào, hàm pushNewClientList của class ServerThread sẽ được gọi nhằm thông báo đến người dùng trên toàn hệ thống cập nhật danh sách người dùng mới.
12 trang |
Chia sẻ: ngtr9097 | Lượt xem: 3223 | Lượt tải: 1
Bạn đang xem nội dung tài liệu Đồ án Thiết kế chương trình chat server, để tải tài liệu về máy bạn click vào nút DOWNLOAD ở trên
CẤU TRÚC CHƯƠNG TRÌNH MINICHAT
Cấu trúc chương trình chat server
Form chính nhận số port do người dùng nhập vào.
Sau khi nhấn nút Start, hàm startServer của class ChatServer sẽ khởi tạo thread serverThread, thread này sẽ mở ra 1 socket và listen ở cổng đã được chỉ định.
Ngoài ra khi server chạy, sẽ có 2 thread khác được chạy là clientChecker và dataRouter.
Khi có 1 client kết nối vào, serverThread sẽ mở ra 1 client thread, mỗi client thread sẽ chịu trách nhiệm gửi và nhận dữ liệu từ 1 client.
Trong quá trình giao tiếp với client, client thread sẽ nắm giữ 1 kết nối, và phát sinh ra 1 thread khác chỉ có nhiệm vụ duy nhất là nhận và xử lý dữ liệu. Thread này là inProcessor. Như vậy, inProcessor sẽ luôn lắng nghe và nhận dữ liệu về, và thread client chỉ gửi dữ liệu đi.
Các client được quản lý bằng dãy và dãy này là ClientList. Trong cấu hình server, chúng tôi để số client tối đa là 20, nếu muốn tăng số lượng, có thể điều chỉnh bằng cách thay đổi hằng MAX_CLIENT trong lớp ServerThread.
Dữ liệu gửi tới được inProcessor xử lý, nếu có yêu cầu gửi message đến client khác, message sẽ được gửi đến thread dataRouter qua hàm bringTo();
Vì cấu trúc dùng để lưu giữ dãy client là cấu trúc array, mặt khác, trong quá trình sử dụng luôn có người dùng login, logout nên việc xóa dữ liệu về những client đã log out là cần thiết. Nếu không sẽ không đủ tài nguyên để cung cấp cho 1 lượng user lớn và quá trình chạy lâu dài. Thread clientChecker cứ mỗi 1s sẽ kiểm tra xem user nào đã logout và xóa dữ liệu về client đó trong ClientList, tức là dừng thread và xóa hẳn con trỏ trong dãy ClientList.
Ngoài ra, để dễ dàng cho việc thể hiện các user đang online trên giao diện của server, class ChatServer có 1 danh sách ClientNameList chỉ dùng để lưu danh sách các người dùng đang online, và danh sách được cập nhật qua các hàm clientListAdd và clientListRemove.
Mỗi khi có người dùng kết nối vào, hàm pushNewClientList của class ServerThread sẽ được gọi nhằm thông báo đến người dùng trên toàn hệ thống cập nhật danh sách người dùng mới.
Hàm setStatus của class ServerThread được gọi khi có 1 người dùng nào đó muốn đổi trạng thái của mình, ở đây có 2 trạng thái để lựa chọn là Available và Invisible.
Sau khi cập nhật trạng thái, hàm pushNewClientList cũng sẽ được gọi để cập nhật danh sách người dùng.
Cấu trúc chương trình chat client
Chat Client có 3 form chính là LoginForm, MainWindow và ChatWindow, ngoài ra còn 1 form phụ là AboutBox, mỗi form tương ứng với 1 class trong chương trình.
Login form
Sau khi kết nối thành công đến server, thread clientSocket sẽ chạy và nắm giữ socket, thread này sẽ chịu trách nhiệm gửi các message điều khiển đến server.
clientSocket sẽ khởi tạo các thread:
MainWindow : là thread phát sinh ra giao diện người dùng để giao tiếp với người sử dụng
Main window
inProcessor : tương tự như ở server, inProcessor sẽ chịu trách nhiệm xử lý các message đến từ server.
chatManager: quản lý các cửa sổ chat. Khi người dùng có nhu cầu chat với 1 người trong buddy list hoặc có 1 chat message từ server đến, chatManager sẽ kiểm tra và mở ra 1 cửa sổ chat tương ứng với buddy đó bằng hàm openChatWindow. Các cửa sổ chat được xếp vào dãy chatList, tương ứng trong ứng dụng này sẽ có tối đa 20 cửa sổ được mở, có thể thay đổi số lượng này bằng cách khai báo lại dãy :
ChatWindow[] chatList = new ChatWindow[20]
Chat window
Danh sách các lệnh điều khiển:
Lệnh từ client gửi đến server:
/to/::
Gửi 1 message đến người sử dụng có ID buddy
/command/login
Bắt đầu đăng nhập, sau lệnh này, client sẽ gửi 1 chuỗi là ID của người sử dụng ở client. Nếu chuỗi này bắt đầu bằng /hideme/ thì người dùng này đăng nhập ở trạng thái invisible
/command/logout
Kết thúc phiên làm việc, thoát ra khỏi server
/command/hideme
Chuyến trạng thái sang Invisible
/command/showme
Chuyển trạng thái sang Available
/clientlist/
Yêu cầu server gửi danh sách các người dùng đang online
Lệnh từ server gửi đến client:
ClientID:
Là 1 con số chỉ thị số ID của người dùng trong dãy quản lý thread, chỉ quan trọng trong debug.
ClientList//////..
Danh sách người dùng online, phân cách bằng dấu “//” và bỏ đi chữ ClientList ở đầub
/from/::
Gửi 1 message từ đến máy client.
NameExisted
Khi login vào server với 1 ID, nếu client nhận được mã này, tức là đã có người online với ID đó, và ID đó không được chấp nhận
/error/
Gửi đến client 1 thông báo lỗi
/shutdown/
Gửi đến client thông báo về việc dừng server, mọi client sẽ phải logout
CÁCH SỬ DỤNG CHƯƠNG TRÌNH MINICHAT
Có một máy làm server chạy chương trình Chat Server
Khi mở chương trình Chat Server đánh number port vào ô port, khi đó sẽ hiện lên ở khung địa chỉ IP và port của máy server
Các máy client cần phải biết địa chỉ IP và port của máy Server
Người sử dụng khi chạy chương trình Chat Client sẽ hiện ra một cửa sổ đăng nhập, người dùng nhập user name và địa chỉ port và IP của máy server vào sau đó nhấn nút Login, sẽ hiện ra cửa sổ chính dưới :
Login window
Cửa sổ chính gồm có danh sách user online muốn chat với người nào thì nhấp đúp vào tên người đó trong Online User, khi đó sẽ hiện lên cửa sổ chat .
người dùng chỉ cần đánh thông tin cần chat rồi nhấn Send hoặc nhấn phím Enter để gửi đi.
Chương trình có thêm tính năng invisible giúp người dùng ẩn không hiện lên trong danh sách online của các user khác .
Khi người dùng không muốn chat nữa thì trên thanh menu chọn File ->Logout
để thoát khỏi chương trình .
LẬP TRÌNH TRUYỀN NHẬN DỮ LIỆU:
Server
public void startServer(int port){
try {
welcomeSocket = new ServerSocket(port);
logWrite("Socket created at port " + port );
logWrite("Server IP is " + InetAddress.getLocalHost().getHostAddress());
serverThread = new ServerThread(welcomeSocket,this);
………
} catch (IOException ex) {
//Logger.getLogger(ChatServer.class.getName()).log(Level.SEVERE, null, ex);
JOptionPane.showMessageDialog(this, "The port has been used, please select another ", "Error", JOptionPane.ERROR_MESSAGE);
}
}
Hàm startServer khởi tạo 1 TCP server socket và đưa quyền nắm giữ socket đó cho thread serverThread
ClientList[nextSlot] = new Client(mainThread,nextSlot);
ClientList[nextSlot].connection = mainSocket.accept();
clientListBusy = true; //turn of this value in Client.class
ClientList[nextSlot].start();
mainThread.logWrite("New client connected " + ClientList[nextSlot].connection.getInetAddress(). getHostAddress().toString());
ClientCount++;
mainThread.updateClientCount(ClientCount);
Khi có client kết nối vào server, hàm accept() sẽ trả về 1 kết nối, 1 thread sẽ được phát sinh để nắm giữ connection
Client
public void logIn(){
int Error = 0;
if(jTextField_username.getText().equals("")){
JOptionPane.showMessageDialog(rootPane, "Check the user name!", "Error", JOptionPane.ERROR_MESSAGE);
Error++;
} else if(jTextField_serverip.getText().equals("")){
JOptionPane.showMessageDialog(rootPane, "Check the server IP!", "Error", JOptionPane.ERROR_MESSAGE);
Error++;
} else if(jTextField_serverport.getText().equals("")){
JOptionPane.showMessageDialog(rootPane, "Check the server port!", "Error", JOptionPane.ERROR_MESSAGE);
Error++;
}
if(Error == 0){
clientSocket = new ClientSocket(jTextField_serverip.getText(), Integer.parseInt(jTextField_serverport.getText()),jTextField_username.getText(),jCheckBox_invisible.isSelected(),jCheckBox_remember.isSelected(),this);
}
}
FLOW CHART
Server
Client 3
inputProcessor
Client 2
inputProcessor
Client 1
inputProcessor
Client Checker
Server Thread
Data Router
Chat Server
(GUI)
Client
Chat Window
(GUI)
Chat Window
(GUI)
Chat Window
(GUI)
Chat Manager
Input Processor
Main Window
(GUI)
Client Socket
Login Form
(GUI)