AS3 Socket从零开始。

3 篇文章 0 订阅
最近项目到有点紧,有点对不住大家,今天在这里写点小知识算是向大家道歉!并祝大家在新的一年里有更大的收获!--FL狂人
大家如果想学AS3 Socket直接在百度里搜一下,会找到很多AS3与Java服务器的例子,很多朋友也许看得很糊涂,也有很多朋友看懂了,但想学更进一步的学习却又不好找教程了。这里我对网上常见的一个例子加点注释,并在原有的基础上加一些改动。转载请注明文章来自Aizna开源社区http://www.aizna.com/
先附上网上找的AS3客户端代码:
package
{
import flash.display.Sprite;
import flash.events.*;
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;
public const PORT:int = 5678; // 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.addEventListener( Event.CONNECT, onConnect );
btnSend.label = "Send Data";
btnSend.emphasized = true;
btnSend.width = 150;
btnSend.move(20, 20);
//addChild(btnSend); btnSend.addEventListener(MouseEvent.CLICK, sendData);
} private function sendData( event:Event )
{ if (! socket.connected)
{
// Connect to the server
socket.connect( "localhost", PORT );
} trace("send...");
socket.writeUTFBytes("example\n");
socket.flush(); } private function onConnect(event:Event):void
{
trace( "The socket is now connected..." ); } private function onSocketData( eventrogressEvent ):void
{
trace( "Socket received " + socket.bytesAvailable + " byte(s) of data:" );
//trace(socket.readMultiByte(socket.bytesAvailable, "UTF-8"));

// 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 readMultiByte( ):void
{
socket.readMultiByte(socket.bytesAvailable, "UTF-8");
} private function readNormalProtocol( ):void
{
// Step 5 - process the normal socket messages here now that
// that handshaking process is complete
}
}
}

java 服务端代码
import java.io.*;
import java.net.*;
public class SocketSever {
public static void main(String[] args) throws IOException{
ServerSocket server=new ServerSocket(5678); while (true) {
Socket client=server.accept();
BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out=new PrintWriter(client.getOutputStream());
//while(true){
String str=in.readLine();
System.out.println(str);
out.println("has receive….");
out.flush();
if("end".equals(str))
break;
//}
client.close();
}
}
}
 
 
测试的时候flash得先从组件里拉一个Button组件到舞台上,并取个实例名btnSend,然后先运行java服务端,再启动客户端,点击按钮就会看到连接成功的输出。
上面的代码显得有点乱,如果看不懂没关系,我们把上面的代码精简一下。
首先是AS3
如果我们要用Socket,得先导入import flash.net.Socket;这个包。如果我们把这个类当文档类来使用的话,需要导入import flash.display.Sprite;这个包。最后我们得是否连接成功这个事件,还得导入import flash.events.*;这个包。
所以代码如下:
package
{
import flash.display.Sprite;
import flash.events.*;
import flash.net.Socket;
public class Main
{ public function Main()
{
// constructor code
}
}
}
http://www.shengshiyouxi.com
第二步,我们需要建立一个Socket并作初始化,然后连接到服务器。加上上面的代码如下:
package
{
import flash.display.Sprite;
import flash.events.*;
import flash.net.Socket;
public class Main extends Sprite
{
private var socket:Socket;
public function Main()
{
socket = new Socket();
socket.connect( "localhost", 5678);
}
}
}

对应的Java服务端代码:
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) throws IOException{
ServerSocket server=new ServerSocket(5678);//建立一个Socket服务端。
server.accept();//等待客户端连接,如果没有客户端连接,
//程序会停在此行,而不会执行下一行。
System.out.println("客户端已连接!");//当有客户端连接上来的时候,
//打印输出客户端已连接。
}
}

以上代码可以说是最简单的Socket连接。
 
 
到这里,服务端代码暂时不管,先把给客户端的Socket加上事件,所以我们在连接到服务器前先加上以下两行代码:
socket.addEventListener(Event.CONNECT, onSocketConnect);//侦听Socket是否已连接上。
socket.addEventListener(Event.CLOSE, onSocketSeverClose);//侦听服务器是否已关闭。
然后写上事件的处理函数。
完整代码如下:
package
{
import flash.display.Sprite;
import flash.events.*;
import flash.net.Socket;
public class Main extends Sprite
{
private var socket:Socket;
public function Main()
{
socket = new Socket();//新建一个Socket

socket.addEventListener(Event.CONNECT, onSocketConnect);//侦听Socket是否已连接上。
socket.addEventListener(Event.CLOSE, onSocketSeverClose);//侦听服务器是否已关闭。

socket.connect( "localhost", 5678);//连接到服务器
}

private function onSocketConnect(e:Event):void
{
trace("已连接上服务器!");
}

private function onSocketSeverClose(e:Event):void
{
trace("服务器已关闭!");
}
}
}
 
 
启动服务端再测试下。发现我们刚连上服务器,服务器就关闭了。所以我们把服务端代码也改一下。
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) throws IOException{
ServerSocket server=new ServerSocket(5678);//建立一个Socket服务端。
while(true)
{
server.accept();//等待客户端连接,如果没有客户端连接,程序会停在此行,而不会执行下一行。
System.out.println("客户端已连接!");//当有客户端连接上来的时候,打印输出客户端已连接。
}
}
}

这里我只是在等待客户端连接的地方加了个死循环,这们服务端不会在有客户端连上来后自动关闭了,它会一直等等服务端的连接。大家可以再测试一下。
 
 
 
接下来,我们在连接服务器后,向服务器发送一个字符串。发送字符串会用到Socket的write方法和flush方法。write方法只是将要发送的信息存储起来,但没真正发送出去。而flush方法是将要发送的信息发送到数据流里。完整代码如下:
package
{
import flash.display.Sprite;
import flash.events.*;
import flash.net.Socket;
public class Main extends Sprite
{
private var socket:Socket;
public function Main()
{
socket = new Socket();//新建一个Socket

socket.addEventListener(Event.CONNECT, onSocketConnect);//侦听Socket是否已连接上。
socket.addEventListener(Event.CLOSE, onSocketSeverClose);//侦听服务器是否已关闭。

socket.connect( "localhost", 5678);//连接到服务器
}

private function onSocketConnect(e:Event):void
{
trace("已连接上服务器!");

//新加代码
socket.writeUTFBytes("abc\n");
socket.flush();
//新加代码

}

private function onSocketSeverClose(e:Event):void
{
trace("服务器已关闭!");
}
}
}
 
 
 
注意:发送的字符串必须加上\n不然服务端不能识别已输入已结束,当然,这只是针对于下面我们下面写的服务端代码而言。
对应的服务端代码如下:
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) throws IOException{
ServerSocket server=new ServerSocket(5678);//建立一个Socket服务端。
while(true)
{

Socket client=server.accept();//等待客户端连接,如果没有客户端连接,程序会停在此行,而不会执行下一行。
System.out.println("客户端已连接!");//当有客户端连接上来的时候,打印输出客户端已连接。
BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));
String str=in.readLine();
System.out.println(str);
}
}
}
 
 
接下来,服务端收到客户端发送的消息后也回一个字符串。有发就要有收,客户端也得同步写接收的语句。在此之前,先给客户端添加一个收到信息的事件侦听。
socket.addEventListener( ProgressEvent.SOCKET_DATA, onSocketData );//侦听服务端是否有消息发送过来。
然后写上事件处理函数
private function onSocketData(e:Event):void
{
var str:String = socket.readMultiByte(socket.bytesAvailable, "UTF-8");
trace(str);
}

完整代码如下:
package
{
import flash.display.Sprite;
import flash.events.*;
import flash.net.Socket;
public class Main extends Sprite
{
private var socket:Socket;
public function Main()
{
socket = new Socket();//新建一个Socket

socket.addEventListener(Event.CONNECT, onSocketConnect);//侦听Socket是否已连接上。
socket.addEventListener(Event.CLOSE, onSocketSeverClose);//侦听服务器是否已关闭。
socket.addEventListener( ProgressEvent.SOCKET_DATA, onSocketData );//侦听服务端是否有消息发送过来。

socket.connect( "localhost", 5678);//连接到服务器
}

private function onSocketConnect(e:Event):void
{
trace("已连接上服务器!");
socket.writeUTFBytes("abc\n");
socket.flush();
}

private function onSocketData(e:Event):void
{
var str:String = socket.readMultiByte(socket.bytesAvailable, "UTF-8");
trace(str);
}

private function onSocketSeverClose(e:Event):void
{
trace("服务器已关闭!");
}
}
}
 
 
 
 
对应的服务端代码如下:
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) throws IOException{
ServerSocket server=new ServerSocket(5678);//建立一个Socket服务端。
while(true)
{

Socket client=server.accept();//等待客户端连接,如果没有客户端连接,程序会停在此行,而不会执行下一行。
System.out.println("客户端已连接!");//当有客户端连接上来的时候,打印输出客户端已连接。
BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));
String str=in.readLine();
System.out.println(str);
PrintWriter out=new PrintWriter(client.getOutputStream());
out.println("cba");
out.flush();
}
}
}

小结:到这里算是写了一个简单的Socket连接,并实现了收发功能,如果从来没接触过Socket的朋友可以从上面的实例中学习Socket,通过上面的小实例可以看出,客户端和服务端必须保持一致,很多朋友学Socket的的难处就是不会写服务端程序,所以写出来的程序没法测试。而去下别人写好的服务端程序又没看懂,不知道如何写对应的客户端,所以就停步不学了。这里我建议有以上问题的朋友了解一下Java语言,学会自己学对应的服务端语言,Java语言和AS3差别不大,写服务端也很简单。相对来说要容易一些。

下面我们将上面的代码再进行扩展,实现通过按钮点击才连接服务器,然后通过按钮发送一个文本框里的输入的内容。算是一个聊天程序的粗雏形。在此之前希望还不太会的朋友多练习一下上面的代码,并通过自己的方式去实习,然后自己思考一下。如何实现我们刚提到的功能。
 
 
 
 
先在客户端加上两个按钮。并取个实例名btnConn和btnSend,然后在代码里添加按钮的点击事件,并且把socket的连接和发送消息写到两个按钮的点击事件处理函数里。

完整代码如下:
package
{
import flash.display.Sprite;
import flash.events.*;
import flash.net.Socket;
import flash.events.MouseEvent;
public class Main extends Sprite
{
private var socket:Socket;
public function Main()
{
socket = new Socket();//新建一个Socket

socket.addEventListener(Event.CONNECT, onSocketConnect);//侦听Socket是否已连接上。
socket.addEventListener(Event.CLOSE, onSocketSeverClose);//侦听服务器是否已关闭。
socket.addEventListener( ProgressEvent.SOCKET_DATA, onSocketData );//侦听服务端是否有消息发送过来。

btnConn.addEventListener(MouseEvent.CLICK, onBtnConnClick);
btnSend.addEventListener(MouseEvent.CLICK, onBtnSendClick);
}

private function onBtnConnClick(e:MouseEvent):void
{
socket.connect( "localhost", 5678);//连接到服务器
}

private function onBtnSendClick(e:MouseEvent):void
{
socket.writeUTFBytes("abc\n");
socket.flush();
}

private function onSocketConnect(e:Event):void
{
trace("已连接上服务器!");
}

private function onSocketData(e:Event):void
{
var str:String = socket.readMultiByte(socket.bytesAvailable, "UTF-8");
trace(str);
}

private function onSocketSeverClose(e:Event):void
{
trace("服务器已关闭!");
}
}
}

服务端代码不变,这时可以再测试一下。
 
 
 
注意:测试的时候一定要先连服务器,再发送数据,不然会出错。如果我们要让代码更人性化一些,可以在发送数据的时候测试一下Socket是否已连接上,所以我们可以加个Boolean变量,来记录Socket是否已连接。
完整代码如下:
package
{
import flash.display.Sprite;
import flash.events.*;
import flash.net.Socket;
import flash.events.MouseEvent;
public class Main extends Sprite
{
private var socket:Socket;
private var isConnect:Boolean = false;
public function Main()
{
socket = new Socket();//新建一个Socket socket.addEventListener(Event.CONNECT, onSocketConnect);
//侦听Socket是否已连接上。;
socket.addEventListener(Event.CLOSE, onSocketSeverClose);
//侦听服务器是否已关闭。;
socket.addEventListener( ProgressEvent.SOCKET_DATA, onSocketData );
//侦听服务端是否有消息发送过来。; btnConn.addEventListener(MouseEvent.CLICK, onBtnConnClick);
btnSend.addEventListener(MouseEvent.CLICK, onBtnSendClick);
} private function onBtnConnClick(e:MouseEvent):void
{
socket.connect( "localhost", 5678);//连接到服务器;
}

private function onBtnSendClick(e:MouseEvent):void
{
if (isConnect)
{
socket.writeUTFBytes("abc\n");
socket.flush();
}
else
{
trace("服务器没接连或已断开!")
}
} private function onSocketConnect(e:Event):void
{
trace("已连接上服务器!");
isConnect = true;
} private function onSocketData(e:Event):void
{
var str:String = socket.readMultiByte(socket.bytesAvailable,"UTF-8");
trace(str);
} private function onSocketSeverClose(e:Event):void
{
trace("服务器已关闭!");
isConnect = false;
}
}
}
 
 
 
现在我们再加两个文本框,一个用于我们输入信息。一个用来接收服务器发来的信息。这两个文本框分别写上实例名称为txtRecevie和txtInput。然后我们在事件发送数据和接收数据的地方做一点修改
onBtnSendClick函数修改如下:
private function onBtnSendClick(e:MouseEvent):void
{
if (isConnect)
{
var str:String = txtInput.text;
socket.writeUTFBytes(str + "\n");
socket.flush();
}
else
{
trace("服务器没接连或已断开!")
}
}

onSocketData函数修改如下:
private function onSocketData(e:Event):void
{
var str:String = socket.readMultiByte(socket.bytesAvailable,"UTF-8");
tctRecevie.text = str;
}
 
 
 
服务端我们也作相应的修改,把接收到的数据转发给客户端
将 out.println("cba");
改为 out.println(str);
然后大家可以测试一下。如果有收到你发出的字符串,说明代码写对了。
这里呢,我希望大家保存一下这个版本。因为接下来的改动会比较大,当然也会更像一个聊天程序。
 
 
 
接下来,
客户端Socket的数据发送不再用socket.writeUTFBytes();而改用socket.writeUTF();
而服务器也对应的将BufferedReader的readLine()方法改为用DataInputStream的readUTF()方法。

客户端完整代码如下:
package
{
import flash.display.Sprite;
import flash.events.*;
import flash.net.Socket;
import flash.events.MouseEvent;
public class Main extends Sprite
{
private var socket:Socket;
private var isConnect:Boolean = false;
public function Main()
{
socket = new Socket();//新建一个Socket socket.addEventListener(Event.CONNECT, onSocketConnect);
//侦听Socket是否已连接上。;
socket.addEventListener(Event.CLOSE, onSocketSeverClose);
//侦听服务器是否已关闭。;
socket.addEventListener( ProgressEvent.SOCKET_DATA, onSocketData );
//侦听服务端是否有消息发送过来。; btnConn.addEventListener(MouseEvent.CLICK, onBtnConnClick);
btnSend.addEventListener(MouseEvent.CLICK, onBtnSendClick);
} private function onBtnConnClick(e:MouseEvent):void
{
socket.connect( "localhost", 5678);//连接到服务器;
}

private function onBtnSendClick(e:MouseEvent):void
{
if (isConnect)
{
var str:String = txtInput.text;
//socket.writeUTFBytes(str + "\n");
socket.writeUTF(str);
socket.flush();
}
else
{
trace("服务器没接连或已断开!")
}
} private function onSocketConnect(e:Event):void
{
trace("已连接上服务器!");
isConnect = true;
} private function onSocketData(e:Event):void
{
var str:String = socket.readMultiByte(socket.bytesAvailable,"UTF-8");
tctRecevie.text = str;
} private function onSocketSeverClose(e:Event):void
{
trace("服务器已关闭!");
isConnect = false;
}
}
}

服务端完整代码如下:
import java.io.*;
import java.net.*;
public class Server {

public static void main(String[] args) throws IOException{
ServerSocket server=new ServerSocket(5678);//建立一个Socket服务端。
while(true)
{

Socket client=server.accept();//等待客户端连接,如果没有客户端连接,程序会停在此行,而不会执行下一行。
System.out.println("客户端已连接!");//当有客户端连接上来的时候,打印输出客户端已连接。
//BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));
//String str=in.readLine();
DataInputStream dis = new DataInputStream(client.getInputStream());
String str=dis.readUTF();
System.out.println(str);
PrintWriter out=new PrintWriter(client.getOutputStream());
out.println(str);
out.flush();
}
}
}

这里大家发现有几个问题,客户端发送数据后,输入框没有清空,而且数据只能发一次。下面我们处理一下这些问题。并且把客户端接受和服务端的发送也改一下。
客户端代码如下:
package
{
import flash.display.Sprite;
import flash.events.*;
import flash.net.Socket;
import flash.events.MouseEvent;
public class Main extends Sprite
{
private var socket:Socket;
private var isConnect:Boolean = false;
public function Main()
{
socket = new Socket();//新建一个Socket socket.addEventListener(Event.CONNECT, onSocketConnect);
//侦听Socket是否已连接上。;
socket.addEventListener(Event.CLOSE, onSocketSeverClose);
//侦听服务器是否已关闭。;
socket.addEventListener( ProgressEvent.SOCKET_DATA, onSocketData );
//侦听服务端是否有消息发送过来。; btnConn.addEventListener(MouseEvent.CLICK, onBtnConnClick);
btnSend.addEventListener(MouseEvent.CLICK, onBtnSendClick);
} private function onBtnConnClick(e:MouseEvent):void
{
socket.connect( "localhost", 5678);//连接到服务器;
}

private function onBtnSendClick(e:MouseEvent):void
{
if (isConnect)
{
var str:String = txtInput.text;
socket.writeUTF(str);
socket.flush();
txtInput.text = "";
}
else
{
trace("服务器没接连或已断开!")
}
} private function onSocketConnect(e:Event):void
{
trace("已连接上服务器!");
isConnect = true;
} private function onSocketData(e:Event):void
{
//var str:String = socket.readMultiByte(socket.bytesAvailable,"UTF-8");
var str:String = socket.readUTF();
tctRecevie.text = tctRecevie.text + str + "\n";
} private function onSocketSeverClose(e:Event):void
{
trace("服务器已关闭!");
isConnect = false;
}
}
}

服务端代码如下:
import java.io.*;
import java.net.*;
public class Server { public static void main(String[] args) throws IOException{
ServerSocket server=new ServerSocket(5678);//建立一个Socket服务端。
DataInputStream dis = null;
DataOutputStream dos = null;

while(true)
{ Socket client=server.accept();//等待客户端连接,如果没有客户端连接,程序会停在此行,而不会执行下一行。
System.out.println("客户端已连接!");//当有客户端连接上来的时候,打印输出客户端已连接。
while(true)
{
dis = new DataInputStream(client.getInputStream());
String str=dis.readUTF();
System.out.println(str);
dos = new DataOutputStream(client.getOutputStream());
dos.writeUTF(str);
}
}
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值