?整个通信过程可以比拟成一个实际的例子,如图
?
?
一个消息从客户端1发送至服务器再从服务器发送回客户端1的过程,通过这个蓄水池的例子可以这样理解:
?
蓄水池1号打开放水闸放水,水通过管道1传送至净水处理器处,净水处理器打开水龙头就能接收到来自蓄水池1号的水,这些水在净水处理器经过处理之后,打开净水处理器的放水闸,经过处理的水通过管道2来到蓄水池1号处,此时蓄水池1号的水龙头打开,便能接收到来自净水处理器的经过处理的水了。
?
在这个例子中,服务器是净水处理器,客户端1就是蓄水池1号,两者都有着向对方发送消息的功能(放水闸)和从对方接收消息的功能(水龙头),水就是传送的信息,放水闸就是输出流,水龙头就是输入流咯。
那么,用代码实现一下这几个东西吧:
?
?????????????? // 建立绑定在指定端口上的服务器对象?
class="java"> //建立一个socket对象(客户机) Socket client = new Socket(this.serverIp, this.port); // 得到输入输出流 InputStream inp = client.getInputStream(); BufferedReader bfr = new BufferedReader(new InputStreamReader(inp)); //使用BufferedReader较直接使用inp更为方便 OutputStream oup = client.getOutputStream();
?聪明的你一定注意到了,服务器还没有输入输出流呢,怎么办?
?
服务器和客户端是不同的,客户端想要传送数据只需要一个水龙头和一个放水闸就够了,但是服务器可能需要同时处理多个客户端的信息,也就是说,这个净水处理器会同时处理许多个蓄水池里的水,那么净水处理器就会需要多个水龙头和放水闸,并且每一个指定的水龙头和放水闸要对应一个指定的蓄水池,并修筑专门对应该蓄水池的管道,这样才不会乱套。而由于一个净水器要对应多个蓄水池,要修筑多条同时使用的管道,这时可以使用线程来作为管道。代码实现如下:
while (true) { // 让服务器进入等待状态:阻塞状态 Socket client = server.accept();//服务器新接收到一个客户端 ConnectThread cot = new ConnectThread(client,this);//新建一个线程,传入新的客户端 arr1.add(cot);//把新建的线程存入线程的队列中 cot.start();//开启线程 }
?
//线程的构造器 public ConnectThread(Socket client, ChatServer cs) throws IOException { this.client = client; //获得输入输出流 inp = client.getInputStream(); oup = client.getOutputStream(); bfr = new BufferedReader(new InputStreamReader(inp)); this.cs = cs; }
?这样,每有一个新的蓄水池连接净水处理器,就会修筑好两者之间的全套设备。
那么接下来就说一下放水和接水的方法:
使用放水闸放水,就是使用OutputStream类的write()方法,
使用水龙头接水就是使用InputStream类的read()方法,
也可以使用BufferedReader类的readLine()方法
需要注意的是
?
?
?该方法读取一句消息时,以"\r","\n"和"\r\n"为标记结尾,也就是每读到这三个标记时自动结束该方法并将其前面的消息记为一句话发送出去,因此使用该方法读取的数据必须是有这三种标记结尾的。
?
知道了这些,就可以实现,从客户机发送给服务器一些数据再从服务器读取出来了,但是要实现真正的通信,是在客户端与客户端之间的。
?
客户端之间聊天的实现
?
客户端通过服务器得到别的客户端所发的消息,继续使用最初的例子就是,蓄水池1可以得到来自蓄水池2的经过净水处理的水。在实例中,我们会这样操作,首先打开蓄水池2的放水闸,净水处理器打开对应蓄水池2的水龙头,净水处理器打开对应蓄水池1的放水闸,蓄水池1打开水龙头。通信也是这样实现的。
?
客户端1,2分别连上客户端之后,客户端2使用OutputStream对象的write()方法通过管道3向服务器写消息,服务器对应客户端2 的线程会使用BufferedReader对象的readLine()方法从客户端2读取消息,再将此消息通过对应客户端1的线程的OutputStream对象的write()方法通过管道2发送给客户端1,客户端1又通过自己的BufferedReader对象的readLine()方法从服务器读取了消息,这样就实现了从客户端2到客户端1的消息传递。
?
?
?