基于P2P的文本聊天
基本流程
Chat.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<s:layout>
<s:BasicLayout/>
</s:layout>
<fx:Script>
<![CDATA[
import mx.controls.Alert;
private var server:String = "rtmfp://stratus.rtmfp.net/";
private var key:String = "12d69cec5cef666f344ac2c1-2a5f71607b74";
private var netConn:NetConnection;
private var myStream:NetStream;
private var controlStream:NetStream;
private var outgoingStream:NetStream;
private var incomingStream:NetStream;
protected function btnConnect_clickHandler(event:MouseEvent):void
{
netConn = new NetConnection();
netConn.addEventListener(NetStatusEvent.NET_STATUS,netConnectHandler);
netConn.connect(server+key);
}
private function netConnectHandler(event:NetStatusEvent):void
{
if(event.info.code=="NetConnection.Connect.Success")
{
this.txtMessageList.text = "连接成功,您的peerID是:"+netConn.nearID;
//把自己的peerID用流发布出去
myStream = new NetStream(netConn,NetStream.DIRECT_CONNECTIONS);
myStream.addEventListener(NetStatusEvent.NET_STATUS,netStreamHandler);
myStream.publish(netConn.nearID);
var myObj:Object = new Object();
myObj.onPeerConnect = function(subscriberStream:NetStream):Boolean
{
txtMessageList.text += "\n有人连接我";
//播放对方的身份流
incomingStream = new NetStream(netConn,subscriberStream.farID);
incomingStream.addEventListener(NetStatusEvent.NET_STATUS,incomingStreamHandler);
incomingStream.play("caller");
var incomingObj:Object = new Object();
incomingObj.onIncomingCall = function(name:String):void
{
txtMessageList.text += "\n对方的名字是:"+name;
//发布自己的身份流
outgoingStream = new NetStream(netConn,NetStream.DIRECT_CONNECTIONS);
outgoingStream.addEventListener(NetStatusEvent.NET_STATUS,calleeStreamHandler);
outgoingStream.publish("callee");
}
incomingObj.onIm = function(name:String,message:String):void
{
txtMessageList.text += "\n"+name+":"+message;
}
incomingStream.client = incomingObj;
return true;
}
myStream.client = myObj;
}
}
protected function btnCall_clickHandler(event:MouseEvent):void
{
//发送自己的身份流
outgoingStream = new NetStream(netConn,NetStream.DIRECT_CONNECTIONS);
outgoingStream.addEventListener(NetStatusEvent.NET_STATUS,callerStreamHandler);
outgoingStream.publish("caller");
//呼叫对方
txtMessageList.text += "\n正在呼叫对方……";
controlStream = new NetStream(netConn,this.txtPeerID.text);
controlStream.addEventListener(NetStatusEvent.NET_STATUS, netStreamHandler);
controlStream.play(this.txtPeerID.text);
//接收对方的回发流
incomingStream = new NetStream(netConn,this.txtPeerID.text);
incomingStream.addEventListener(NetStatusEvent.NET_STATUS,incomingStreamHandler);
incomingStream.play("callee");
var incomingObj:Object = new Object();
incomingObj.onConnectSuccess = function(name:String):void
{
txtMessageList.text += "\n已与"+name+"连接成功";
}
incomingObj.onIm = function(name:String,message:String):void
{
txtMessageList.text += "\n"+name+":"+message;
}
incomingStream.client = incomingObj;
}
protected function btnSend_clickHandler(event:MouseEvent):void
{
//先本地显示自己的聊天内容
txtMessageList.text += "\n"+this.txtUserName.text+":"+this.txtMessage.text;
/**
* 如果是呼叫方的Send
* 1.这里的outgoingStream的名称是"caller"
* 2.需在接收方的onPeerConnect里指定onIm函数
*
* 如果是接收方的Send
* 1.这里的outgoingStream的名称是"callee"
* 2.虽然名称都为outgoingStream,但接收方回发自己的身份流时,被重新实例化了
* 3.需在发送方连接接收方时,在发送方的连接操作里,监听onIm事件
*/
outgoingStream.send("onIm",this.txtUserName.text,this.txtMessage.text);
this.txtMessage.text = "";
}
private function netStreamHandler(e:NetStatusEvent):void
{
}
private function callerStreamHandler(event:NetStatusEvent):void
{
//当有人播放我时
if(event.info.code=="NetStream.Play.Start")
{
outgoingStream.send("onIncomingCall",this.txtUserName.text);
}
}
private function calleeStreamHandler(event:NetStatusEvent):void
{
if(event.info.code=="NetStream.Publish.Start")
{
outgoingStream.send("onConnectSuccess",this.txtUserName.text);
}
}
private function incomingStreamHandler(event:NetStatusEvent):void
{
}
]]>
</fx:Script>
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<s:Panel title="P2P Test">
<s:layout>
<s:VerticalLayout paddingLeft="5" paddingRight="5" paddingBottom="5" paddingTop="5"/>
</s:layout>
<s:HGroup width="100%">
<s:Label width="50" text="用户名:" />
<s:TextInput id="txtUserName" width="200" text="胡晓伟" />
<s:Button id="btnConnect" label="链接" click="btnConnect_clickHandler(event)" />
</s:HGroup>
<s:HGroup width="100%">
<s:Label width="50" text="呼叫:" />
<s:TextInput id="txtPeerID" width="300" />
<s:Button id="btnCall" label="呼叫" click="btnCall_clickHandler(event)" />
</s:HGroup>
<s:HGroup width="100%">
<s:Label width="50" text="信息:" />
<s:TextInput id="txtMessage" width="200" />
<s:Button id="btnSend" label="发送" click="btnSend_clickHandler(event)" />
</s:HGroup>
<s:TextArea id="txtMessageList" width="100%"/>
</s:Panel>
</s:Application>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<s:layout>
<s:BasicLayout/>
</s:layout>
<fx:Script>
<![CDATA[
import mx.controls.Alert;
private var server:String = "rtmfp://stratus.rtmfp.net/";
private var key:String = "12d69cec5cef666f344ac2c1-2a5f71607b74";
private var netConn:NetConnection;
private var myStream:NetStream;
private var controlStream:NetStream;
private var outgoingStream:NetStream;
private var incomingStream:NetStream;
protected function btnConnect_clickHandler(event:MouseEvent):void
{
netConn = new NetConnection();
netConn.addEventListener(NetStatusEvent.NET_STATUS,netConnectHandler);
netConn.connect(server+key);
}
private function netConnectHandler(event:NetStatusEvent):void
{
if(event.info.code=="NetConnection.Connect.Success")
{
this.txtMessageList.text = "连接成功,您的peerID是:"+netConn.nearID;
//把自己的peerID用流发布出去
myStream = new NetStream(netConn,NetStream.DIRECT_CONNECTIONS);
myStream.addEventListener(NetStatusEvent.NET_STATUS,netStreamHandler);
myStream.publish(netConn.nearID);
var myObj:Object = new Object();
myObj.onPeerConnect = function(subscriberStream:NetStream):Boolean
{
txtMessageList.text += "\n有人连接我";
//播放对方的身份流
incomingStream = new NetStream(netConn,subscriberStream.farID);
incomingStream.addEventListener(NetStatusEvent.NET_STATUS,incomingStreamHandler);
incomingStream.play("caller");
var incomingObj:Object = new Object();
incomingObj.onIncomingCall = function(name:String):void
{
txtMessageList.text += "\n对方的名字是:"+name;
//发布自己的身份流
outgoingStream = new NetStream(netConn,NetStream.DIRECT_CONNECTIONS);
outgoingStream.addEventListener(NetStatusEvent.NET_STATUS,calleeStreamHandler);
outgoingStream.publish("callee");
}
incomingObj.onIm = function(name:String,message:String):void
{
txtMessageList.text += "\n"+name+":"+message;
}
incomingStream.client = incomingObj;
return true;
}
myStream.client = myObj;
}
}
protected function btnCall_clickHandler(event:MouseEvent):void
{
//发送自己的身份流
outgoingStream = new NetStream(netConn,NetStream.DIRECT_CONNECTIONS);
outgoingStream.addEventListener(NetStatusEvent.NET_STATUS,callerStreamHandler);
outgoingStream.publish("caller");
//呼叫对方
txtMessageList.text += "\n正在呼叫对方……";
controlStream = new NetStream(netConn,this.txtPeerID.text);
controlStream.addEventListener(NetStatusEvent.NET_STATUS, netStreamHandler);
controlStream.play(this.txtPeerID.text);
//接收对方的回发流
incomingStream = new NetStream(netConn,this.txtPeerID.text);
incomingStream.addEventListener(NetStatusEvent.NET_STATUS,incomingStreamHandler);
incomingStream.play("callee");
var incomingObj:Object = new Object();
incomingObj.onConnectSuccess = function(name:String):void
{
txtMessageList.text += "\n已与"+name+"连接成功";
}
incomingObj.onIm = function(name:String,message:String):void
{
txtMessageList.text += "\n"+name+":"+message;
}
incomingStream.client = incomingObj;
}
protected function btnSend_clickHandler(event:MouseEvent):void
{
//先本地显示自己的聊天内容
txtMessageList.text += "\n"+this.txtUserName.text+":"+this.txtMessage.text;
/**
* 如果是呼叫方的Send
* 1.这里的outgoingStream的名称是"caller"
* 2.需在接收方的onPeerConnect里指定onIm函数
*
* 如果是接收方的Send
* 1.这里的outgoingStream的名称是"callee"
* 2.虽然名称都为outgoingStream,但接收方回发自己的身份流时,被重新实例化了
* 3.需在发送方连接接收方时,在发送方的连接操作里,监听onIm事件
*/
outgoingStream.send("onIm",this.txtUserName.text,this.txtMessage.text);
this.txtMessage.text = "";
}
private function netStreamHandler(e:NetStatusEvent):void
{
}
private function callerStreamHandler(event:NetStatusEvent):void
{
//当有人播放我时
if(event.info.code=="NetStream.Play.Start")
{
outgoingStream.send("onIncomingCall",this.txtUserName.text);
}
}
private function calleeStreamHandler(event:NetStatusEvent):void
{
if(event.info.code=="NetStream.Publish.Start")
{
outgoingStream.send("onConnectSuccess",this.txtUserName.text);
}
}
private function incomingStreamHandler(event:NetStatusEvent):void
{
}
]]>
</fx:Script>
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<s:Panel title="P2P Test">
<s:layout>
<s:VerticalLayout paddingLeft="5" paddingRight="5" paddingBottom="5" paddingTop="5"/>
</s:layout>
<s:HGroup width="100%">
<s:Label width="50" text="用户名:" />
<s:TextInput id="txtUserName" width="200" text="胡晓伟" />
<s:Button id="btnConnect" label="链接" click="btnConnect_clickHandler(event)" />
</s:HGroup>
<s:HGroup width="100%">
<s:Label width="50" text="呼叫:" />
<s:TextInput id="txtPeerID" width="300" />
<s:Button id="btnCall" label="呼叫" click="btnCall_clickHandler(event)" />
</s:HGroup>
<s:HGroup width="100%">
<s:Label width="50" text="信息:" />
<s:TextInput id="txtMessage" width="200" />
<s:Button id="btnSend" label="发送" click="btnSend_clickHandler(event)" />
</s:HGroup>
<s:TextArea id="txtMessageList" width="100%"/>
</s:Panel>
</s:Application>