2. 使用stop方法强行终止线程(这个方法不推荐使用,因为stop和suspend、resume一样,也可能发生不可预料的结果)。
3. 使用interrupt方法中断线程。
1. 使用退出标志终止李团线程
当run方法执行完后,线程就会退出。但有时run方法是永远不会结束的。如在服务端程序中使用线程进行监听客户端请求,或是其他的需要循环处理的任务。在这种情况下,一般是将这些任务放在一个循环中,如while循环。如果想让循环永远运行下去,可以使用while(true){……}来处理。但要想使while循环在某一特定条件下退出,最直接的方法就是设一个boolean类型的标志,并通过设置这个标志为true或false来控制while循环是否退出。下面给出了一个利用退出标志终止线程的例子。
package chapter2
public class ThreadFlag extends Thread
{
public volatile boolean exit = false
public void run()
{
while (!exit)
}
public static void main(String[] args) throws Exception
{
ThreadFlag thread = new ThreadFlag()
thread.start()
sleep(5000)// 主线程延迟5秒
thread.exit = true // 终止线程thread
thread.join()
System.out.println("线程退出!")
}
}
在上面代码盯扰没中定义了一个退出标志exit,当exit为true时,while循环退出,exit的默认值为false.在定义exit时,使用了一个Java关键字volatile,这个关键字的目的是使exit同步,也就是说在同一时刻只能由一个线程来修改exit的值,
2. 使用stop方法终止线程
使用stop方法可以强行终止正在运行或挂起的凯纳线程。我们可以使用如下的代码来终止线程:
thread.stop()
虽然使用上面的代码可以终止线程,但使用stop方法是很危险的,就象突然关闭计算机电源,而不是按正常程序关机一样,可能会产生不可预料的结果,因此,并不推荐使用stop方法来终止线程。
3. 使用interrupt方法终止线程
使用interrupt方法来终端线程可分为两种情况:
(1)线程处于阻塞状态,如使用了sleep方法。
(2)使用while(!isInterrupted()){……}来判断线程是否被中断。
在第一种情况下使用interrupt方法,sleep方法将抛出一个InterruptedException例外,而在第二种情况下线程将直接退出。下面的代码演示了在第一种情况下使用interrupt方法。
package chapter2
public class ThreadInterrupt extends Thread
{
public void run()
{
try
{
sleep(50000) // 延迟50秒
}
catch (InterruptedException e)
{
System.out.println(e.getMessage())
}
}
public static void main(String[] args) throws Exception
{
Thread thread = new ThreadInterrupt()
thread.start()
System.out.println("在50秒之内按任意键中断线程!")
System.in.read()
thread.interrupt()
thread.join()
System.out.println("线程已经退出!")
}
}
上面代码的运行结果如下:
在50秒之内按任意键中断线程!
sleep interrupted
线程已经退出!
在调用interrupt方法后, sleep方法抛出异常,然后输出错误信息:sleep interrupted.
注意:在Thread类中有两个方法可以判断线程是否通过interrupt方法被终止。一个是静态的方法interrupted(),一个是非静态的方法isInterrupted(),这两个方法的区别是interrupted用来判断当前线是否被中断,而isInterrupted可以用来判断其他线程是否被中断。因此,while (!isInterrupted())也可以换成while (!Thread.interrupted())。
关于消息循环:1,我们站在一个什么高度看消息循环?消息循环其实没有什么深奥的道理。如果一个邮递员要不断在一个城市中送信,我们要求他做什么?要求他来回跑,但他一次只能在一个地方出现。如果我们的应用程序只有一个线程的话,我们要他不断地为窗口传递消息,我们怎么做?在一个循环中不断的检测消息,并将他发送到适当的窗口。窗口可以有很多个,但消息循环只有一个,而且每时每刻最多只有一个地方在执行代码。为什么? 看第二点。
2,因为是单线程的(程序进程启动的时候,只有而且有一个线程,我们称他为主线程),所以就像邮递员一样,每次只能在某一个地方干活。什么意思呢?举个例子,用::DiapatchMessage派送消息,在窗口处理过橘冲清程(WinProc,窗口函数)返回之前,他是阻塞的,不会立即返回,也就是消息循环此时不能再从消息队列中读取消息,直到::DispatchMessage返回。如果你在窗口函数中执行一个死循环 *** 作,就算你用PostQuitMessage函数退出,程序也会down掉。
while(1)
{
PostQuitMessage(0)//程序照样down.
}
所以,当窗口函数处理没有返回的时候,消息循环是不会从消息队列中读取消息的。这也是为什么在模式对话框中要自己用无限循环来继续消息循环,因为这个无限循环阻塞了原来的消息循环,所以,在这个无限循环中要用GetMessage,PeekMessage,DispatchMessage来从消息队列中读取消息并派送消息了。要不然程序就不会响应了,这不是我们所希望的。
以说,消息循环放在程序的什么的地方都基本上是过的去的,比如放在DLL里面。但是,最好在任何时候,只有一个消息循环在工作(其他的都被阻塞了)。然后,我们要作好的一件事情,就是怎么从消息循环中退出!当然用WM_QUIT是可以拉~(PostThreadMessage也是个好主意),这个消息循环退出后,可能程序退出,也可能会激活另外一个被阻塞的消息循环,程序继续运行。这要看你怎么想,怎么去做。最后一个消息循环结束的时候,也许就是程序快结束的时候,因为主线程的执行代码也快要完了(除非BT的再作个死循环)。
NOTE: 让windows系统知道创建一个线程的唯一方法是调用API CreatThread函数(__beginthreadex之类的都要在内部调用他创建新线程)。好像windows核心编程说,在win2000下,系统用CreateRemoteThread函数来创建线程,CreateThread在内部调用CreateRemoteThread。不过这不是争论的焦点,至少win98下CreateRemoteThread并不能正常工作,还是CreateThread主持大局。
3,在整个消息循环的机制中,还必须谈到窗口函数的可重入性。什么意思?就是窗口函数(他是个回调函数)的代码什么时候都可以被系统(调用者一般是user32模块)调用。比如在窗口过程中,向自己的窗口SendMessage(***)那么执行过程是怎样的?
我们知道,SendMessage是要等到消息发送并被目标窗口执行完之后才返圆前回的。那么窗口在处理消息,然后又等待刚才发送到本窗口的消息被处理后之后(SendMessage返回)才继续往下执行,程序不就互相死锁了吗?
其实是不会的。windows设计一套适合SendMessage的判则算法,他判断如果发送的消息是属于本线程创建的窗口的,那么直接由user32模块调用窗口函数(可能就有窗口重入),并将消息的处理结果结果返回。这样做体现了窗口重入。上面的例子,我们调用SendMessage(***)发送消息到本窗口,那么窗口过程再次被调用,处理完消息之后将结果返回,然后SendMessage之后的程序接着执行。对于非队列消息,如果没有窗口重入,不知道会是什么样子。
NOTE: 由于窗口的可重入性。在win32 SDK程序中应尽量少用全局变量和静态变量,因为在窗口函数执行过程中可能窗口重入,如果重入后将这些变量改了,但你的程序在窗口重入返回之后继续执行,可能就是使用已经改变的全局或静态变量。在MFC中(所有窗口的窗口函数基本上都是AfxWndProc),按照类的思想进行了组织,一般变量都是类中的,好管理的多。
4,MFC中窗口类(比如C**View,CFrameWnd等)中的MessageBox函数,以及AfxMessageBox函数都是阻塞原有的消息循环的。由消息框内部的一个消息循环来从消息队列中读取消息,并派送消息(和模式对话框类似)。实际上,这些消息函数最终调用的是::MessageBox,它在消息框内部实现了一个消息循环(原有的主程序消息循环被阻塞了)。论坛中碰到过几次关于计时器和消息框的问题,看下面的代码:
void CTest_recalclayoutView::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
MessageBox("abc")
while(1)//设计一个死循环
CView::OnTimer(nIDEvent)
}
咱让OnTimer大约5秒钟d出一个消息框。那么,消息框不断的被d出来,只要消息框不被关闭,那么程序就不会进入死循环。实际上,每次d出对话框,都是最上层的那个消息框掌握着消息循环,其他的消息循环被阻塞了。只要不关闭最上面的消息框,while(1)就得不到执行。如果点了关闭,程序就进入了死循环,只能用ctrl+alt+del来解决问题了。
5,消息循环在很多地方都有应用。比如应用在线程池中。一个线程的执行周期一般在线程函数返回之后结束,那么怎么延长线程的生命周期呢?一种方法就是按照消息循环的思想,在线程中加入消息循环,不断地从线程队列读取消息,并处理消息,线程的生命周期就保持着直到这个消息循环的退出。
NOTE:只要线程有界面元素或者调用GetMessage,或者有线程消息发送过来,系统就会为线程创建一个消息队列。
6,在单线程程序中,如果要执行一个长时间的复杂 *** 作而且界面要有相应的话,可以考虑用自己的消息泵。比如,可以将一个阻塞等待 *** 作放在一个循环中,并将超时值设置得比较小,然后每个等待的片段中用消息泵继续消息循环,使界面能够响应用户 *** 作。等等之类,都可以应用消息泵(调用一个类似这样的函数):
BOOL CChildView::PeekAndPump()
{
MSG msg
while(::PeekMessage(&msg,NULL,0,0,PM_NOREMOVE))
{
if(!AfxGetApp()->PumpMessage())
{
::PostQuitMessage(0)
return false
}
}
return true
}
其实,用多线程也能解决复杂运算时的界面问题,但是没有这么方便,而且一般要加入线程通信和同步,考虑的事情更多一点。
综上所述,MFC消息循环就那么回事,主要思想还是和SDK中差不多。这种思想主要的特点表现在迎合MFC整个框架上,为整个框架服务,为应用和功能服务。
首先给出XML文件(telephone.xml,unicode格式)的定义:<?xml version="1.0" ?>
<telephones>
<telephone name="铜化金" telephonen="(020)845559887" email="[email protected]" />
<telephone name="全不真" telephonen="(020)842342444" email="[email protected]" />
</telephones>
<?xml version="1.0" ?><telephones><telephone name="铜化金" telephonen="(020)845559887" email="[email protected]" /><telephone name="全不真" telephonen="(020)842342444" email="[email protected]" /></telephones>
铜化金,全不真.哈,都是假的!但不会影响我们的研究.先看看连接XML过程:
var myXML = new XML()// 建立一个XML对象
myXML.ignoreWhite = true// 放弃仅包含空白的文本节点
myXML.onLoad = function(success) {
//trace("xml file loaded!")// 测试点1
if (success) {
parseXML(this)// 若加载XML成功,执行parseXML函数
}
}
myXML.load("telephone.xml")// 加载本棚大谨地XML文件
function parseXML(xmlDoc) {
// 这里写加载成功之后的语句,如读取/写入XML
}
var myXML = new XML()// 建立一个XML对象 myXML.ignoreWhite = true// 放弃仅包含空白的文本节点 myXML.onLoad = function(success) { //trace("xml file loaded!")// 测试点1 if (success) { parseXML(this)// 若加载XML成功,执行parseXML函数 } }myXML.load("telephone.xml")// 加载本地XML文件 function parseXML(xmlDoc) { // 这里写加载成功之链基后的语句,如读取/写入XML }
这个加载过程是比较完善的.看看随便给出的测试函数:
// 这里写加载成功之后的语句,如读取/写入XML
var nm = xmlDoc.firstChild.childNodes
trace(nm[0].attributes.name)// 测试点2
// 这里写加载成功之后的语句,如读取/写入XML var nm = xmlDoc.firstChild.childNodestrace(nm[0].attributes.name)// 测试点2
看,打印出"铜化金"来了.主要要讲是是第一句:
nm是个数组,您可以明确表明它是一个数组.如:
// 这里写加载成功之后的语句,如读取/写入XML
var nm:Array = new Array()
nm = xmlDoc.firstChild.childNodes
trace(nm[0].attributes.name)
// 这里写加载成功之后的语句,如读取/写入XML var nm:Array = new Array()nm = xmlDoc.firstChild.childNodestrace(nm[0].attributes.name)
这是标准写法,显得累赘一点.而xmlDoc是函数参数传入的XML对象.(这里也可用myXML)
firstChild就是引用父级节点的子级列表中的第一个子级(若没,则为null),这里就是指向<telephones>.childNodes则是此子级的所有子级组成的数组.
还不明显吗? 就是把所有telephone记录赋予给nm数组!然后就可以在nm数组里读取数据了!
还是让我们来做一个实际项目,在fla文件中放三个动态文本输入框,实例名仿庆字分别是t1,t2,t3.分别用来存储姓名,电话号码,电子邮箱地址.您可以在这三个动态文本前加上提示,这里就不详述了.
然后添加两个Button组件,其label属性分别是Perv,Next.实例名字分别是b1,b2
改写程序,如下:
var myXML = new XML()// 建立一个XML对象
myXML.ignoreWhite = true// 放弃仅包含空白的文本节点
myXML.onLoad = function(success) {
if (success) {
//trace("xml file loaded!")
parseXML(this)// 若加载XML成功,执行parseXML函数
}
}
myXML.load("telephone.xml")// 加载本地XML文件
var n:Number = new Number(0)// 建立保存当前节点变量
function parseXML(xmlDoc) {
// 这里写加载成功之后的语句,如读取/写入XML
display(0)
}
function display(n)
{
var nm:Array = new Array()
nm = myXML.firstChild.childNodes
t1.text = nm[n].attributes.name
t2.text = nm[n].attributes.telephonen
t3.text = nm[n].attributes.email
}
stop()
var myXML = new XML()// 建立一个XML对象 myXML.ignoreWhite = true// 放弃仅包含空白的文本节点 myXML.onLoad = function(success) { if (success) { //trace("xml file loaded!")parseXML(this)// 若加载XML成功,执行parseXML函数 } }myXML.load("telephone.xml")// 加载本地XML文件 var n:Number = new Number(0)// 建立保存当前节点变量 function parseXML(xmlDoc) { // 这里写加载成功之后的语句,如读取/写入XML display(0)} function display(n) { var nm:Array = new Array()nm = myXML.firstChild.childNodest1.text = nm[n].attributes.namet2.text = nm[n].attributes.telephonent3.text = nm[n].attributes.email } stop()
b1中写:
on(click)
{
_root.n = _root.n - 1
_root.display(_root.n)
}
on(click) { _root.n = _root.n - 1_root.display(_root.n)}
b2中写:
on(click)
{
_root.n = _root.n + 1
_root.display(_root.n)
}
on(click) { _root.n = _root.n + 1_root.display(_root.n)}
虽然没有强检测返回的数据(超出了文件显示undefined),但已经实现了基本的数据控制了。其实我们可以很容易完善它,看:
var myXML = new XML()// 建立一个XML对象
myXML.ignoreWhite = true// 放弃仅包含空白的文本节点
myXML.onLoad = function(success) {
if (success) {
//trace("xml file loaded!")
parseXML(this)// 若加载XML成功,执行parseXML函数
}
}
myXML.load("telephone.xml")// 加载本地XML文件
var n:Number = new Number(0)// 建立保存当前节点变量
var nMax:Number = new Number(0)// 建立保存最大子级变量
function parseXML(xmlDoc) {
// 这里写加载成功之后的语句,如读取/写入XML
display(0)
}
function display(n)
{
var nm:Array = new Array()
nm = myXML.firstChild.childNodes
nMax = nm.length -1
t1.text = nm[n].attributes.name
t2.text = nm[n].attributes.telephonen
t3.text = nm[n].attributes.email
}
stop()
var myXML = new XML()// 建立一个XML对象 myXML.ignoreWhite = true// 放弃仅包含空白的文本节点 myXML.onLoad = function(success) { if (success) { //trace("xml file loaded!")parseXML(this)// 若加载XML成功,执行parseXML函数 } }myXML.load("telephone.xml")// 加载本地XML文件 var n:Number = new Number(0)// 建立保存当前节点变量 var nMax:Number = new Number(0)// 建立保存最大子级变量 function parseXML(xmlDoc) { // 这里写加载成功之后的语句,如读取/写入XML display(0)} function display(n) { var nm:Array = new Array()nm = myXML.firstChild.childNodesnMax = nm.length -1 t1.text = nm[n].attributes.namet2.text = nm[n].attributes.telephonent3.text = nm[n].attributes.email } stop()
b1的定义:
on(click)
{
if(_root.n <_root.nMax){
_root.n = _root.n + 1
_root.display(_root.n)
}
}
on(click) { if(_root.n <_root.nMax){ _root.n = _root.n + 1_root.display(_root.n)} }
b2的定义:
on(click)
{
if(_root.n>0) {
_root.n = _root.n - 1
_root.display(_root.n)
}
}
on(click) { if(_root.n>0) { _root.n = _root.n - 1_root.display(_root.n)} }
看得出来那里改过吗?(其实加粗文字的地方就是了).看看我做的效果吧(丑陋得很,好在不是做美工的"心得体会")
Flash MX Professional 2003中没有向xml文件增加数据的功能.即保存文件,Flash是没有这个能力,但创建节点当然还是可以:
var xmlDoc = new XML()
var root = xmlDoc.createElement("abc")
xmlDoc.appendChild(root)
var child0 = xmlDoc.createElement("def")
root.appendChild(child0)
trace(xmlDoc)
var xmlDoc = new XML()var root = xmlDoc.createElement("abc")xmlDoc.appendChild(root)var child0 = xmlDoc.createElement("def")root.appendChild(child0)trace(xmlDoc)
至于如何保存XML文件,可以使用诸如ASP等语言的协助.但这样比较麻烦了,本文不涉及这点.(我会写一个笔记,关于如何保存XML的.请关注BLOG安排)
XML入门必看(建议中等Flash学习者观看)
一、有关XML
1、XML入门知识
XML(eXtensible Markup Language)是一种具有数据描述功能(Meta-language)、高度结构性及可验证性的语言。和HTML一样,XML同样使用了标记和属性;和HTML最大的不同在于XML的标记和属性允许用户自行定义,并可以依照所定义的标记与属性的语法来开发应用程序。XML采用了开放架构设计,它允许在Internet上的任何平台或语言之间交换数据。这项技术已经被广泛采用,目前几乎难以找到一个不以某种方式使用XML的应用程序。
一个简单的XML文件如下所示:
<XML>
<FLASH>
<A1>XML入门知识</A1>
<A2>撰写XML</A2>
</FLASH>
<OTHER>
<A1>为什么是XML</A1>
</OTHER>
</XML>
在Flash中涉及的XML不会很复杂,能看懂类似上面这样的XML文件,足已对付。
2、为什么在Flash中用XML
首先,大多数浏览器限制了URL为256个字符(包括查询字符串数据)。而XML对象没有这样的限制,这就使它成为将数据库内容加入Flash动画的一个理想方法。
其次,XML对象允许输入和集成任何Web上的XML格式的数据到Flash中,Flash能够将XML数据和精彩的动画及声音无缝结合起来。
另外,Flash几乎拥有在任何平台上处理XML的能力。一般来说,大多数XML转换是在服务器端处理的,因为浏览器对XML的支持不是很完全。
但是,Flash载入一个外部XML文件如果超过15秒就会超时,它不会再进行载入,Flash Player和动画会停止。同样的,在浏览器中使用load或sendAndLoad载入64K或更大的数据会导致性能问题。其特征包括服务器应答"Error 501-Not Implemented"或浏览器的无响应状态。Flash Player也不能从外部Web站点上载入XML文件。Flash动画只能从它自己的域里载入XML数据。例如,一个在adomain.com上的Flash动画就不能从bdomain.com读取或载入XML数据。
二、Flash中XML应用的原理
从Flash MX开始,对XML的支持已经初具规模,在Flash MX 2004中得到了加强,现在用Flash MX 2004来做有关XML的应用已经很方便了。在Flash MX 2004中使用XML主要有两种方式,使用XML对象和使用XMLSocket对象。使用XML对象应用的是HTTP的通讯方式,而使用XMLSocket对象应用的是Socket的通讯方式,两者有比较大的区别。
下面分别介绍使用XML的两种方式。
1、使用XML对象
在网络应用中,使用XML对象应用HTTP的通讯方式,基本的通讯模式仍然是请求响应。先在Flash中对数据进行处理,生成XML树,然后通过HTTP的通讯方式将XML文件发送到服务器端。在服务器端,先对接收到的XML树进行解释,再根据流程做相应的 *** 作,比如读写数据库或其他的资源,然后生成XML树,通过HTTP的通讯方式将XML文件发送到Flash端。最后在Flash端接收XML文件,对XML树进行解释,对相应的数据进行 *** 作,如此循环。其通讯原理请参考图1。
下面分别介绍Flash端和服务器端的东西。
A、Flash端:主要用到XML对象中的send()、load()、sendAndLoad()、onLoad()、onData()及其他 *** 纵XML树的方法与事件。
比如,生成XML树的代码如下:
loginXML = new XML()//生成一个XML对象
loginElement = loginXML.createElement("LOGIN")//生成一个元素
loginElement.attributes.username = username//设置元素的属性
loginElement.attributes.password = password
loginXML.appendChild(loginElement)//将所生成的元素加到XML对象
解释XML树的代码如下:
loginReplyXML = new XML()//生成一个响应的XML对象
loginReplyXML.onLoad = onLoginReply()//设置响应XML对象下载事件的函数
function onLoginReply () { //对返回的XML文件进行 *** 作
var e = this.firstChild//解释返回的XML文件
if (e.nodeName == "LOGINREPLY" &&e.attributes.status == "OK") {
//根据返回的XML文件中的数据做相应的 *** 作
gotoAndStop ("success")
} else {
gotoAndStop ("loginFailed")
}}
有关XML数据的通讯代码如下:
loginXML.sendAndLoad("http://www.pcedu.com.cn/test.asp", loginReplyXML)
//根据URL去取响应的XML文件到响应的XML对象中
B、在服务器端:常用的工具有Asp、jsp、PHP、Perl等等脚本语言,它们所起的作用是 *** 纵XML树和数据的通讯。
下面以常用的Asp为例,解释XML树的代码为:
//创建一个新的Domdocument对象,存客户端传送过来的XML请求
var xmlLogin = new ActiveXObject("Msxml2.Domdocument")
//从发送来的表单中取得数据
xmlLogin.loadXML(Request.Form())
//创建XML元素
var reElement = xmlLogin.documentElement
//提取用户名和密码信息
password = reElement.attributes[0].nodevalue
username = reElement.attributes[1].nodevalue
生成XML树的代码为并发送的代码为:
//创建一个新的Domdocument对象,向客户端发送
var xmlRepley = new ActiveXObject("Msxml2.Domdocument")
//创建一个简单的XML文件
xmlRepley.loadXML("<LOGINREPLY login='1' msg='"+Msg+"' />")
//也是通过Write()的方法将XML文件返回到Flash端
Response.Write(xmlRepley.xml)
C、还有一种情况是 *** 作本地的XML文件,无非也就是生成、解释XML文件,得到所要的数据,只不过不需要在服务器端做其他的 *** 作了。比如,读一个本地的XML文件的代码为:
playlist_xml = new XML()//创建一个XML对象
playlist_xml.ignoreWhite = true//省略空白
playlist_xml.onLoad = function(success) { //当加载XML文件成功的时候触发此函数
trace("success")
}
playlist_xml.load("playlist.xml")//加载本地的XML文件
值得说明的是,上面所涉及的代码都是举例而已,实际应用中的代码可能会复杂很多。但其中的原理都是相通的,先生成XML文件,发送到服务器端,最后将服务器端返回的XML文件解释。只要思路清晰,做起来就比较有效率,也不容易出错。
2、使用XMLSocket对象
在网络通讯中,使用XMLSocket对象的通讯方式为Socket,(所谓的Socket,可以将它想象为一条通路,需要通讯的时候,在客户端跟服务器端建立一个连接,然后传送内容,通讯完毕后再撤销这个通路)。Flash端跟服务器端的通讯模式为:先在Flash端跟服务器端建立一个Socket连接,生成XML文件后,通过所建立的Socket连接将XML文件发送到服务器端,服务器端解释所接收到的文件,对数据进行相应的 *** 作后,生成一个XML文件,通过Socket连接发送到Flash端,Flash端解释XML文件后就得到所需要的数据。如此循环, *** 作完成后关闭Socket连接。有点难懂,可以参考图2仔细想想。
下面分别解释在Flash端跟服务器端的东西。
A、在Flash端:XMLSocket对象中,只有三个方法和四个事件,都是在Socket通讯时候用的,对XML文件的 *** 作还是要靠XML对象。比如,下面是一些简单的Socket *** 作:
//声明XMLSocket对象
var mySocket=new XMLSocket()
//根据IP地址和端口连接服务器
mySocket.connect("127.0.0.1",9980)
//连接成功与否的判断
mySocket.onConnect=function(sucess)else
}
//当接收到XML文档的时候,触发此函数
mySocket.onXML=function(xmlDoc)
B、在服务器端:选用服务器端的开发语言的标准是,起码要能够做Socket方面的 *** 作(复杂的应用当中还需要多线程、负载平衡等方面的东西)。比较常用的有C/C++、java,其他的比如Delphi、Vb等工具对Socket的 *** 作就有点不方便。要开发一个高效率、稳定、可扩展的服务器端程序并不是一件很简单的事情,最好能找点相应的资料深入学习一下,刚入门的时候,学习的重点可以放在Socket和多线程上面。下面以比较流行的java语言来举例说明服务器端程序的简单架构:
//运用多线程防止服务器阻塞
public class MultiThreadServer extends Thread
{
private ServerSocket listen_socket
public MultiThreadServer(int port)
{
try
{
listen_socket = new ServerSocket(port)//创建一个服务器端的Socket
this.start()//启动多线程
}
catch(IOException e) //捕捉异常
}
//下面为服务器监听线程的主程序。
public void run()
{
while(true) //死循环,一直在端口上监听有无客户端的Socket连接
{
try
{
//有客户端连接上来,创建一个相应的Socket,并启动响应的函数
Socket client_socket= listen_socket.accept()
SockState sstate=new SockState(client_socket)
OperThread oper=new OperThread(sstate)
}catch(Exception ee)
{
System.out.print("MultiThreadServer run:"+ee.getMessage())
}
}
}
}
3、XML在Flash中主要涉及两方面的应用,本地应用和网络应用。
本地应用主要是存取XML文件中所保存的数据,这里所指的数据并不一定限定是文本数据,也可以是图片数据,声音数据等等。比如可以用Flash + XML来做图片管理器,歌曲列表管理器,用处还是比较大的,也比较灵活。
网络应用是XML在Flash中的主要用途,它的优缺点在前面内容中已经提到。比如说,可以用来做电子商务方面的应用、论坛、聊天室等等。
如果看不懂,那是因为您的基础不好,您还是先去我们的初级入门板块看
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)