⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 0029.htm

📁 Java语言是Internet上最热门的编程语言
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<html>

<head>
<title>新时代软件教程:操作系统 主页制作 服务器 设计软件 网络技术 编程语言 文字编辑</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<style>
<!--
body, table {font-size: 9pt; font-family: 宋体}
a {text-decoration:none}
a:hover {color: red;text-decoration:underline}
.1  {background-color: rgb(245,245,245)}
-->
</style>
</head>
<p align="center"><script src="../../1.js"></script></a>
    <p align="center"><big><strong>用JAVA编制Internet电子白板软件</strong></big></p>

<div align="right">---摘自《计算机世界》(文/刘飞龙)</div>
<h3 align="center"><font size="2">前言</font></h3>

<p><font size="2">  随着Internet的迅速发展,在Email、WWW、FTP等传统的非实时应用日趋成熟的同时,广大网络用户对在线实时交流的需求不断扩大,如网上会议、远程教学、协同工作等。这方面的应用软件也日益丰富起来。该类软件主要分为两类,一种是以目前BBS和主页上的聊天室为代表的纯文字型的交流工具;另一种就是本文要介绍的电子白板类交流工具。电子白板除了具备聊天室的全部功能外,更重要的是,它还引入了绘画图形交流功能,使网上交流的形象性和直观性大大加强了,弥补了文字交流的不足。当分布在Internet不同位置的用户用白板进行交流时,一个人在自己的白板上绘制的图形可以马上在别人的白板上显示出来,好象大家都在同一块白板上绘画,彼此间的距离感大大缩短了。</font></p>

<p><font size="2">  目前具有电子白板功能的软件有微软的Netmeeting等。此类软件在使用前需要用安装盘安装(Netmeeting是Internet 
Explorer 4.0的选装件),在设置完成后才能使用。相比而言,在主页中用Java 
Applet实现白板功能就显得优势很大。因为它不需要传统软件的下载、安装和设置的繁琐步骤,只要用支持JAVA的浏览器连接到该Applet所在主页,就可以使用白板。用于浏览器的普及性(大部分常用浏览器都支持JAVA,如InternetExploer3.0与Netscape 
Navigator 3.0及以上版本)使得这种电子白板的潜在客户群是巨大的。此外,用JAVA编制电子白板软件还有一个显而易见的优势,就是整个软件(尤其是白板服务器)无须重新修改编译就可在NT、Unix、Linux等支持JAVA的平台上运行。</font></p>

<p><font size="2">  目前基于浏览器和JAVA的电子白板正处于起步阶段,笔者尚未在网上看到该类软件。由于工作需要,笔者自行开发了一套此类电子白板软件。这里想将开发中的一些经验介绍给大家,以达到共同交流的目的。</font></p>

<h3 align="center"><font size="2">工作原理</font></h3>

<p><font size="2">  电子白板有两种实现模型,一种是无白板服务器,因此仅支持两个用户直接连结;另一种是有白板服务器,原则上不限制同时上线人数和交谈室个数,具体实现上可视服务器性能和需要而定。本文要介绍属于后者。</font></p>

<p><font size="2">  当用户需用白板与他人交流时,需要先用浏览器连到Applet所在主页,Applet运行后会连接到该白板服务器,和服务器建立TCP连接。每个用户可以在自己的白板上(嵌在Applet画面中)绘制图形和输入文字,Applet会将这些信息通过已建立的网络连接发往白板服务器,并不断侦听、接收来自白板服务器的图形和文字信息,将其再现在用户的白板中。白板服务器的作用是不断侦听、接收来自各Applet的信息,并将其转发给其他用户。</font></p>

<p><font size="2">  由于浏览器对Java Applet的限制,使得Applet只能访问发送该Applet的宿主主机,因此只能在该Applet所在主机上运行白板服务器,使得Applet能建立和远程白板服务器的联系。</font></p>

<h3 align="center"><font size="2">功能设计</font></h3>

<p><font size="2">  一个实用的电子白板系统应该具备以下基本功能:</font>

<ol>
  <li><font size="2">用户在浏览到白板主页时,需登录后才能进行交流。这将提供交流时用的名字,必要时还可做权限检查。<br>
    </font></li>
  <li><font size="2">用户能够根据交谈室的交谈主题选择参加和退出现有的交谈室,并且能建立新的交谈室。可以根据该电子白板系统的应用领域和需要附加一些权限设置。<br>
    </font></li>
  <li><font size="2">用户只能和在同一交谈室中的用户交流。一个交谈室的信息对于别的交谈室是不可见的。<br>
    </font></li>
  <li><font size="2">白板应至少具有一些如更换画笔颜色、清除画板(仅影响自己的白板)等方便用户的功能。<br>
    </font></li>
  <li><font size="2">白板应具有一个操作提示和操作信息反馈栏,对用户显示一些操作提示和操作结果信息,这样可以方便用户使用。<br>
    </font></li>
  <li><font size="2">用户应能暂停和恢复自己的白板工作。</font></li>
</ol>

<p><font size="2">  为了增加白板的实用价值,可以考虑增加如与windows画笔工具类似的画正方形、圆形等类似功能。本例作为电子白板基本模型的建立,故没有加入这些功能。实际上,只要了解了下面要介绍的白板通讯协议集的设计原则,增加以上功能是非常容易的。</font></p>

<h3 align="center"><font size="2">通讯协议集的制定</font></h3>

<p><font size="2">  由于JAVA内置的标准基础通讯协议是TCP/IP,所以我们只需在其基础上建立电子白板的应用层协议集。协议集的模型将采用服务器/客户机的请求/应答模式。可以根据需要实现的白板功能制定通讯协议集,协议集中包括登录、图形传输(分服务器发出和客户机发出两部分)、文字传输(分服务器发出和客户机发出两部分)、服务器要求刷新交谈室及成员名单、客户机要求刷新交谈室及成员名单、加入指定交谈室、退出交谈室、建立新交谈室、暂停/恢复交流等部分。</font></p>

<p><font size="2">  由于已经依靠TCP/IP协议保证数据传输的正确性,所以在这个电子白板的通讯协议集的设计中应在保证功能的前提下尽量简洁,来提高带宽利用率。白板通讯协议集的细节可参考如下:</font></p>

<p><font size="2">  注意:<br>
  (S)表示该部分由服务器发出,客户机接收;<br>
  (C)表示该部分由客户机发出,服务器接收;</font></p>

<p><font size="2">  数据格式表示:引号之间表示字符串,(short)表示短整形数(2字节),(int)表示标准整形数(4字节)。</font>

<ul type="square">
  <li><font size="2">登录(C):&quot;log&quot;→用户名字符串。<br>
    </font></li>
  <li><font size="2">图形传输(客户机发出)(C):&quot;draw&quot;→(int)颜色值→(short)直线起点横坐标→(short)直线起点纵坐标→(short)直线终点横坐标→(short)直线终点纵坐标。<br>
    </font></li>
  <li><font size="2">图形传输(服务器发出)(S):&quot;draw&quot;→(int)颜色值→(short)直线起点横坐标→(short)直线起点纵坐标→(short)直线终点横坐标→(short)直线终点纵坐标。<br>
    </font></li>
  <li><font size="2">文字传输(客户机发出)(C):&quot;text&quot;→用户在白板对话框中输入的文字字符串。<br>
    </font></li>
  <li><font size="2">文字传输(服务器发出)(S):&quot;text&quot;→文字输入者姓名字符串→该用户输入的文字字符串。<br>
    </font></li>
  <li><font size="2">服务器要求刷新交谈室及成员名单(S):&quot;refresh&quot;→交谈室1主题字符串→交谈室1中的用户1姓名字符串→交谈室1中的用户2姓名字符串→...→&quot;complete&quot;→交谈室2主题字符串→交谈室2中的用户1姓名字符串→交谈室2中的用户2姓名字符串→...→&quot;complete&quot;→...→最后一个交谈室主题字符串→最后一个交谈室中的用户1姓名字符串→最后一个交谈室中的用户2姓名字符串→...→&quot;complete&quot;→&quot;ok&quot;。<br>
    </font></li>
  <li><font size="2">客户机要求刷新交谈室及成员名单(C):&quot;refresh&quot;。(服务器收到此命令,会执行前面的服务器要求刷新交谈室及成员名单子协议,以响应客户机请求)<br>
    </font></li>
  <li><font size="2">加入指定交谈室(C):&quot;join&quot;→申请加入的交谈室主题字符串。<br>
    </font></li>
  <li><font size="2">退出交谈室(C):&quot;quit&quot;。<br>
    </font></li>
  <li><font size="2">建立新交谈室(C):&quot;new&quot;→申请建立的新交谈室主题字符串。(服务器收到此命令,会自动在该用户原来所在的交谈室中注销,并使该用户成为新交谈室的一员)<br>
    </font></li>
  <li><font size="2">暂停交流(C):&quot;pause&quot;。<br>
    </font></li>
  <li><font size="2">恢复交流(C):&quot;continue&quot;。</font></li>
</ul>

<p><font size="2">  以上为本电子白板软件所遵循的通讯协议集。这个协议集的可扩充性很强,可以随时按增加的功能扩充协议集。例如需要传送圆形图案,则可将如下协议加到协议集中:&quot;circle&quot;→(int)颜色值→(short)圆心横坐标→(short)圆心纵坐标→(short)圆半径。</font></p>

<h3 align="center"><font size="2">编程实现</font></h3>

<p><font size="2">  程序设计分服务器JAVA Application和客户端Java 
Applet两部分进行。</font></p>

<p><font size="2">  编程中需要注意以下几点:</font>

<ol>
  <li><font size="2">服务器程序不要采用客户端接入时建立用户线程,退出交谈室时销毁线程的工作流程。因为有些操作系统的线程操作机制不够健全,在线程销毁时线程所占资源不能被完全释放,以致于在白板服务器运行的过程中将逐渐消耗掉系统资源。所以应在服务器初始化时按照最大允许同时上线的用户数建立所有用户服务线程。这些线程将等待客户端接入,当用户退出交谈室时线程并不销毁,而是清除用户数据,重新进入等待接入状态,准备为下一个用户服务。这样就保证了白板服务器可以长期可靠运行。<br>
    </font></li>
  <li><font size="2">当用户在白板上连续绘画时可能产生大量的图形数据,客户端Applet若在白板的AWT事件处理程序中完成将这些数据传输给服务器的任务,则很有可能由于网络I/O的瓶颈作用,使得AWT事件处理线程受阻,从而影响白板Applet、浏览器、其他正在运行的应用软件的界面相应性。解决的办法就是使Applet再建立一个后台绘图数据传输线程,白板的AWT事件处理程序将用户的绘图数据通过管道流(PipedStream)传输给这个线程后就返回,把网络传输的任务留给这个线程进行。<br>
    </font></li>
  <li><font size="2">在服务器和客户端Applet中,协议集每一个子协议的实现都要分别建立一个同步块(synchronize),该子协议的全部操作都要在这个同步块内完成,以限制自由访问网络接插建立的输入流和输出流。使得当一个线程执行一个子协议时能够独占这些网络资源,而使别的线程不能访问这些资源,以保证线程能够完整正确地执行子协议。但是由于同步操作会降低线程调度和执行效率,所以要在确保子协议完整执行的前提下尽量缩小同步代码块的范围。<br>
    </font></li>
  <li><font size="2">由于协议集中的数据类型既有字符串又有整形数,因此在程序中选用DataInputStream和DataOutputStream作为数据输入流和输出流。此外,由于UTF格式的文本支持中文字符集,且在字符串中已包含长度信息,可以方便数据读取,故在本程序的网络通信中的字符串全部采用UTF格式。设计自己的白板程序时,可以根据需要换用其他文本格式和编码规则,但一定要保证输入流和输出流采用的是同一种格式和编码。<br>
    </font></li>
  <li><font size="2">考虑到目前Netscape Navigator 3.0和Internet Explorer 
    3.0目前仍普遍使用,而这两种浏览器的JAVA虚拟机都不支持较新的JDK1.1标准,所以在本程序的客户机Applet部分中没有使用JDK1.1特有的类库。</font></li>
</ol>

<p><font size="2">  首先介绍服务器程序的编制。需确定主要的几个类及其成员函数。列表如下:</font>

<ul type="square">
  <li><font size="2">ChatServer类:服务器程序的启动类。<br>
    </font></li>
  <li><font size="2">ChatServer():建立服务器管理界面。<br>
    </font></li>
  <li><font size="2">initServer():建立服务器插结,初始化交谈室数据,按照允许同时上线的最大用户数建立多个用户服务线程。<br>
    </font></li>
  <li><font size="2">go():启动用户服务线程。<br>
    </font></li>
  <li><font size="2">quit():中止用户服务线程,关闭服务器插结,并释放全部资源。<br>
    </font></li>
  <li><font size="2">User类:为Thread类的子类,实现用户服务线程,处理服务器/客户机会话。<br>
    </font></li>
  <li><font size="2">run():等待客户端接入;客户端接入后初始化网络资源,进入循环侦听客户端请求的状态,并根据客户端的请求调用相应的协议处理程序。<br>
    </font></li>
  <li><font size="2">sendText():按照文字传输子协议,接收用户发出的文字信息,并转发给同一交谈室的其他用户。<br>
    </font></li>
  <li><font size="2">sendDraw():按照图形传输子协议,接收用户发出的图形信息,并转发给同一交谈室的其他用户。<br>
    </font></li>
  <li><font size="2">commandCenter():为服务器接收到的指令选择运行适当的处理程序。<br>
    </font></li>
  <li><font size="2">server_ask_refresh():服务器主动刷新交谈室及成员名单。<br>
    </font></li>
  <li><font size="2">server_answer_reresh():响应客户机要求刷新交谈室及成员名单。<br>
    </font></li>
  <li><font size="2">server_answer_log():响应客户机登录。<br>
    </font></li>
  <li><font size="2">server_answer_join():响应用户加入指定交谈室请求。<br>
    </font></li>
  <li><font size="2">server_answer_pause():响应用户暂停交流请求。<br>
    </font></li>
  <li><font size="2">server_answer_continue():响应用户恢复交流请求。<br>
    </font></li>
  <li><font size="2">server_answer_newRoom():响应用户建立新交谈室请求。<br>
    </font></li>
  <li><font size="2">server_answer_quit():响应用户退出交谈室请求。<br>
    </font></li>
  <li><font size="2">server_ask_text():服务器向客户机转发文字信息。<br>
    </font></li>
  <li><font size="2">server_ask_draw():服务器向客户机转发图形信息。<br>
    </font></li>
  <li><font size="2">refreshToAll():服务器刷新所有在线客户端的交谈室数据。<br>
    </font></li>
  <li><font size="2">refreshToAllNotMe():服务器刷新除该用户外,所有在线客户端的交谈室数据。<br>
    </font></li>
  <li><font size="2">socketClose():用户申请退出时调用,关闭网络插结,释放线程占用的网络资源。<br>
    </font></li>
  <li><font size="2">RoomGroup类:保存所有交谈室数据,直接处理与交谈室有关操作。<br>
    </font></li>
  <li><font size="2">newRoom():建立新交谈室。<br>
    </font></li>
  <li><font size="2">join():加入指定交谈室。<br>
    </font></li>
  <li><font size="2">quit():退出指定交谈室。<br>
    </font></li>
  <li><font size="2">getUsersName():返回指定交谈室内的用户名。<br>
    </font></li>
  <li><font size="2">getRoomID():按照交谈室主题查询并返回交谈室ID号。<br>
    </font></li>
  <li><font size="2">Room类:保存并处理本交谈室用户数据。<br>
    </font></li>
  <li><font size="2">join():加入本交谈室。<br>
    </font></li>
  <li><font size="2">quit():退出本交谈室。<br>
    </font></li>
  <li><font size="2">getUsersName():返回本交谈室的用户名。<br>
    </font></li>
  <li><font size="2">DataBag类:包装图形和文字数据。<br>
    </font></li>
  <li><font size="2">AboutDialog类:生成About对话框,可显示版权信息。<br>
    </font></li>
  <li><font size="2">QuitDialog类:生成QuitDialog对话框,用于确认是否结束服务器运行。</font></li>
</ul>

<p><font size="2">  客户机Applet包含的类及其主要成员函数如下:</font>

<ul type="square">
  <p><font size="2">ChatApplet类:为Applet类的子类,实现Runnable接口。是白板Applet的核心类,完成与用户交流和与服务器通讯的任务。<br>
  </font></p>
  <li><font size="2">init():初始化Applet用户界面。<br>
    </font></li>
  <li><font size="2">run()::循环侦听来自白板服务器的信息,调用commandCenter命令处理程序。<br>
    </font></li>
  <li><font size="2">start():生成并启动Applet线程。<br>
    </font></li>
  <li><font size="2">stop():中止Applet线程。<br>
    </font></li>
  <li><font size="2">destroy():中止后台图形数据传送线程,调用关闭网络资源函数。<br>
    </font></li>
  <li><font size="2">socketClose():关闭所有打开的网络插结和通讯流。<br>
    </font></li>
  <li><font size="2">openSocket():建立网络插结和通讯流。<br>
    </font></li>
  <li><font size="2">commandCenter():集中处理来自用户和服务器以及来自Applet内部的命令,调用相应的处理程序。<br>
    </font></li>
  <li><font size="2">client_ask_refresh():客户机请求刷新交谈室数据。<br>
    </font></li>
  <li><font size="2">client_answer_refresh():客户机接收服务器发送的交谈室数据。<br>
    </font></li>
  <li><font size="2">client_ask_log():申请登录到服务器。<br>
    </font></li>
  <li><font size="2">client_ask_join():申请加入指定交谈室。<br>
    </font></li>
  <li><font size="2">client_ask_pause():暂停交流。<br>
    </font></li>
  <li><font size="2">client_ask_continue():恢复交流。<br>
    </font></li>
  <li><font size="2">client_ask_newRoom():申请建立新交谈室。<br>
    </font></li>
  <li><font size="2">client_ask_quit():退出交谈室。<br>
    </font></li>
  <li><font size="2">client_ask_text():发送用户输入的文字信息。<br>
    </font></li>
  <li><font size="2">client_answer_text():接收服务器转发的其他用户的文字信息。<br>
    </font></li>
  <li><font size="2">client_answer_draw():接收服务器转发的其他用户的图形信息。<br>
    </font></li>
  <li><font size="2">refreshRoomList():显示交谈室列表。<br>
    </font></li>
  <li><font size="2">refreshUserList():显示指定交谈室中的用户列表。<br>
    </font></li>
  <li><font size="2">printChat_Area():将该用户和来自服务器的其他用户的输入的文字用指定格式显示在Applet的交谈文本框中。<br>
    </font></li>
  <li><font size="2">sendText():判断用户输入的文字是否为有效字符串,若有效则调用发送文字函数。<br>
    </font></li>
  <li><font size="2">drawBoard_Canvas():按DataBag对象的值,在Applet的白板上绘图。<br>
    </font></li>
  <li><font size="2">boardCanvas_MouseDrag():当鼠标在白板上拖动时调用此函数,将鼠标轨迹包装成数据包发送给后台网络传输线程。<br>
    </font></li>
  <li><font size="2">logButton_Clicked():当用户单击Applet的登录钮时调用此函数,建立网络插结和后台网络传输线程。<br>
    </font></li>
  <li><font size="2">其他一系列用户界面事件处理函数:与用户交流,接收用户输入,直接处理或调用commanCenter函数执行用户命令。<br>
    </font></li>
  <li><font size="2">RoomData类:存储该交谈室的主题和用户名的数据类<br>
    </font></li>
  <li><font size="2">addUser():在该交谈室中添加用户名。<br>
    </font></li>
  <li><font size="2">removeUser():在该交谈室中删除用户名。<br>
    </font></li>
  <li><font size="2">getUsersName():返回所有在该交谈室中的用户名。<br>
    </font></li>
  <li><font size="2">Rooms类:为Vector类的子类。存储所有交谈室的用户数据。<br>
    </font></li>
  <li><font size="2">getRoomByName():按交谈室主题返回指定交谈室的RoomData对象。<br>
    </font></li>
  <li><font size="2">addElement():添加RoomData对象。<br>
    </font></li>
  <li><font size="2">SendDrawData类:为Thread类的子类,实现后台网络传输线程。<br>
    </font></li>
  <li><font size="2">run():循环侦听来自Applet主线程的图形信息,并将其通过网络接插生成的输出流发送给服务器。<br>
    </font></li>
  <li><font size="2">quit():关闭该线程与Applet主线程的连接流。<br>
    </font></li>
  <li><font size="2">Logo类:为Canvas类的子类。用于在Applet中显示图标或版权信息。</font></li>
</ul>

<p><font size="2">  此外程序中还定义了几个异常类,可以方便程序的异常处理机制设计,增加程序的可维护性和可读性。Applet徽标的默认图形文件名是&quot;cdownlogo.jpg&quot;(457×60),服务器像标的默认图形文件名是&quot;icon.gif&quot;(19×17)。服务器默认占用的端口号为10000。以上各项可以视需要修改。</font></p>

<h3 align="center"><font size="2">结论</font></h3>

<p><font size="2">  本文结合笔者的编程经验初步介绍了基于浏览器和JAVA的电子白板软件的程序设计过程,希望这些内容能够对广大软件开发人员有所帮助。欢迎大家与笔者联系(lfl@cenpok.net),就电子白板的一些问题进行切磋和交流。</font></p>

<h3 align="center"><font size="2">附录内容:</font></h3>

<ol>
  <li><font size="2">本电子白板系统的完整源程序。已测试通过,可以直接编译运行。<br>
    </font></li>
  <li><font size="2">嵌入Applet的主页示范。请注意主页中Applet的参数设置。<br>
    </font></li>
  <li><font size="2">本电子白板客户端Applet的用户界面及操作方法简介。</font></li>
</ol>

<h3 align="center"><font size="2">附录1:源程序:</font></h3>

<p><font color="#800000">import java.net.*;<br>
import java.io.*;<br>
import java.awt.*;<br>
import java.util.*;<br>
import java.applet.*;<br>
<br>
// class 1:server main class,服务器启动类<br>
public class ChatServer extends Frame {<br>
<br>
final static int DEFAULT_USERCOUNT=30;<br>
final static int DEFAULT_PORT=10000;<br>
final static String ICON_FILE=&quot;icon.gif&quot;;<br>
int num_Line=0;<br>
User[] users=null;<br>
ServerSocket ss=null;<br>
RoomGroup roomGroup=null;<br>
int port=DEFAULT_PORT;<br>
Image icon=null;<br>
<br>
java.awt.TextArea message_TextArea;<br>
java.awt.List users_List;<br>
java.awt.Choice room_Choice;<br>
java.awt.Label message_Label;<br>
java.awt.Label room_Label;<br>
java.awt.Label userList_Label;<br>
java.awt.Button clean_Button;<br>
<br>
java.awt.MenuBar mainMenuBar;<br>
java.awt.Menu menu1;<br>
java.awt.Menu menu3;<br>
<br>
void initServer(int port) throws IOException {<br>
users=new User[ChatServer.DEFAULT_USERCOUNT];<br>
roomGroup=new RoomGroup(ChatServer.DEFAULT_USERCOUNT,room_Choice,<br>
this);<br>
try{<br>
ss=new ServerSocket(port,5);<br>
message_TextArea.appendText(&quot;\nserver socket init successed&quot;);<br>
<br>
}catch(Exception e){<br>
System.out.println(e);<br>
message_TextArea.appendText(&quot;\nserver socket init error&quot;+e);<br>
}<br>
for(int i=0;i&lt; users.length;i++) {<br>
users[i]=new User(this,i);<br>
}<br>
roomGroup.setUsers(users);<br>
show();<br>
go();<br>
message_TextArea.appendText(&quot;\nserver started&quot;);<br>
<br>
}<br>
<br>
ChatServer(int port) throws IOException {<br>
<br>
icon=getToolkit().getImage(ICON_FILE);<br>
MediaTracker tracker = new MediaTracker(this);<br>
tracker.addImage(icon,0);<br>
try{<br>
tracker.waitForAll();<br>
}catch(Exception e){<br>
System.out.println(e);<br>
}<br>
//{{INIT_CONTROLS<br>
setLayout(null);<br>
addNotify();<br>
resize(insets().left + insets().right + 544,<br>
insets().top + insets().bottom + 355);<br>
//$$ openFileDialog1.move(36,276);<br>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -