问题3:客户端是怎样获取服务端的返回数据的?
我们再回顾一下代码六吧。代码六中,当连接建立时会启动一个线程用于处理服务端返回的数据,我们看看这个处理线程是怎么实现的吧,下面贴出Client.Connection类和Client.Call类中的相关方法吧:
代码九:
方法一: public void run() { ??? while (waitForWork()) { receiveResponse(); //具体的处理方法 } close(); ??? } 方法二: private void receiveResponse() { if (shouldCloseConnection.get()) { return; } touch(); try { int id = in.readInt(); // 阻塞读取id if (LOG.isDebugEnabled()) LOG.debug(getName() + " got value #" + id); Call call = calls.get(id); //在calls池中找到发送时的那个对象 int state = in.readInt(); // 阻塞读取call对象的状态 if (state == Status.SUCCESS.state) { Writable value = ReflectionUtils.newInstance(valueClass, conf); value.readFields(in); // 读取数据 //将读取到的值赋给call对象,同时唤醒Client等待线程,贴出setValue()代码方法三 call.setValue(value); calls.remove(id); //删除已处理的call } else if (state == Status.ERROR.state) { ??? } else if (state == Status.FATAL.state) { ??? } } catch (IOException e) { markClosed(e); } } 方法三: public synchronized void setValue(Writable value) { this.value = value; callComplete(); //具体实现 } protected synchronized void callComplete() { this.done = true; notify(); // 唤醒client等待线程 }代码九完成的功能主要是:启动一个处理线程,读取从服务端传来的call对象,将call对象读取完毕后,唤醒client处理线程。就这么简单,客户端就获取了服务端返回的数据了哦~。客户端的源码分析就到这里了哦,下面我们来分析Server端的源码吧。