Windows下TightVNC Server Web服务源码分析

使用TightVNC一段时间后,一直好奇它是如何实现用浏览器访问服务器端,今天就分析一下它的技术原理。用任一浏览器访问一台服务器例如http://192.168.1.102:5800,等其加载完后查看网页源文件可以看到下面的HTML代码:

<HTML>

<HEAD><TITLE>TightVNC desktop [jujumao]</TITLE></HEAD>

<BODY>

     <APPLET CODE=VncViewer.class ARCHIVE=VncViewer.jar WIDTH=1280 HEIGHT=1056>

       <PARAM NAME="PORT" VALUE="5900">

     </APPLET><BR>

     <A HREF="http://www.tightvnc.com/">www.TightVNC.com</A>

</BODY>

</HTML>

代码很简单,稍微阅读一下就可知道它其实是通过JAVA的APPLET小程序来实现用浏览器服务器的,而且可以知道运行的是VncViewer.jar,入口在VncViewer.class,启动时向服务器传递一个参数PORT,值是5900。5900是默认服务器监听的端口,VncViewer客户端 就是通过这个端口连接服务器的。这样我们就可以大概知道:客户端用浏览器访问服务器5800端口,服务器接收到请求后返回上面的HTML代码,这样浏览器就开始执行这段HTML代码,代码中有APPLET标签,最后运行的就是从服务器下载的VncViewer.jar这个文件来实现跟服务器之间的控制。本人利用一些HTTP协议的数据包截取工具发现,从访问到可以用浏览器进行控制的全过程,只有两次的HTTP请求,在进行控制的时候并没有发生HTTP协议数据包,即可从其表现上判定,实质是运行VncViewer.jar来实现对服务器的控制的。

然而实际的源码是否也如猜测一样?打开TightVNC源码工程,找到vncServer类,里面有一个使用启用HTTP服务器的函数:

vncServer::SetHttpdEnabled(BOOL enable_httpd, BOOL enable_params)

{

if (enable_httpd != m_httpd_enabled) {

m_httpd_enabled = enable_httpd;

m_httpd_params_enabled = enable_params;

BOOL socketConn = SockConnected();

SockConnect(FALSE);

SockConnect(socketConn);

} else {

if (enable_params != m_httpd_params_enabled) {

m_httpd_params_enabled = enable_params;

if (SockConnected()) {

SockConnect(FALSE);

SockConnect(TRUE);

}

}

}

return TRUE;

}

更看SockConnect函数中启动HTTP服务器的代码:

             if (m_httpConn == NULL && m_httpd_enabled && m_port_http != m_port) {

m_httpConn = new vncHTTPConnect;

if (m_httpConn != NULL) {

// Start up the HTTP server

if (!m_httpConn->Init(this, m_port_http,

   m_httpd_params_enabled)) {

delete m_httpConn;

m_httpConn = NULL;

return FALSE;

}

}

}

这里的m_httpConn是一个vncHTTPConnect类,它的Init函数其实是启动了一个连接的vncSockConnectThread线程,而实际最后运行HTTP协议的代码在它run函数中的DOHTTP函数中// Code to be executed by the thread

void vncHTTPConnectThread::run(void *arg)

{

vnclog.Print(LL_INTINFO, VNCLOG("started HTTP client thread\n"));

// Perform the transaction

DoHTTP(m_socket);

// And close the client

delete m_socket;

vnclog.Print(LL_INTINFO, VNCLOG("quitting HTTP client thread\n"));

}

DOHTTP函数对浏览的HTTP请求作解析

// Switch, dependent upon the filename:

if (filename[1] == '\0' || (m_allow_params && filename[1] == '?'))

如果是没有参数或有参数就进行解析,并发送HTTP代码,如下:

// Send the java applet page

sprintf(indexpage, HTTP_FMT_INDEX,

desktopname, width, height+32, m_server->GetPort(), params);

HTTP_FMT_INDEX定义如下:

const char HTTP_FMT_INDEX[] =

"<HTML>\n"

"   <HEAD><TITLE>TightVNC desktop [%.256s]</TITLE></HEAD>\n"

"   <BODY>\n"

"     <APPLET CODE=VncViewer.class ARCHIVE=VncViewer.jar WIDTH=%d HEIGHT=%d>\n"

"       <PARAM NAME=\"PORT\" VALUE=\"%d\">\n"

"%.1024s"

"     </APPLET><BR>\n"

"     <A HREF=\"http://www.tightvnc.com/\">www.TightVNC.com</A>\n"

"   </BODY>\n"

"</HTML>\n";

其他情况就传输资源文件中编译的文件。

// Now search the mappings for the desired file

for (int x=0; x < filemappingsize; x++)

打开工程文件的资源文件可以发现VncViewer.jar和.class文件都被编译在了WinVncServer.exe里面去了。

你可能感兴趣的:(windows,server,服务器,HTTP服务器,web服务,applet)