欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

通信之增强版服务器

程序员文章站 2022-06-01 13:20:53
...

        要做通信,当然不能停留在仅满足于实现它,就算我们一时还做不出像腾讯那样强大的qq,但至少我们可以以之为目标并一步一步做下去。

       我们暂且还用命令行的telnet命令充当客户端,那么,就服务器而言, 在服务器的最简代码基础上,我们可添加的内容还有很多。

        最基本的,不能只发字符而不能发送汉字吧;其次,服务器不能只可以连一个客户端吧;然后,客户端是不是要有用户名和密码才能登录呢;至于聊天,客户端之间要可以群聊吧,服务器要可以给每一个客户端发公告吧;最后的最后,是不是应该给服务器加个界面美化一下呢?

        这些功能,虽然看起来还不及qq的万分之一,但如果连这些最基础的模块都没有,如何一步“登上”qq呢?不要去问:以这样的速度什么时候才能做出来山寨qq。这个问题并没有答案,但肯定的是,不是今天,也不是明天。

        那么,现在,就让我们实现这个增强版的服务器。这里我们定义5个类。

        ChatUI:实现服务器界面并启动服务器。

        ChatThread:处理服务器对象的线程类,每一个ChatThread对象对应一个客户机。

        ChatTools:将某个客户机发来的消息发送给其他客户机。

        DaoTools:生成模拟数据,验证客户端账号。

        UserInfo:用户数据类,每个UserInfo对象存放一个用户的账号。

        以下解释几个主要方法。

        首先是用户名验证,我们只简单的验证用户名是否存在,用户名是我们预先存入数据库的:

//验证是否存在该用户名        
public static boolean checkLogin(UserInfo user){
	if(userDB.containsKey(user.getName()))
		return true;
	System.out.println("认证失败"+user.getName());
	return false;
}
//内存用户信息数据库
private static Map<String, UserInfo> userDB = new HashMap();
//静态块:模拟生成内存中的用户数据,用户名为user1~10
//当程序启动时,这段代码(静态块中的)会自动执行,向userDB中存放数据
static{
	for(int i=0;i<10;i++){
		UserInfo user = new UserInfo();
		user.setName("user"+i);
		user.setPassword("password"+i);
		userDB.put(user.getName(), user);
	}
}
        然后是发送群聊消息的方法,我们分为两种,一种是客户端给其他客户端发送的消息,一种是服务器给所有客户端发送的消息,(sendMsg与最简代码发送消息的类似):
public static void castMsg(UserInfo sender,String msg){
	msg = sender.getName()+" say:"+msg;
	for(int i=0;i<stlist.size();i++){
		ChatThread ctt = stlist.get(i);
		//如果客户端的port与自身不同,才发送消息
		if(ctt.getClient() !=sender.getClient()){
			ctt.sendMsg(msg);
		}
	}
}
public static void castMsg(String msg){
	for(int i=0;i<stlist.size();i++){
		ChatThread ctt = stlist.get(i);
	        ctt.sendMsg(msg);
	}
}
         最后,在线程run()方法中读取客户机发来的消息(closeMe是关闭连接的方法):
InputStream ins=client.getInputStream();
out=client.getOutputStream();
//将输入流ins封装为可以读取一行字符串,也就是以\r\n结尾的字符串
BufferedReader brd = new BufferedReader(new InputStreamReader(ins));
sendMsg("欢迎你来聊天!请输入你的用户名:");
String userName = brd.readLine();
sendMsg(userName+"  请输入你的密码:");
String password = brd.readLine();
user = new UserInfo(client);
user.setName(userName);
user.setPassword(password);
//调用数据库模块,验证用户是否存在
boolean loginState = DaoTools.checkLogin(user);
	if(!loginState){//不存在这个用户账号则关闭
		this.closeMe();
		return ;
	}
ChatTools.addClient(this); //认证成功:将这个对象加入服务器队列
String input = brd.readLine();//一行一行的读取客户机发来的消息
if(!"bye".equals(input)){//一直读取
	System.out.println("服务器收到的是: "+input);
	if(runFlag){
		//读到一条消息后,就发送给其他的客户机去...
		ChatTools.castMsg(this.user, input);
		input = brd.readLine();//读取下一条
	}
}
if("bye".equals(input)){
	if(runFlag)
		ChatTools.castMsg(this.user, "我下线了,再见!");
	this.closeMe();
}
         最基本的模块大概就是这样,只要把它们结合起来,就可以实现增强版的服务器了。