Võ Văn Hải's blog

Chỉ có một điều tuyệt đối đó là mọi thứ đều tương đối…

ChatRoom đơn giản

Trong ví dụ này, chúng ta sẽ làm 1 chat room đơn giản sử dụng java Socket. Đầu tiên, ta xây dựng 1 server lắng nghe trên cổng 9999 và cho phép nhiều client cùng kết nối 1 lúc.

Ở đây 1 cách đơn giản, chúng ta dùng 1 ArrayList để lưu danh sách các socket kết nối. Không có giới hạn nào cho việc kết nối cả.

Code cho Chatroom server:



package chatchit.chatroom;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Scanner;

public class ChatRoomServer {
  private static String message="";
  public static void main(String[] args) {
    try {
      final ServerSocket svr=new ServerSocket(9999);
      System.out.println("Chatroom server starting...");
      final ArrayList<Socket>listSoc=new ArrayList<Socket>();
      while(true) { 
        final Socket soc=svr.accept();
        listSoc.add(soc);
        System.out.println("number of client is "+listSoc.size());
        new Thread(new Runnable() {
          @Override
          public void run() {
            try {
              Scanner in=new Scanner(soc.getInputStream());
              while(in.hasNextLine()) {
                message=in.nextLine();
                for(Socket s:listSoc) {
                  if(s==null
                    listSoc.remove(s);
                  else if(!s.equals(soc)){
                    PrintWriter out=new PrintWriter(s.getOutputStream(),true);
                    out.println(message);
                  }
                }
              }
            catch (IOException e) {
              e.printStackTrace();
            }
          }
        }).start();
      }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}

Client
Ta có thể dùng telnet làm client cho các chat client. Cách thực hiện như sau:
Vào menu run, gõ telnet, 1 cửa sổ console xuất hiện. Ta kết nối đến chatroom bằng lệnh o localhost 9999(nếu nối đến 1 server khác thì url thay vì localhost phải đối thành IP hoặc server name).
Như vậy ta chat được rồi đấy. hình minh họa:
https://vovanhai.files.wordpress.com/2009/03/chattelnet.png
Ta cũng có thể xây dụng 1 client chat đơn giản với ý tưởng như sau: client gồm 2 tiến trình. 1 tiến trình dùng cho việc đọc các thông điệp từ chatroom gửi về và 1 tiến trình cho việc phát đi các thông điệp. Code như sau:



package chatchit.chatroom;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class ChatClient {
  public static void main(String[] args) {
    try {
      final Socket soc=new Socket("localhost",9999);
      while(true)
      {
        new Thread(new Runnable() {
          Scanner sc=new Scanner(System.in);
          String msg=sc.nextLine();
          @Override
          public void run() {
            try {
              if(msg.equalsIgnoreCase("bye"))
                System.exit(1);
              PrintWriter out=new PrintWriter(soc.getOutputStream(),true);
              out.println(msg);
            catch (IOException e) {
              e.printStackTrace();
            }
          }
        }).start();
        new Thread(new Runnable() {
          @Override
          public void run() {
            try {
              Scanner in=new Scanner(soc.getInputStream());
              while(in.hasNextLine()) {
                System.out.println("svr:"+in.nextLine());
              }
            catch (IOException e) {
              e.printStackTrace();
            }
          }
        }).start();
      }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}

Lưu ý: code ở đây hết sức đơn giản. Để xây dựng 1 trình chat thực sự bạn còn rất nhiều chuyện để làm. Tôi sẽ quay lại hướng dẫn đề tài này 1 ngày gần đây. Chúc thành công!

5 Responses to “ChatRoom đơn giản”

  1. changngoc said

    Thầy ơi! cái bài này em muốn đưa vào giao diện gồm có một cái 1 JtextField,1 Jbutton, 1 Jlist. khi người ta nhập vào textfield và dữ liệu sẽ được lấy gởi tới Server sau khi nhấn button. Nếu em viết giống như thầy thì cái vòng while nó chạy hoà đến khi OutoffmemoryError vì trong cái hàm While em có một cái “String str = text.gettext();” cái này nó cứ chạy hoài cho đến khi hết dung lượng của Ram thì nó mới văng ra mặc dù em đã để “String str = text.gettext();” trong hàm “if(obj.equals(btn))” nó vẫn outoffmemory
    Nếu em bỏ cái vòng while thì nó sau khi click button thì hàm “actionPerformed(ActionEvent arg0)” được gọi lại và cái port của client lại được làm mới do đó no nhận dữ liệu không đúng. Thầy làm thế nào chỉ dùm em với.

  2. dieudx said

    Thầy ơi, với một chương trình chát em dùng multithread, thì mình có cách nào để kiểm tra được số Threads tối đa tại một thời điểm hay không?

  3. Phuong said

    Em chao thay!
    Thay oi em dang su dung netbean de lap trinh mang, nhung em khong biet lam the nao de chay 2 chuong trinh client/ server dong thoi ma khong can dung den start/run. Thay co the chi cho em biet khong ah?
    Em cam on thay nhieu!

  4. vovanhai said

    Nhấn phải lên lớp, chọn run file

  5. nguyen kim chi said

    thầy ơi em đang tạo một phòng chat bằng eclipse, khi em telnet tới thì nó lít được những người đang chat nhưng ma khi em đóng lại rồi thì nó vẫn hiện ra danh sách những người đang chat. e phải làm sao khi e đóng lại thì user đó cũng thoát ra khỏi phòng chat.
    Code của em đây thầy:
    package org.dsna.helloserver;

    import java.util.ArrayList;

    import org.apache.mina.core.service.IoHandlerAdapter;
    import org.apache.mina.core.session.IoSession;

    public class HelloServerHandler extends IoHandlerAdapter {

    private static final Object USER_ID = “USER_ID”;
    private final ArrayList conectedSessions = new ArrayList();

    @Override
    public void sessionOpened(IoSession session) throws Exception {
    super.sessionOpened(session);
    session.write(“Welcome to my server”);
    }

    @Override
    public void messageReceived(IoSession session, Object message)
    throws Exception {
    String str = message.toString();
    String commands[] = str.split(” “);

    if (str.trim().equalsIgnoreCase(“bye”)) {
    session.close(true);
    return;
    } else if (str.trim().equalsIgnoreCase(“hi”)) {
    session.write(“I’m Chi”);
    }

    if (commands.length == 1) {
    if (commands[0].equals(“help”)) {
    session.write(“Available commands:”);
    session.write(“connect : connect to the user to the tchat”);
    session.write(“disconnect : disconnect the user from the tchat”);
    session.write(“message : send a message to the user “);
    session.write(“message-all : send a message to all connected users”);
    session.write(“list : get the list of all connected users”);
    session.write(“quit : close the session to the server”);

    } else if (commands[0].equals(“disconnect”)) {
    String userName = (String) session.getAttribute(USER_ID);
    if (userName == null) {
    session.write(“You are not connect nơw”);
    } else {
    session.setAttribute(USER_ID, null);
    conectedSessions.remove(session); // ex9 step 2b
    session.write(“You are have been disconnect: ” + userName);
    }
    } else if (commands[0].equals(“list”)) { // ex9 step 3
    for (IoSession tmpSession : conectedSessions) {
    String nameOfTheUser = (String) tmpSession
    .getAttribute(USER_ID);
    session.write(nameOfTheUser);
    }

    }

    } else if (commands.length == 2) {
    if (commands[0].equals(“connect”)) {
    String userName = (String) session.getAttribute(USER_ID);

    if (session.getAttribute(USER_ID) == null) {
    conectedSessions.add(session); // ex9 step 2a
    session.write(“Welcome ” + commands[1]);
    session.setAttribute(USER_ID, commands[1]);
    // session.write(“list”);
    // arl.add(USER_ID);
    } else {
    session.write(“You are already connected, your user name is ”
    + userName);
    }
    }
    } else if (commands[0].equals(null)) {
    String userName = (String) session.getAttribute(USER_ID);
    if (userName == null) {

    }
    }
    }
    }

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: