`
liuhaixiao
  • 浏览: 151081 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Flash AS3.0 Socket编程

 
阅读更多

抄自: http://www.cnblogs.com/Longbin/articles/1929771.html

 

我们在使用ActionScript3.0进行Socket编程的时候需要关注下面的问题,我们将在今后的学习中逐个对下面的问题进行讨论,并尽量逐渐的改进我们的程序.
1.
Socket服务器建立连接.
2.
Socket服务器发送数据.
3.
Socket服务器读数据.
4.
Socket服务器进行握手,并确定收到了什么样的数据和如何处理这些数据.
5.
Socket服务器断开,或者当服务器想与你断开的时候发消息给你.
6.
处理使用Sockets时候引发的错误.


Socket服务器建立连接.

解决方法:
我们通过调用Socket.connect( )或者XMLSocket.connect( )方法并监听网络连接的事件消息.

讨论:
连接一台Socket服务器你需要确定两个信息,一个是Socket服务器的域名或者IP地址,另一个是服务器监听的端口号.
无论你使用的是Socket还是XMLSocket类的实例,连接请求都是完全的一样的,两个类都是使用一个名叫connect()的方法,该方法有两个参数:
host :
该参数为字符串类型,可以是一个域名,例如"www.example.com",也可以是一个IP地址,例如"192.168.1.101".如果Socket服务器与你该Flash影片发布的Web服务器是同一个,该参数为Null.
port :
该参数为一个表示Socket服务器监听端口的int.该值最小为1024.除非在服务器中有一个policy文件,用于指定允许端口号小于1024.
因为Flash Socket编程是一个异步的过程,connect()方法不会等到一个连接完成后再执行下一行代码的执行.如果你想在一个连接完全执行完之前与一个Socket完全绑定,那么你将会得到一个意想不到的结果,并且你当前的代码将不能工作.
在尝试一个新的Socket连接的时候我们最好先添加一个连接事件监听器.当一个连接建立成功,Socket或者XMLSocket会发出一个连接事件,这就可以让你知道交互已经准备好了.
下面举了一个Socket实例与本地Socket服务器的2900端口建立连接的例子:

package {
   import flash.display.Sprite;
   import flash.events.*;
   import flash.net.Socket;

   public class SocketExample extends Sprite {

private var socket:Socket;

public function SocketExample(   ) {
   socket = new Socket(   );
   
   // Add an event listener to be notified when the connection
   // is made
   socket.addEventListener( Event.CONNECT, onConnect );
   
   // Connect to the server
   socket.connect( "localhost", 2900 );
}

private function onConnect( event:Event ):void {
   trace( "The socket is now connected..." );
}

   }
}

如果你想通过XMLSocket与服务器建立连接代码也是基本一样的.首先你创建了一个连接事件监听器,然后调用connect()方法.所不同的是Socket实例改为了XMLSocket:

package {
   import flash.display.Sprite;
   import flash.events.*;
   import flash.net.XMLSocket;

   public class SocketExample extends Sprite {

private var socket:XMLSocket;

public function SocketExample(   ) {
   socket = new XMLSocket(   );
   
   // Add an event listener to be notified when the connection is made
   socket.addEventListener( Event.CONNECT, onConnect );
   
   // Connect to the server
   socket.connect( "localhost", 2900 );
}

private function onConnect( event:Event ):void {
   trace( "The xml socket is now connected..." );
}

   }
}

如果连接失败,可那是下面两种原因的一种:一种是连接立即失败和运行时错误,另一种是如果无法完成连接从而产生一个ioError或者securityError事件.关于错误事件处理信息的描述,我们打算改日讨论.
请牢记,当与一个主机建立一个Socket连接时,Flash Player要遵守如下安全沙箱规则.
1.Flash
.swf文件和主机必须严格的在同一个域名,只有这样才可以成功建立连接.
2.
一个从网上发布的.swf文件是不可以访问本地服务器的.
3.
本地未通过认证的.swf文件是不可以访问任何网络资源的.
4.
你想跨域访问或者连接低于1024的端口,必须使用一个跨域策略文件.
如果尝试连接未认证的域或者低端口服务,这样就违反了安全沙箱策略,同时会产生一个securityError事件.这些情况都可以通过使用一个跨域策略文件解决.无论是Socket对象还是XMLSocket对象的策略文件,都必须在连接之前通过使用flash.system.Security.loadPolicyFile()方法载入策略文件.具体如下:
Security.loadPolicyFile("http://www.rightactionscript.com/crossdomain.xml");
获得的改策略文件不仅定义了允许的域名,还定义了端口号.如果你不设置端口号,那么Flash Player默认为80端口(HTTP协议默认端口).<allow-access-from>标签中可以使用逗号隔开设置多个端口号.下面这个例子就是允许访问80110端口.

<?xml version="1.0"?>

<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="*" to-ports="80,110" />
</cross-domain-policy>

2.Socket服务器发送数据.

解决方法:
对于Socket对象来说,通过是用write方法(writeByte(),writeUTFBytes( )等方法.)先向缓存区写入数据,然后使用flush()方法发送数据.对于XMLSocket对象,使用send()方法.

讨论:
Socket
XMLSocket类向Socket服务器发送数据的方法是不相同的.让我们首先看一下Socket类的方法.
当你使用Socket对象向服务器发送数据的时候,你首先要将数据写入到一个缓冲区中.Socket类设置了一系列的方法来写数据.每一个方法都用于写不同的数据类型的数据(或者不同的数据).这些方法分别是: writeBoolean( ), writeByte( ), writeBytes( ), writeDouble( ), writeFloat( ), writeInt( ), writeMultiByte( ), writeObject( ), writeShort( ), write- UnsignedInt( ), writeUTF(), writeUTFBytes( ). 这些方法大多数都只接受一个参数,该参数的类型同方法的名字相匹配.例如,writeBoolean()方法接受一个布尔值作为参数, writeByte( ), writeDouble( ), writeFloat( ), writeInt( ), writeShort( ), writeUnsignedInt( ) 方法接受一个数字型参数.writeObject()方法接受一个对象类型作为参数,但该对象必须序列化成为AMF格式.writeBytes( )方法允许你传一个ByteArray参数,并带有偏移量和长度两个参数.例如,下面这段代码,调用了一个writeBytes( )方法,该方法将ByteArray对象中的所有byt值都传出去了(偏移量为0,长度和ByteArray数组长度等长):

socket.writeBytes(byteArray, 0, byteArray.length);

writeUTF( )
writeUTFBytes( ) 方法允许你的发送字符串类型的参数.每个一个方法只接受一个字符串作为参数.writeUTFBytes( )方法简单的将字符串作为Bytes发送.writeUTF( )方法在写入真正数据之前,先写入byts的数量.
writeMultiByte( )
方法也允许字符串类型的参数,但是使用的为非默认字符集.该方法需要两个参数:字符串和字符集名称.FlashFlex的帮助文档中有一个自持所有字符集的列表,该列表中的标签和描述符是一一对应的.使用标签值作为writeMultiByte( )作为字符集.例如下面的代码发送了一个编码为Unicode的字符串:

socket.writeMultiByte("example", "unicode");

相一个Socket对象传数值的方法完全依赖于你所有数据的类型和服务所接受数据的类型.使用一个Socket对象,你完全可以使用 ActionScript写一个TelnetPOP mail客户端.这两种协议都支持ASCII字符指令.例如,在连接一个POP服务器之后,你可以通过使用USER指令指定一个用户.下面代码向一个 Socket对象发一条指令:

// POP servers expect a newline (\n) to execute the preceding command.
socket.writeUTFBytes("USER exampleUsername\n");

向一个Socket对象写入数据其实并没有将数据发送到Socket服务器.每调用一个write方法都向Socket对象添加一个数据.例如,下面代码向一个Socket对象添加了四个byte的数据,但是没有一个发出了.

socket.writeByte(1);
socket.writeByte(5);
socket.writeByte(4);
socket.writeByte(8);

当你想将这些累积的数据发送到Socket服务器需要调用flush()方法.flush()方法调用之后将把所有已经写入的数据发送出去,并清空缓冲区:

socket.flush(   );

XMLSocket
类是一个非常简单用于发送数据的API.写于发数据都是由send()这一个方法来完成的.send()方法可以接受任何数据类型的参数.它可以将所有的参数都转换为一个字符串类型并发送到服务器.通常参数为一个XML对象或者一个包含数据结构类似XML数据的字符串:

xmlSocket.send(xml);

然而,准确的格式完全依赖于服务器所能够接受的格式.如果服务器接受XML格式的数据,你必须发送XML格式的数据.如果服务器只接受URL编码的数据,你也必须发送URL编码的数据.

3.Socket服务器读数据

解决方法:
对于Socket实例,先收到socketData事件,然后调用如下两个方法的一个,比如,readByte()或者readInt(),在事件控制器中确定不会去读过去的bytesAvailable.
对于XMLSocket实例,先收到data事件,然后解析从事件控制器内部装载的XML数据.

讨论:
从一个socket连接接收的数据依赖于你使用的Socket的类型.socketXMLSocket都可以从服务器接受到数据,但是它们处于不同重量级的技术.让我们在讨论XMLSocket之前先关注下Socket.
我都知道socketFlash中是一个异步的行为.因此,它就不能简单的创建一个Socket连接,然后就立刻尝试去读取数据.read方法不能等到从服务器传过来数据之后在返回.换句话说,你只能在客户端从服务器载入所有数据之后才可以读取数据.在数据可用之前读数据会产生一个错误.
通过socketData事件广播到Socket实例,这样我们就可以知道什么时候数据可以被读取.那么我们要为socketData事件添加一个事件监听器,任何时候只要有新的数据从一个socket服务器发送过来,都会触发事件控制器.在事件处理器的内部我们写入我们要执行的代码去读取和处理收到的数据.
从一个前端服务器读取数据,Socket类为我们提供了许多不同的方法,这些方法依赖于你所读得数据类型.例如,你可以通过readByte()方法读一个byte数据,或者通过一个使用readUnsignedInt()方法去读一个无符号整数.下面这个表列出来能够从服务器读取的数据类型,返回值, read方法每次读入的字节数.

Table:Socket read methods for various datatypes
方法:返回值类型       描述       字节数
readBoolean( ):Boolean       
Socket读取一个Boolean.       1
readByte( ):int       
Socket读取一个byte.       1
readDouble( ):Number       
Socket读取一个IEEE 754双精度浮点数.       8
readFloat( ):Number       
Socket读取一个IEEE 754单精度浮点数.       4
readInt( ):int       
Socket读取一个有符号32-bit整数值.       4
readObject( ):*       
Socket读取一个AMF-encoded对象.       n
readShort( ):int       
Socket读取一个有符号16-bit整数值.       2
readUnsignedByte( ):uint       
Socket读取一个无符号字节.       1
readUnsignedInt( ):uint       
Socket读取一个无符号32-bit整数       4
readUnsignedShort( ):uint       
Socket读取一个无符号16-bit整数.       2
readUTF( ):String       
Socket读取一个一个UTF8字符串.       n


有两个额外的方法没有在上面这个表中描述.它们分别是readBytes()readUTFBytes().readBytes()方法只可以让socket读数据但不能返回一个值,并且该方法需要3个参数:

bytes:
一个flash.util.ByteArray实例读取从socket中收到的数据.
offset:
一个uint,指定从什么位置开始读取socket中收到数据的偏移量.默认值为0.
length:
一个uint,用于指定读取bytes的数量.默认值为0,意思就是说将所有的可用的数据都放入ByteArray.

另一个readUTFBytes()方法,只需要一个长度参数用于指定UTF-8字节的读入数量,并且该方法会将所有读入的字节码转换成为字符串类型.

注意:在从一个Socket读数据之前,首先要判断bytesAvailable的属性.如果你不知道要读入的数据类型是什么就去读数据的话,将会产生一个错误(flash.errors.EOFError).

下面的例子代码连接了一个socket服务器,读取并显示每次从服务器发来的数据.

package {
   import flash.display.Sprite;
   import flash.events.ProgressEvent;
   import flash.net.Socket;

   public class SocketExample extends Sprite {

private var socket:Socket;

public function SocketExample(   ) {
   socket = new Socket(   );
   
   // Listen for when data is received from the socket server
   socket.addEventListener( ProgressEvent.SOCKET_DATA, onSocketData );

   // Connect to the server
   socket.connect( "localhost", 2900 );
}

private function onSocketData( eventrogressEvent ):void {
   trace( "Socket received " + socket.bytesAvailable + " byte(s) of data:" );

   // Loop over all of the received data, and only read a byte if there
   // is one available
   while ( socket.bytesAvailable ) {
       // Read a byte from the socket and display it
       var data:int = socket.readByte(   );
       trace( data );
   }
}
   }
}

在上面的这个例子中,如果一个socket服务器发送回一个消息(例如"hello"),当一个客户段连入服务器就会返回并输出下面类似的文字:

Socket received 5 byte(s) of data:
72
101
108
108
111

注意:一旦数据从socket读出,它就不能再次被读.例如,读一个字节之后,这个字节就不能再"放回来",只能读后边的字节.

当收到的数据为ASCII编码,你可以通过readUTFBytes()方法重新构建一个字符串.readUTFBytes()方法需要知道多少个字节需要转换为字符串.你可以使用bytesAvailable去读所有的字节数据:

var string:String = socket.readUTFBytes(socket.bytesAvailable);

XMLSocket
类的动作和Socket类相比在从服务器接受数据的风格相似.两者都是通过事件监听器来监听数据接收通知的,这主要取决于Flash异步的Socket实现.然而,在处理实际数据的时候有很大的不同.

有个XMLSocket实例在从服务器下载完数据后分发数据事件.通过flash.events.DataEvent.DATA常量定义的数据事件包含一个data属性,该属性包含了从服务器收到的信息.

注意:使用XMLSocket从服务器返回的数据总是认为是一个字符串类型的数据.这样不用为任何数据类型的数据指定读取方法.

这些从服务器返回的数据是没有经过任何处理的原始数据.因此,你不能通过XMLSocket连接立即使用XML,你发送和接收的都是纯字符串数据.如果你期望XML,在你处理数据之前,你必须首先将这些数据转换为一个XML的实例.
下面的这段代码在初始化的时候通过XMLSocket连接到了本地服务器的2900端口.在连接成功之后,一个<test>消息会发送到服务器.onData事件监听者控制从服务器返回的响应.在本例中返回字符串<response><test success='true'/></response>.你可以通过事件的data属性发现为字符串数据,然后XML类的构造函数将字符串转换成为了XML实例.最后,通过使用E4X语法的XML实例的一部分信息.(关于通过使用E4X处理XML的更多详细信息,我们需要另外讨论.)

package {
   import flash.display.Sprite;
   import flash.events.Event;
   import flash.events.DataEvent;
   import flash.net.XMLSocket;

   public class SocketExample extends Sprite {

private var xmlSocket:XMLSocket;

public function SocketExample(   ) {
   xmlSocket = new XMLSocket(   );
   
   // Connect listener to send a message to the server
   // after we make a successful connection
   xmlSocket.addEventListener( Event.CONNECT, onConnect );
   
   // Listen for when data is received from the socket server
   xmlSocket.addEventListener( DataEvent.DATA, onData );

   // Connect to the server
   xmlSocket.connect( "localhost", 2900 );
}

private function onConnect( event:Event ):void {
   xmlSocket.send( "<test/>" );
}

private function onData( eventataEvent ):void {
   // The raw string returned from the server.
   // It might look something like this:
   // <response><test success='true'/></response>
   trace( event.data );
   
   // Convert the string into XML   
 
   var response:XML = new XML( event.data );
   
   // Using E4X, access the success attribute of the "test"
   // element node in the response.
   // Output: true
   trace( response.test.@success );
}
   }
}

注意:data事件分发数据之前,XMLSocket实例必须从服务器收到一个表示为空的byte('\\0').也就是说,从服务器仅仅只发送所需要的字符串是不够的,必须在结尾处加入一个表示为空的byte.

.Socket服务器进行握手,并确定收到了什么样的数据和如何处理这些数据.

解决方法:
创建不同的常量来声明协议的状态.使用这些常量将指定的处理函数映射到相应的状态.在一个socketData事件控制器中,通过状态映射调用这些函数的.

讨论:
建立Socket连接通常要处理握手这个环节.尤其是在服务器初始化需要向客户端发送数据.然后客户端通过一种特殊的方式相应这些数据,接着服务器因此再次响应.整个处理过程直到握手完成并且建立起一个"正常的"连接为止.

处理服务器的不同响应是非难的,主要的原因是socketData事件控制器不能保存上下文的顺序.也就是说,服务器的响应不会告诉你"为什么"响应也不告诉你这些响应数据被那个处理程序来处理.要想知道如何处理这些从服务器返回的响应不能从响应的本身来获得,尤其在响应变化的时候.或许一个响应返回了两个字节码,另一个返回了一个整数值还跟了一个双精度浮点数.这样看来让响应本身处理自己是一大难题.

我们通过创建一个状态量来标注不同的上下文,服务器通过这些上下文将数据发送到客户端.与这些状态量都有一个相关联的函数来处理该数据,这样你就可以很轻松的按照当前的协议状态去调用正确的处理函数.

当你要与一个Socket服务器建立连接需要考虑如下几个步骤:
1.
当与服务器连接的时候,服务器立刻返回一个标志服务器可以支持的最高协议版本号的整数值.
2.
客户端在响应的时候会返回一个实际使用协议的版本号.
3.
服务器返回一个8byte的鉴定码.
4.
然后客户端将这鉴定码返回到服务器.
5.
如果客户端的响应不是服务器端所期望的,或者,就在这个时候该协议变成了一个常规操作模式,于是握手结束.

实际上在第四步可以在鉴定码中包含更多的安全响应.你可以通过发送各种加密方法的密匙来代替逐个发送的鉴定码.这通常使用在客户端向用户索要密码的时候然后密码成为了加密过的8byte鉴定码.该加密过的鉴定码接着返回到服务器.如果响应的鉴定码匙服务器所期望的,客户端就知道该密码是正确的,然后同意建立连接.

实现握手框架,你首先要为处理从服务器返回的不同类型的数据分别创建常量.首先,你要从步骤1确定版本号.然后从步骤3收取鉴定码.最后就是步骤5的常规操作模式.我们可以声明

如下常量:

public const DETERMINE_VERSION:int = 0;
public const RECEIVE_CHALLENGE:int = 1;
public const NORMAL:int = 2;

常量的值并不重要,重要的是这些值要是不同的值,两两之间不能有相同的整数值.

下一个步骤我们就要为不同的数据创建不同处理函数了.创建的这三个函数分别被命名为readVersion( ), readChallenge( )  readNormalProtocol( ). 创建完这三个函数后,我们就必须将这三个函数分别映射到前面不同状态常量,从而分别处理在该状态中收到的数据.代码如下:

stateMap = new Object(   );
stateMap[ DETERMINE_VERSION ] = readVersion;
stateMap[ RECEIVE_CHALLENGE ] = readChallenge;
stateMap[ NORMAL          ] = readNormalProtocol;

最后一步是编写socketData事件处理控制器,只有通过这样的方式,建立在当前协议状态之上的正确的处理函数才可以被调用.首先需要创建一个 currentStateint变量.然后使用stateMap去查询与currentState相关联的函数,这样处理函数就可以被正确调用了.

var processFunc:Function = stateMap[ currentState ];
processFunc(   ); // Invoke the appropriate processing function

下面是一点与薄记相关的处理程序.在你的代码中更新currentState从而确保当前协议的状态.

前面我们所探讨的握手步骤的完整的代码如下:
package {
   import flash.display.Sprite;
   import flash.events.ProgressEvent;
   import flash.net.Socket;
   import flash.utils.ByteArray;

   public class SocketExample extends Sprite {

// The state constants to describe the protocol
public const DETERMINE_VERSION:int = 0;
public const RECEIVE_CHALLENGE:int = 1;
public const NORMAL:int = 2;

// Maps a state to a processing function
private var stateMap:Object;

// Keeps track of the current protocol state
private var currentState:int;

private var socket:Socket;

public function SocketExample(   ) {
   // Initialzes the states map
   stateMap = new Object(   );
   stateMap[ DETERMINE_VERSION ] = readVersion;
   stateMap[ RECEIVE_CHALLENGE ] = readChallenge;
   stateMap[ NORMAL          ] = readNormalProtocol;
   
   // Initialze the current state
   currentState = DETERMINE_VERSION;

   // Create and connect the socket
   socket = new Socket(   );
   socket.addEventListener( ProgressEvent.SOCKET_DATA, onSocketData );
   socket.connect( "localhost", 2900 );
}

private function onSocketData( eventrogressEvent ):void {
   // Look up the processing function based on the current state
   var processFunc:Function = stateMap[ currentState ];
   processFunc(   );
}

private function readVersion(   ):void {
   // Step 1 - read the version from the server
   var version:int = socket.readInt(   );
   
   // Once the version is read, the next state is receiving
   // the challenge from the server
   currentState = RECEIVE_CHALLENGE;
   
   // Step 2 - write the version back to the server
   socket.writeInt( version );
   socket.flush(   );
}

private function readChallenge(   ):void {
   // Step 3 - read the 8 byte challenge into a byte array
   var bytes:ByteArray = new ByteArray(   );
   socket.readBytes( bytes, 0, 8 );
   
   // After the challenge is received, the next state is
   // the normal protocol operation
   currentState = NORMAL;
   
   // Step 4 - write the bytes back to the server
   socket.writeBytes( bytes );
   socket.flush(   );
}

private function readNormalProtocol(   ):void {
   // Step 5 - process the normal socket messages here now that
   // that handshaking process is complete
}
   }
}

5.Socket服务器断开,或者当服务器想与你断开的时候发消息给你.

解决方法:
通过调用Socket.close( )或者XMLSocket.close( )方法显性的断开与服务器的连接.同时可以通过监听close事件获得服务器主动断开的消息.

讨论:
通常情况下我们需要对程序进行下清理工作.比如说,你创建了一个对象,当这个对象没有用的时候我们就要删除它.因此,无论我们什么时候连接一个 Socket服务器,都要在我们完成了必要的任务之后显性的断开连接一直留着无用的Socket连接浪费网络资源,应该尽量避免这种情况.如果你没有断开一个连接,那么这个服务器会继续保持着这个无用的连接.这样一来就很快会超过了服务器最大Socket连接上线.

Socket
XMLSocket对象断开连接的方法是一样的.你只需要调用close()方法就可以了:

// Assume socket is a connected Socket instance
socket.close(   );   // Disconnect from the server

同样的,XMLSocket对象断开连接的方法一样:

// Assume xmlSocket is a connected XMLSocket instance
xmlSocket.close(   );   // Disconnect from the server

close()
方法用于通知服务器客户端想要断开连接.当服务器主动断开连接会发消息通知客户端.可以通过调用addEventListener()方法注册一个close事件的一个监听器.Socket  XMLSocket都是使用Event.CLOSE作为"连接断开"事件类型的;例如:

// Add an event listener to be notified when the server disconnects
// the client
socket.addEventListener( Event.CLOSE, onClose );

注意:调用close()方法是不会触发close事件的,只用服务器主动发起断开才会触发.一旦一个Socket断开了,就无法读写数据了.如果你想要从新这个连接,你只能再建立个新的连接了.

6.处理使用Sockets时候引发的错误.

解决方法:
使用try/catch处理I/OEOF(end of file)错误.

讨论:
Socket
XMLSocket类对错误的处理很类似.不如,当调用connect()方法的时候,在下面任何一个条件成立的情况下SocketXMLSocket对象会抛出一个类型为SecurityError的错误.

.swf未通过本地安全认证.
端口号大于655535.

当调用XMLSocket对象的send()或者Socket对象的flush()的时候,如果socket还没有连接这两个方法都会抛出一个类型为 IOError的错误.尽管你可以将send()或者flush()方法放入try/catch结构块中,你也不能依赖于try/catch结构块作为你应用程序的逻辑.更好的办法是,在调用send()或者flush()方法之前使用一个if语句首先判断一下Socket对象的connected属性是否为True.例如,下面的代码使用了if语句作为程序逻辑的一部分,Socket对象当前不是连接状态就调用 connectToSocketServer()方法.但是我们依然需要将flush()方法放到try/catch语句块中.通过使用 try/catch语句块将flush()方法抛出的错误写入到日志中:

if ( socket.connected ) {
try {
       socket.flush(   );
}
catch( error:IOError ) {
       logInstance.write( "socket.flush error\n" + error );
}
}
else {
connectToSocketServer(   );
}

所有的Socket类的read方法都能够抛出EOFErrorIOError类型的错误.当你试图读一个数据,但是没有任何可用数据将触发EOF错误.当你试图从一个已经关闭的Socket对象中对数据时将会抛出I/O错误.

除了SocketXMLSocket类的方法能够抛出的错误以外,这些类的对象还会分发错误事件.有两种基本的错误事件类型,他们分别由 socketIOErrorsecurityError错误引起.IOError事件为IOErrorEvent类型,当数据发送或接收失败触发该事件.SecurityError事件是SecurityErrorEvent类型,当一个Socket尝试连接一个服务器,但由于服务器不在安全沙箱范围之内或者端口号小于1024的时候触发该错误事件.

注意:这两种安全策略引起的错误都可以通过跨域访问策略文件解决.

分享到:
评论

相关推荐

    刘嘉怡.中期检查.doc

    刘嘉怡.中期检查.doc

    COMSOL热电效应模型:基于MATLAB API的热电转换仿真与优化

    内容概要:本文详细介绍了如何使用COMSOL Multiphysics进行热电效应仿真的全过程。首先解释了热电效应的基本概念及其应用场景,如手机充电发烫、吹风机温度升高等。接着,通过具体实例展示了如何在COMSOL中建立热电模型,包括选择合适的物理场(焦耳热和热电效应)、设定材料属性(电导率、导热系数、塞贝克系数)、绘制几何形状以及设置边界条件。文中还提供了详细的MATLAB代码片段用于自动化建模流程,涵盖求解器配置、网格划分、后处理等方面的技术细节。此外,作者分享了一些常见问题的解决方案,如求解器不收敛、网格畸变等。 适合人群:对热电效应感兴趣的科研人员、工程技术人员及高校学生,尤其适用于有一定COMSOL和MATLAB基础的学习者。 使用场景及目标:帮助读者掌握热电效应的基本原理和COMSOL仿真技能,能够独立完成从模型构建到结果分析的完整流程。目标是提高热电转换系统的效率,优化设计参数,探索新材料的应用潜力。 其他说明:文章不仅提供了理论指导,还包括大量实战经验和技术技巧,有助于解决实际建模过程中遇到的问题。

    汽车内外饰模具设计规范详解:分型面、斜顶滑块及模架顶出系统的技术要点

    内容概要:本文深入探讨了汽车内外饰模具设计的关键要素,涵盖分型面设计、斜顶和滑块的应用、模架选择以及顶出系统的配置。针对每个部分,不仅提供了理论指导,还辅以Python、MATLAB等编程语言的实际代码示例,帮助理解和实施具体设计方案。例如,分型面设计强调了如何根据产品结构和外观要求确定最佳分型面位置;斜顶和滑块部分讨论了不同类型及其应用场景;模架和顶出系统则关注于结构稳定性和顶出效果的优化。 适合人群:从事汽车模具设计的专业人士,尤其是希望深入了解内外饰模具设计细节的新手设计师和技术人员。 使用场景及目标:适用于汽车内外饰模具设计项目,旨在提高模具设计的精度和效率,减少试错成本,确保产品质量。通过学习本文提供的技术和实践经验,能够更好地应对实际工作中遇到的各种挑战。 其他说明:文中提到的代码示例和经验公式均来源于实际工程案例,具有较高的参考价值。同时,作者还分享了许多宝贵的行业经验和技巧,有助于读者快速掌握模具设计的核心技能。

    python3.10以上 可安装pyside6(类似pyqt),具体安装操作步骤

    python3.10以上 可安装pyside6(类似pyqt),具体安装操作步骤

    【人工智能领域】DeepSeek AI深度探索平台的优势解析:多模态处理、低成本训练与广泛应用场景综述

    内容概要:DeepSeek AI是由杭州深度求索人工智能基础技术研究有限公司于2025年1月20日发布的深度探索AI技术。它具有多模态能力、多语言支持、长上下文理解、领域垂直优化、开源特性等多项技术突破,支

    IIS配置phpweb服务器所需VC-redist.x64.rar

    IIS配置phpweb服务器所需VC_redist.x64.rar

    云南移动5G-A网业战略发展探讨 -创新领航,千帆竞发,共同迈入5G-A新时代.pptx

    云南移动5G-A网业战略发展探讨 -创新领航,千帆竞发,共同迈入5G-A新时代.pptx

    C#学习之OpenCv实现模版匹配案例

    本文描述了如何使用C#基于OpenCvSharpe实现模版匹配功能,其中实现了下功能: 1、图像加载; 2、模版加载、绘制、保存功能; 3、模版匹配功能。

    【软件工程与数据分析】数据结构求职面试问题汇总:涵盖链表、树结构及算法复杂度分析的实战题目解析

    内容概要:本文档汇集了CSci 235软件设计与分析II课程中关于数据结构的面试题,由Stewart Weiss教授整理。文档涵盖了广泛的数据结构主题,包括但不限于链表(如单链表、双向链表、循环链表)、二叉树(如二叉搜索树、最小高度二叉搜索树)、栈、队列等。每个问题都旨在考察求职者对不同数据结构的理解及其应用场景。例如,选择合适的数据结构实现手机通讯录功能,或设计支持撤销功能的文本编辑器。此外,文档还探讨了复杂度分析(Big-O表示法),以及如何优化特定操作的时间复杂度。最后,文档提供了额外的学习资源链接,帮助求职者进一步准备面试。 适合人群:计算机科学专业的学生或有志于从事软件开发工作的求职者,特别是那些希望在技术面试中表现优异的人士。 使用场景及目标:①理解并掌握常见数据结构的基本概念和特性;②学会根据不同场景选择最合适的数据结构;③掌握常见数据结构操作的时间复杂度分析;④为技术面试做充分准备,提高面试成功率。 其他说明:文档中的问题不仅限于理论知识,还包括实际编码练习,建议读者在学习过程中动手实践,以加深理解和记忆。同时,文档提供的额外资源链接可以作为扩展阅读材料,帮助读者更全面地掌握相关知识。

    【路径规划】基于matlab A_Star融合灰狼算法GWO求解多仓库机器人送货路径规划【含Matlab源码 13134期】.zip

    Matlab领域上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    帆软本地打印插件FinePrint 8.0版本

    帆软本地打印插件FinePrint 8.0版本,适用于FineReport8

    【嵌入式控制系统】基于EECS461课程的嵌入式控制技术在汽车领域的应用与发展:从基础概念到未来挑战了文档的主要内容

    内容概要:本文介绍了密歇根大学EECS 461课程——嵌入式控制系统的核心内容及其发展背景。课程旨在教授学生嵌入式控制系统的理论与实践,包括传感器和执行器接口、实时性能和安全要求、混合行为系统、分布式控制网络等方面的知识。文中特别强调了现代汽车作为嵌入式控制系统的典型应用,从1977年到2019年间,汽车技术经历了从模拟控制到微处理器控制的巨大变革,如今的汽车具备了更高效、更环保、更安全的特点。课程还涵盖了S32K144微控制器的开发环境、实验室练习(如数字I/O、PWM信号生成、虚拟墙模拟等)以及自动代码生成工具的使用。 适合人群:具备一定编程基础,特别是对嵌入式系统感兴趣的本科生和研究生,尤其是电气工程、计算机科学专业的高年级学生或硕士生。 使用场景及目标:①了解嵌入式控制系统的基本概念和发展历程;②掌握嵌入式控制系统的设计方法和技术手段,如实时操作系统、中断处理、网络通信协议(CAN)等;③通过实际项目操作,熟悉嵌入式硬件平台和开发工具链的应用。 其他说明:随着汽车行业向智能化、自动化方向发展,对于能够开发复杂嵌入式软件的人才需求日益增长。EECS 461不仅为学生提供了扎实的技术训练,也为他们未来的职业发展打下了坚实的基础。此外,课程还反映了跨学科教育的重要性,鼓励学生打破传统学术界限,培养解决实际问题的能力。

    C#与Halcon联合编程实现高效视觉几何定位与测量框架

    内容概要:本文详细介绍了如何利用C#与Halcon联合编程构建高效的视觉几何定位与测量框架。主要内容涵盖模板创建与匹配、圆测量、数据持久化以及图像采集等方面的技术细节。首先,通过创建形状模板并进行匹配,实现了工件的精确定位。接着,针对圆形物体的测量,提出了动态ROI绘制、亚像素边缘提取和稳健圆拟合的方法。此外,还讨论了模板管理和图像采集的最佳实践,确保系统的稳定性和高效性。最后,强调了Halcon对象的内存管理和错误处理机制,提供了实用的优化建议。 适合人群:具备一定编程基础,尤其是对C#和Halcon有一定了解的研发人员和技术爱好者。 使用场景及目标:适用于工业生产线上的自动化检测设备开发,旨在提高工件定位和尺寸测量的精度与效率。主要目标是帮助开发者掌握C#与Halcon联合编程的具体实现方法,从而构建稳定可靠的视觉检测系统。 其他说明:文中提供了大量实战代码片段和调试技巧,有助于读者快速理解和应用相关技术。同时,作者分享了许多实际项目中的经验和教训,使读者能够避开常见陷阱,提升开发效率。

    【人工智能领域】DeepSeek AI核心技术优势及广泛应用场景:推动全球AI创新与产业变革

    内容概要:本文深入探讨了DeepSeek AI的独特优势及其在全球AI领域的影响力。DeepSeek由中国深度求索公司开发,自2025年1月20日发布以来,凭借其卓越的性能和独特优势迅速吸引了全球关注。其核心优势包括:1) 极致成本效率,如低成本训练和高效推理;2) 强大的推理能力,涵盖多领域表现优异

    php连接sqlserver之VC-redist.x64.exe

    php连接sqlserver之VC_redist.x64.exe

    基于Matlab/Simulink的异步电动机恒压频比与转差频率控制仿真及其实现

    内容概要:本文详细介绍了利用Matlab/Simulink进行异步电动机交流调速系统的仿真实验,主要探讨了两种控制方式:恒压频比(V/F)开环控制和转差频率闭环控制。文中不仅提供了具体的数学模型和代码片段,还展示了不同控制方式下的仿真结果对比,包括转速响应、电流波形和谐波含量等方面的表现。此外,文章深入讲解了SVPWM(空间矢量脉宽调制)的应用,强调了其相对于传统SPWM的优势,并给出了详细的参数调整技巧和注意事项。 适合人群:从事电机控制系统设计的研究人员和技术人员,尤其是对Matlab/Simulink有一定基础并希望深入了解异步电动机调速系统的人群。 使用场景及目标:适用于需要进行电机控制算法开发和优化的场合,旨在帮助读者掌握异步电动机调速的基本原理和具体实现方法,提高仿真的准确性和效率。 其他说明:文章通过丰富的实例和图表,生动地展示了各种控制策略的特点和效果,有助于读者更好地理解和应用相关理论。同时,文中提供的调试技巧对于解决实际工程中的常见问题非常有帮助。

    电动汽车等速工况续驶里程仿真及Matlab实现详解

    内容概要:本文详细介绍了如何利用Matlab进行电动汽车等速工况续驶里程的仿真。首先解释了等速工况的概念及其重要性,接着展示了具体的参数设定,如车辆质量、风阻系数、电池容量等。然后深入探讨了核心算法,包括阻力计算、功率需求、能量消耗以及SOC(剩余电量)的变化过程。文中特别强调了一些常见的陷阱和注意事项,如单位换算错误、电机效率的动态变化等。最后,通过可视化工具展示了仿真结果,并讨论了可能的改进方向,如引入NEDC工况循环和其他动态因素。 适合人群:新能源汽车专业的学生、研究人员以及对电动汽车仿真感兴趣的工程师。 使用场景及目标:①帮助理解和掌握电动汽车等速工况续驶里程仿真的原理和方法;②提供详细的代码实现和注释,便于学习和修改;③用于课程设计、毕业设计或其他研究项目。 其他说明:本文不仅提供了完整的Matlab代码,还包括详细的参数说明和常见问题解析,确保使用者能够顺利运行并理解整个仿真过程。同时,作者还分享了许多实践经验,有助于提高仿真的准确性和实用性。

    【定稿】桂林电子科技大学第七届大学生思政课社会实践优秀成果展示活动实施方案 (1).zip

    【定稿】桂林电子科技大学第七届大学生思政课社会实践优秀成果展示活动实施方案 (1).zip

    直线感应电机瞬态磁场仿真教程:Maxwell 16.0与ANSYS 2020关键技术解析

    内容概要:本文详细介绍了使用Maxwell 16.0和ANSYS 2020进行直线感应电机瞬态磁场仿真的方法和技术要点。首先强调了建模前的准备工作,包括初级线圈布置、次级导体材料选择、气隙宽度等参数的确定。然后针对Maxwell 16.0用户,讲解了坐标系的选择(笛卡尔坐标系)、初级绕组绘制、运动参数设置、网格剖分优化以及边界条件的正确配置。对于ANSYS 2020用户,则着重讲述了如何利用Maxwell模块建立模型并在Mechanical中进行电磁力耦合分析,包括参数化扫描设置、气隙厚度扫描、磁密云图动态更新等技巧。此外,文中还分享了许多实用的经验和注意事项,如避免常见的参数设置错误、提高仿真精度的方法、处理推力波动等问题的具体措施。 适合人群:从事电机设计与仿真的工程师、研究人员,尤其是有一定Maxwell和ANSYS使用基础的技术人员。 使用场景及目标:帮助用户掌握直线感应电机瞬态磁场仿真的全流程,确保仿真结果的准确性,提升工作效率。具体应用场景包括但不限于新电机设计验证、现有电机性能优化、故障诊断等。 其他说明:文中提供了大量具体的命令和脚本示例,便于读者直接应用到实际工作中。同时,作者结合自身丰富的实践经验,给出了许多宝贵的建议和警示,有助于读者避开常见陷阱,顺利完成仿真任务。

    基于Matlab Simulink的交流异步电机矢量控制与SVPWM仿真建模及优化

    内容概要:本文详细介绍了如何在Matlab Simulink中构建交流异步电机的矢量控制模型及其SVPWM调制方法。首先解释了坐标变换(如Clarke和Park变换)的基本原理,并提供了具体的实现代码。接着讨论了双闭环控制策略,即电流环和速度环的设计与参数整定,强调了PI控制器的抗饱和处理以及速度环带宽的选择。对于SVPWM部分,文章对比了几种不同的调制算法,推荐了一种改进的七段式算法,提高了电压利用率并降低了谐波含量。此外,文中还分享了许多实际调试过程中遇到的问题及解决方案,如启动电流冲击、低频振荡等。 适合人群:从事电力电子、电机驱动系统设计的研究人员和技术工程师,尤其是对矢量控制和SVPWM感兴趣的初学者。 使用场景及目标:适用于需要深入了解交流异步电机矢量控制原理及其实现方法的人群。目标是在掌握理论基础上,能够独立搭建并优化Simulink仿真模型,从而提高实际应用中的性能表现。 其他说明:随文提供的工程文件包含了完整的模型和详细的参数整定表格,便于读者进行实践操作。同时,作者还提供了一些实用的小贴士,帮助避免常见的错误和陷阱。

Global site tag (gtag.js) - Google Analytics