国内最全IT社区平台 联系我们 | 收藏本站
华晨云阿里云优惠2
您当前位置:首页 > php开源 > php教程 > Java小程序之简单多人聊天室的实现(山寨QQ前传)

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

来源:程序员人生   发布时间:2017-03-10 10:13:19 阅读次数:4198次

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

1、前言:
通过对Java服务器生猛上手的学习,已基本明白了Java中通讯的基本原理,和服务器,ip,ip地址的概念;
我们思考下服务器究竟是用来干吗的呢?当多台客户端连上服务器以后,服务器需要提供的就是为连接进来的客户端提供相应的服务;具体的来讲就是处理不同客户端发来的消息或数据,然后把这些消息或数据发送到另外的客户端;服务器的目的就是正确转发消息或数据;

2、简单多人聊天室的实现思路:
1、创建服务器等待客户真个连接
2、客户端连接进来以后,获得输入输出流,利用输入输出流发送消息;
3、发送服务器连接成功的信息给客户端,并提示客户端输入账户和密码进行登录
4、服务器接收客户端发来的账号和密码,校验成功后,提示登录成功,开始多人聊天

难点:如何实现多人聊天?定义1个容器:用于封装所有的ServerThread线程对象,遍历该容器中的对象,将消息转发给每个客户端(自己可以除外)

问题:当某个客户端退出后,其他客户端再发消息的时候,转发就会报错;

解决:当有客户端退出时,将该客户端从容器中移除;不在向该客户端转发消息;

3、程序源代码:

连接服务器类:
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("客户端连接进来了......");
				//当有客户端连接进来以后,开启1个线程,用来处理该客户真个逻辑,
				ServerThread st = new ServerThread(socket);
				st.start();
				//添加该客户端到容器中
				list.add(st);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}


服务器线程处理类:
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);
					}
				}
				//等待读取下1次的消息
				msg=readMsg(ins);
			}

		} catch (Exception e) {
			System.out.println("客户端不正常关闭......");
//			e.printStackTrace();
		}
		//有异常后统1将流关闭
		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) {
			// 点击关闭客户端时会返回⑴值
			if (value == ⑴) {
				throw new Exception();
			}
			str = str + ((char) value);
			value = ins.read();
		}
		str = str.trim();
		return str;
	}

}


函数入口类:
package com.huaxin.server;

public class Test {
	
	public static void main(String[] args) {
		Myserver ms = new Myserver();
		ms.initServer();
	}

}


4、运行结果:(务必先启动服务器

第1次毛病是由于未先开启服务器

输入正确的用户名和密码进行登录:

多人聊天界面:(中间有1次密码输入毛病,但是还是可以再次输入.......)


5、总结:
通过完成这个简单的多人聊天的小程序,有1种说不出来的喜悦感;原来用Java来实现简单的多人聊天这么简单;自己也能写出1个小小的聊天的软件了呢......
接下来我们是否是可以写个山寨版的QQ了呢......哈哈........拭目以待.......
共勉!


生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠
程序员人生
------分隔线----------------------------
分享到:
------分隔线----------------------------
关闭
程序员人生