群聊服务器
群聊服务器要将所有连接到服务器上的客户端对象都集中到一起(比如一个队列)来处理,将其中每个对象发送的消息转发给其他所有连接的客户端,并且在有新连接加入时对其他的连接的客户端进行通知等等功能。所以需要编写几个类来分别实现这些功能。每个类的功能要尽量的单一,这样便于调试。
服务器增加了验证登陆信息、转发消息等多个功能,也就需要增加几个类来辅助。首先对于登陆用户来说,需要验证其用户名和密码,创建一个DaoTools类:负责验证用户名和密码是否正确。验证用户信息的过程可以首先模拟一个数据库,用一个map存储用户名和对应的用户信息,在运行到验证模块前就将设置好的数据存入MAP,验证时,通过用户名得到对应的用户类,也就得到了该用户密码,验证是否符合。因此,也就需要创建一个用户信息类,其中存储用户名,密码以及以后可能用到的IP地址、登录时间等等信息。转发消息作为另外一个独立功能,也需要建立一个辅助类,其中放置通知上下线以及转发消息的方法。因为上线用户个数不定,可用一个队列来存放客户端处理线程类每增加一个客户连入,则启动一个处理线程,加入到队列中,而当前在线人数就是该队列的长度。转发消息则只要遍历队列,发送消息即可达成。
综上,总共需要设置五个类:
ChatServer类:创建服务器并等待连结。
ServerThread类:处理连结的线程类,读取客户端输入流并发送给客户端。
UserInfo类:用户信息类,存放用户属性。
DaoTools类:一个辅助类,使用时并不需要创建对象,直接调用其中存放的方法就好,因此其中的方法都是static方法。这个类中存放的是验证用户登录的方法。
ChatTools类:同样不需要创建对象,是一个辅助方法,转发客户机发送的消息,并有将新上线的用户即一个线程加入队列或者下线用户移除队列的方法。
这里列出DaoTools类的代码,因为其中使用了静态块的方法。静态块是在类被加载之时就优先执行的代码,所以在验证用户信息之时,就不会出现map中无数据的情况。
package Server1;
import java.util.HashMap;
/**
* 系统数据访问操作实现类
* 帐号验证,数据保存,更改……
* @author Administrator
*
*/
public class DaoTool {
/**
* 查看这个用户是否可以登录成功
* @param user:要检查的用户对象
* @return:是否成功登录
*/
public static boolean checkLogin(UserInfo user){
//在此只验证用户名是否存在
if(userDB.containsKey(user.getName())){
return true;
}
System.out.println("认证失败!:"+user.getName());
return false;
}
//内存用户信息数据库
private static java.util.Map<String, UserInfo> userDB = new HashMap<String, UserInfo>();
//静态块:模拟生成内存中的用户数据,用户名为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);
}
}
}
简单客户端
简单客户端与服务器类似,不过客户端不是要开放端口来等待连接,而是要知道服务器的IP和端口去连接。客户端对象是Socket类的对象,在创建时即要指定要连接的服务器的IP和端口。
Socket client = new Socket("ip",port);
其中ip是一个代表地址的字符串,port则是一个int值。
与服务器存在同样的问题,所以这条语句也需要try catch(当然throws也可以)。
之后从这个Socket对象上取得输入输出流就可以与服务器进行通信了。当然,通信还是要按照一定的协议,这样双方才能够互相理解对方在说什么!