基于上一篇文章,现在来实现一个简单的聊天室,就是服务器和客户机之间能够进行文字交流。想一下,既然是聊天室,那么就会有很多人,服务器如何去处理很多客户的连接,将在接下来的代码中进行讲解
因为客户机没有牵扯到多对一的问题,就先从客户端上手吧
一、客户端
客户端由三个类构成,既然是聊天室,单独用一个类去创建窗口,另外一个类处理网络通信,再单独弄一个登陆的窗口总之就是,尽量做到一个类只去处理一件事情或者一类事情。
通信类
public class SocketDemo extends Thread(){
private DataInputStream dips;
private DataOutputStream dops;
private String userName;
private JTextArea jta;//客户端界面上的用来接收服务器发来消息的文本框
public SocketDemo(JTextArea jta,String userName) {
this.jta = jta;
this.userName = userName;
}
//这一部分的代码在上一篇文章中有讲解过
//判断客户机是否与服务器连接上,用布尔型做标记,置于窗口类中使用
public boolean isConnected(){
try {
Socket client = new Socket("127.0.0.1",8888);
System.out.println("客户机与服务器连接成功");
InputStream ips = client.getInputStream();
OutputStream ops =client.getOutputStream();
//如果使用上面的输入输出流,在读取超过字节的范围的数据,会造成数据丢失。所以使用到下面两个输入输出流来保证传输数据的一致性
dips = new DataInputStream(ips);
dops = new DataOutputStream(ops);
return true;
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
}
//在上一篇博客中说到,客户机与服务器的数据交换要基于一定的协议,用来判断这一段数据是什么东西
//向服务器发送消息的方法
public void senMessage(String Message){
try{
String a = userName+":"+"Message";
dops.writeByte(3);//用字节3来表示接下来的数据是文本消息
byte[] data = a.getBytes();
int length = data.length;
dops.writeInt(length);//第二个数据,消息的字节长度
dops.write(data);//第三个数据,消息内容
dops.flush();
System.out.println("客户机发送消息成功");
jta.append(a+"\r\n");
}catch(IOException e){
e.printStackTrace();
System.out.println("客户机发送消息失败");
}
}
/*
* 1.客户机的read方法若没有收到服务器发来的消息,会一直阻塞,所以将其放在线程中更好
* 2.先读取数据
* 3.显示到文本框中
* 4.自定义协议:文本消息数据包:第一个数据:字节3(用来判断是文本消息)
* 第二个:int型,这次消息的字节长度
* 第三个:文本消息的内容
*/
public void run() {
while(true) {
try {
byte type = dips.readByte();//第一个数据,和发送消息的方法一样,用来标记
if(type == 3) {
int length = dips.readInt();//第二个,收到消息的字节长度
byte[] data = new byte[length];