Java小程序之简单多人聊天室的实现(山寨QQ前传)

duzicunhuo 8年前
   <h2><strong>一、前言:</strong></h2>    <p>通过对Java服务器生猛上手的学习,已经基本明白了Java中通信的基本原理,以及服务器,ip,ip地址的概念;</p>    <p>我们思考下服务器到底是用来干嘛的呢?当多台客户端连上服务器以后,服务器需要提供的就是为连接进来的客户端提供相应的服务;具体的来说就是处理不同客户端发来的消息或者数据,然后把这些消息或者数据发送到另外的客户端;服务器的目的就是正确转发消息或者数据;</p>    <h2><strong>二、简单多人聊天室的实现思路:</strong></h2>    <p>1、创建服务器, 等待客户端的连接</p>    <p>2、客户端连接进来以后,获取输入输出流,利用输入输出流发送消息;</p>    <p>3、发送服务器连接成功的信息给客户端,并提示客户端输入账户和密码进行登录</p>    <p>4、服务器接收客户端发来的账号和密码,校验成功后,提示登录成功,开始多人聊天</p>    <p>难点:如何实现多人聊天? 定义一个容器:用于封装所有的 ServerThread 线程对象,遍历该容器中的对象,将消息转发给每一个客户端(自己可以除外)</p>    <p>问题: 当某个客户端退出后,其他客户端再发消息的时候,转发就会报错;</p>    <p>解决:当有客户端退出时,将该客户端从容器中移除;不在向该客户端转发消息;</p>    <h2>三、 <strong>程序源代码:</strong></h2>    <p>连接服务器类:</p>    <pre>  package com.huaxin.server;    import java.io.IOException;  import java.net.ServerSocket;  import java.net.Socket;  import java.util.ArrayList;    public class Myserver {      public static ArrayList<ServerThread>list =new ArrayList<ServerThread>();      public  void initServer() {        try {     //创建服务器对象,并指定端口号     ServerSocket server = new ServerSocket(9090);     System.out.println("服务器已经建立......");     //不断获取客户端的连接     while(true){      Socket socket =server.accept();      System.out.println("客户端连接进来了......");      //当有客户端连接进来以后,开启一个线程,用来处理该客户端的逻辑,      ServerThread st = new ServerThread(socket);      st.start();      //添加该客户端到容器中      list.add(st);     }    } catch (Exception e) {     e.printStackTrace();    }     }    }</pre>    <p>服务器线程处理类:</p>    <pre>  package com.huaxin.server;    import java.io.IOException;  import java.io.InputStream;  import java.io.OutputStream;  import java.net.Socket;    public class ServerThread extends Thread {     public Socket socket;   public InputStream ins;   public OutputStream ous;     public ServerThread(Socket socket) {    this.socket = socket;   }     public void run() {    try {     // 获取输入输出流     ins = socket.getInputStream();     ous = socket.getOutputStream();     // 发送消息给客户端     String msg = "welcome to zhou's server !";     sendMsg(ous, msg);     // 发送要求登录信息给客户端     String userinfo = "please input your name:";     sendMsg(ous, userinfo);     // 获取客户端输入的用户名     String userName = readMsg(ins);     // 发送要求密码信息给客户端     String pwd = "please input your password:";     sendMsg(ous,  pwd);     // 获取客户端输入的密码     String pass = readMsg(ins);     // 登录验证     boolean falg = loginCheck(userName, pass);     // 校验不通过时,循环校验     while (!falg) {      msg = "Fail to connect server......";      sendMsg(ous, msg);      msg = "please check your name and password and login again.....";      sendMsg(ous, msg);      msg = "please input your name:";      sendMsg(ous, msg);      // 获取客户端输入的用户名      userName = readMsg(ins);      // 发送要求密码信息给客户端      msg = "please input your password:";      sendMsg(ous, msg);      // 获取客户端输入的密码      pass = readMsg(ins);      falg = loginCheck(userName, pass);     }       // 校验成功后:开始聊天     msg = "successful connected..... you can chat with your friends now ......";     sendMsg(ous, msg);     // 聊天处理逻辑     //读取客户端发来的消息     msg=readMsg(ins);     //输入bye结束聊天     while(!"bye".equals(msg)){      //给容器中的每个对象转发消息      for (int i = 0; i <Myserver.list.size(); i++) {       ServerThread st =Myserver.list.get(i);       //不该自己转发消息       if(st!=this){        sendMsg(st.ous, userName+"  is say:"+msg);       }      }      //等待读取下一次的消息      msg=readMsg(ins);     }      } catch (Exception e) {     System.out.println("客户端不正常关闭......");  //   e.printStackTrace();    }    //有异常后统一将流关闭    try {     ins.close();     ous.close();     socket.close();     //将当前已经关闭的客户端从容器中移除     Myserver.list.remove(this);    } catch (IOException e) {     // TODO Auto-generated catch block     e.printStackTrace();    }   }     // 校验客户端输入的账号和密码的函数,由于没有数据库,暂时写死了   public boolean loginCheck(String name, String pwd) {    if (name.equals("zhou") && pwd.equals("zhou") || name.equals("user") && pwd.equals("pwd")      || name.equals("huaxinjiaoyu") && pwd.equals("huaxinjiaoyu")) {       return true;    }    return false;   }     // 发送消息的函数   public void sendMsg(OutputStream os, String s) throws IOException {    // 向客户端输出信息    byte[] bytes = s.getBytes();    os.write(bytes);    os.write(13);    os.write(10);    os.flush();     }     // 读取客户端输入数据的函数   public String readMsg(InputStream ins) throws Exception {    // 读取客户端的信息    int value = ins.read();    // 读取整行 读取到回车(13)换行(10)时停止读    String str = "";    while (value != 10) {     // 点击关闭客户端时会返回-1值     if (value == -1) {      throw new Exception();     }     str = str + ((char) value);     value = ins.read();    }    str = str.trim();    return str;   }    }</pre>    <p>函数入口类:</p>    <pre>  package com.huaxin.server;    public class Test {      public static void main(String[] args) {    Myserver ms = new Myserver();    ms.initServer();   }    }</pre>    <h2><strong>四、运行结果:(务必先启动服务器)</strong></h2>    <p>第一次错误是由于未先开启服务器:</p>    <p><strong><img src="https://simg.open-open.com/show/0a157c4d3a27b9b118162b723ea97865.png"> </strong></p>    <p>输入正确的用户名和密码进行登录:</p>    <p><strong><img src="https://simg.open-open.com/show/02cba1cff61ad7c8662aefad8e7bf833.png"> </strong></p>    <p>聊天界面:(中间有一次密码输入错误,但是还是可以再次输入.......)</p>    <p><strong><img src="https://simg.open-open.com/show/766023f46da32b7ecc1c290295a2b657.png"> </strong></p>    <h2>五、总结:</h2>    <p>通过完成这个简单的多人聊天的小程序,有一种说不出来的喜悦感;原来用Java来实现简单的多人聊天这么简单;自己也能写出一个小小的聊天的软件了呢......</p>    <p>接下来我们是不是可以写个山寨版的QQ了呢......哈哈........拭目以待.......</p>    <p> </p>    <p>来自:http://blog.csdn.net/bluesky_usc/article/details/54318498</p>    <p> </p>