服务器负责各种资源的统一管理,而客户端则是各种为用户进行各种服务的地方,用户的各种请求都是在客户端进行真正的处理。而客户端在计算完毕以后要输出结果则必须通过服务器进行。客户端到服务器的请求是表现为QWSCommand的实例,数据通道仍然是Unix域socket。下图列出了客户端到服务器的所有请求,这些请求大部分是使用Qt开发的程序员无须知道的,在移植Qt的过程中也无需做任何改动。
客户端到服务器的通信过程同服务器到客户端的通信一样,首先是串行化,通过socket发送,到了服务器端,服务器再反串行化得到QWSCommand的实例。读者可能注意到QWSCommand和QWSEvent都是继承与QWSProtocolItem,实际上串行化的工作由QWSProtocolItem提供,而QWSCommand的子类使用它提供的函数将自己特定的数据串行化。下面给出了QWSCommand的原型,结构非常简单,主要是定义了Command的类型以及制造Command的工厂函数,这里的factory和前面讲到的QWSEvent方式是一样的,就不赘述了。
struct QWSCommand : QWSProtocolItem
{
QWSCommand(int t, int len, char *ptr) : QWSProtocolItem(t,len,ptr) {}
enum Type {
Unknown = 0,
……
GrabMouse,
……
};
static QWSCommand *factory(int type);
};
接下来我们以QWSGrabMouseCommand为例来讲解客户端到服务器的请求的传递过程,流程图见下图。
QWSGrabMouseCommand是客户端想独自占有鼠标时发出的请求。windowid是Qt内部表示的窗口ID,每一个command都包含该id。grab如果为true表示请求占有鼠标,为false则表示请求释放鼠标,下面给出了QWSGrabMouseCommand的原型。
struct QWSGrabMouseCommand : public QWSCommand
{
QWSGrabMouseCommand() :
QWSCommand(QWSCommand::GrabMouse,
sizeof(simpleData), reinterpret_cast<char *>(&simpleData)) {}
struct SimpleData {
int windowid;
bool grab; // grab or ungrab?
} simpleData;
};
服务器在检测到与客户端的连接有数据到来以后需要首先反串行化,然后依据具体的请求做出相应的处理。具体流程见下图: