简单的对话聊天窗体组件

来源:互联网 发布:德州扑克入门知乎 编辑:程序博客网 时间:2024/05/16 05:54
这个也是前面博客 

php+as3简单聊天室这一篇许给大家的东西,本来是挂在我国外租用空间上的,去年国外空间费用调整,我没及时看到通知,所以挂在空间的一些东西丢失了,好在我源码一般都有备份,不过调试环境变化了 ,所以有些东西需要在本地重新配置环境,比如说这个东西,我当时在amfphp1.9+php5.2+mysql5环境下写的,但Php升5.26之后,对amfphp1.9不再支持了,所以这次,我又重新安装了一个低版本的阿帕奇+php环境,跟php+as3那篇博客差的时间有点长,这个东西其实就是玩具,没有任何实用价值,因为第一as3现阶段下行速度太明显,另外这个工具直接通过读写数据库来操作,如果是真实的项目,那么服务器的压力会很快吃不消,真正现在实用的工具,都是用redis和memcached这样的存储服务器来临时保存这么快速更新的数据,过一段时间,在同步到我们的真实数据库,也就是说把我这个东西的php部分用上面两个工具拿到服务器内存里面来工作,不过为什么没用还拿出来呢,因为写这东西的时候网络方面还没啥经验,另外这个工具也能一定程度上减少客户端的工作量,总比从0开始要好,小伙伴们可以根据这个工具的思路来写自己的聊天窗口,只要把这里的连接amfphp部分改成redis和memcached就可以了,当然go语言也可以,我们先看下运行结果

看这个演示,可能细心的小伙伴发现,他跟我前面写的那个聊天室的区别在于它有世界和帮派两个窗口,两个窗口接收的服务器信息是不同的,像不像梦幻西游的聊天窗体呢(当时我就是想山寨一个这样的组件),它是怎么做的呢,我们来看看,

<?phpclass flash_guest {public function flash_guest() { mysql_connect("localhost", "root", "root")or die("没找到数据库"); mysql_select_db("airdb")or die("连接数据库失败");} function addtobase($username, $userqq, $useremail, $usermessage) {$addto="INSERT INTO `airdb`.`guest` (`id` ,`username` ,`qq` ,`useremail` ,`usermessage` )VALUES ('', '".$username."', '".$userqq."', '".$useremail."', '".$usermessage."')";mysql_query($addto);return null;}function showmessage() {return mysql_query("SELECT * FROM `guest` ORDER BY `guest`.`id` DESC LIMIT 0 , 30");}}?>
这是服务器的php源码,过后我会跟amfphp1.9一起打包给大家,省的大家去网上找了,上面连接数据库的部分记得要自己改下,改成小伙伴自己本地的数据库登录,然后我们看看sql
-- phpMyAdmin SQL Dump-- version 3.1.3-- http://www.phpmyadmin.net---- 主机: localhost-- 生成日期: 2009 年 10 月 17 日 20:55-- 服务器版本: 5.1.32-- PHP 版本: 5.2.9-1SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;/*!40101 SET NAMES utf8 */;---- 数据库: `mydatabase`---- ------------------------------------------------------------ 表的结构 `guest`--CREATE TABLE IF NOT EXISTS `guest` (  `id` int(10) NOT NULL AUTO_INCREMENT,  `username` varchar(20) NOT NULL,  `qq` int(20) NOT NULL,  `useremail` varchar(25) NOT NULL,  `usermessage` text NOT NULL,  PRIMARY KEY (`id`)) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=41 ;---- 导出表中的数据 `guest`--INSERT INTO `guest` (`id`, `username`, `qq`, `useremail`, `usermessage`) VALUES(1, 'swordfishx82', 95766154, 'swordfishx@163.com', 'godness me');
把sql文件导入到数据库中,我们先在Mysql里面定义一个名为airdb的空库,然后导入


导入之后是这样的,然后我们看看amfphp1.9什么样子,

amfphp1.9之所以一直被国内开发者喜爱是因为,这个版本带了一个flash的可视化窗口工具,在2.0之后不知为啥,这个工具没有了,调试起来反而麻烦了,而且2.0版本之后链接取消了原来的gateway.php文件,直接连接index.php这个文件,我们看下客户端如何写的

左边代码注释的地方是我以前国外空间的地址,现在没用了,所以改成了下面的本地,工具的目录结构如右边,这里注意蓝色的lib,flcs4Component.swc是flash4的可视化组件库,因为as3里面缺少这些东西,所以我在flash5里面把可视化组件打成了swc包方便在as3里面使用,

看代码,
package {import flash.display.Sprite;import flash.events.Event;import TalkTip.TalkTip;/** * ... * @author swordfishx */public class Main extends Sprite {public function Main():void {if (stage) init();else addEventListener(Event.ADDED_TO_STAGE, init);}private function init(e:Event = null):void {removeEventListener(Event.ADDED_TO_STAGE, init);// entry pointaddChild(new TalkTip());}}}
文档类,这个是我的习惯,因为为了方便整合到其他地方,我总是喜欢,把做好的组件单提出来,让他可以直接new出来使用,所以文档类里面一直都会很干净,

package TalkTip{import fl.controls.Label;import flash.display.Bitmap;import flash.display.Sprite;import fl.controls.TextArea;import fl.controls.TextInput;import fl.controls.Button;import flash.events.MouseEvent;import flash.net.NetConnection;import flash.net.Responder;import flash.events.Event;/** * ... * @author swordfishx */public class TalkTip extends Sprite{[Embed(source="../../lib/TaikTipRes/xs.jpg")]private var TalkTipResxs:Class;[Embed(source="../../lib/TaikTipRes/xx.jpg")]private var TalkTipResxx:Class;private var htmstr:String = "<font color='#ff0000' size='25' face='宋体'>" + "健康游戏,抵制外挂" + "</font>"private var textareaheight:int = 150;//-------------------通讯-----------//private var mylocalhost:String = "http://swordfishx.freevar.com/amfphp/gateway.php";private var mylocalhost:String ="http://localhost/amfphp1.9/gateway.php";private var myconn:NetConnection;private var myresponder:Responder;//-------------------------------------private var imgxs:Bitmap = new TalkTipResxs();private var imgxx:Bitmap = new TalkTipResxx();private var button:Button = new Button();private var btnworld:Button = new Button();private var btnprivate:Button = new Button();private var textarea:TextArea = new TextArea();private var inputtxt:TextInput = new TextInput();private var nameinput:TextInput = new TextInput();private var emailinput:TextInput = new TextInput();private var qqinput:TextInput = new TextInput();private var qqname:Label = new Label();private var namelb:Label = new Label();//---------------------------------------------初始化private var TalkState:int = 0;//---------------------------------------public function TalkTip(){init();}private function init():void{textarea.x = 1;textarea.width = 300;textarea.height = textareaheight;textarea.htmlText = htmstr;textarea.alpha = 1;//-------------------------显示区域btnworld.width = 50;btnworld.label = "世界";btnworld.x = 1;btnworld.y = textarea.height + 1;btnprivate.width = 50;btnprivate.label = "帮派";btnprivate.x = btnworld.width + 1;btnprivate.y = textarea.height + 1;//-----------------------------连接切换imgxs.x = 250;imgxx.x = 250 + imgxs.width;imgxs.y = textarea.height + 1;imgxx.y = textarea.height + 3;//----------------------------布局inputtxt.x = 1;inputtxt.width = 250;inputtxt.y = textarea.height + 1 + btnprivate.height;button.width = 50;button.label = "发送";button.x = inputtxt.width + 1;button.y = textarea.height + 1 + btnprivate.height;//------------------------------------------------btnworld.addEventListener(MouseEvent.CLICK, btworldstate);btnprivate.addEventListener(MouseEvent.CLICK, btnprivatestate);button.addEventListener(MouseEvent.CLICK, onsub);//---------------------------qqname.text = "qq号码:";namelb.text = "名称:";qqname.x = 300;qqname.y = 1;namelb.x = 300;namelb.y = 100;nameinput.x = 300+qqname.width;nameinput.y = 100;qqinput.x = 300+qqname.width;qqinput.y = 1;//--------------------------addChild(button);addChild(textarea);addChild(btnworld);addChild(btnprivate);addChild(imgxs);addChild(imgxx);addChild(inputtxt);addChild(nameinput);addChild(qqinput);addChild(namelb);addChild(qqname);//addChild(emailinput);}private function btworldstate(evt:MouseEvent):void{TalkState = 0;onshow();trace("0");}private function btnprivatestate(evt:MouseEvent):void{TalkState = 1;onshow();trace("1");}private function onsub(evt:MouseEvent):void{myresponder = new Responder(onsubresult);myconn = new NetConnection();myconn.connect(mylocalhost);if (TalkState == 0){myconn.call("flash_guest.addtobase", myresponder, nameinput.text, int(qqinput.text), emailinput.text, inputtxt.text);}else if (TalkState == 1){myconn.call("flash_guest.addtobase", myresponder, nameinput.text, int(qqinput.text), inputtxt.text, inputtxt.text);}cleartext();}private function onshow():void{if (TalkState == 0){myresponder = new Responder(onshowresult, onshowstatus);}else if (TalkState == 1){myresponder = new Responder(onprivateshowresult, onshowstatus);}myconn = new NetConnection();myconn.connect(mylocalhost);myconn.call("flash_guest.showmessage", myresponder);}private function onshowresult(p:Object):void{textarea.text = "";var showarray:Array = new Array();showarray = p["serverInfo"]["initialData"];for (var i:uint; i < showarray.length; i++){//showmessage.text += "\n QQ:"+showarray[i][2];if (showarray[i][3] != ""){textarea.text += String("\n 昵称:" + showarray[i][1]);textarea.text += "\n 帮派:" + showarray[i][3];}else{textarea.text += String("\n 昵称:" + showarray[i][1]);textarea.text += "\n 世界:" + showarray[i][4];}textarea.text += "\n===================================";}}private function onprivateshowresult(p:Object):void{textarea.text = "";trace("帮派");var showarray:Array = new Array();showarray = p["serverInfo"]["initialData"];for (var i:uint; i < showarray.length; i++){if (showarray[i][3] != ""){textarea.text += String("\n 昵称:" + showarray[i][1]);textarea.text += "\n 帮派:" + showarray[i][3];textarea.text += "\n===================================";}}}private function onsubresult(p:Object):void{inputtxt.text = "提交成功!";onshow();}private function onshowstatus(p:Object):void{inputtxt.text = "连接出错";}private function cleartext():void{nameinput.text = "";qqinput.text = "";emailinput.text = "";inputtxt.text = "";}}}
代码并不多,我讲讲,amfphp是怎么工作的,首先
private var mylocalhost:String ="http://localhost/amfphp1.9/gateway.php";
这句连接amfphp,通知amfphp工作,然后我们以按钮为例看看他是如何通信的,
button.addEventListener(MouseEvent.CLICK, onsub);
这里鼠标监听onsub,

private function onsub(evt:MouseEvent):void{myresponder = new Responder(onsubresult);myconn = new NetConnection();myconn.connect(mylocalhost);if (TalkState == 0){myconn.call("flash_guest.addtobase", myresponder, nameinput.text, int(qqinput.text), emailinput.text, inputtxt.text);}else if (TalkState == 1){myconn.call("flash_guest.addtobase", myresponder, nameinput.text, int(qqinput.text), inputtxt.text, inputtxt.text);}cleartext();}
上面的call方法中这里调用了myresponder,它是amfphp核心responder类的一个实例

private function onsubresult(p:Object):void{inputtxt.text = "提交成功!";onshow();}
结果方法,在这个方法中有一个onshow(),

private function onshow():void{if (TalkState == 0){myresponder = new Responder(onshowresult, onshowstatus);}else if (TalkState == 1){myresponder = new Responder(onprivateshowresult, onshowstatus);}myconn = new NetConnection();myconn.connect(mylocalhost);myconn.call("flash_guest.showmessage", myresponder);}
这里把接收到数据分开,世界和帮派的数据不同就是因为这里,

myresponder = new Responder(onshowresult, onshowstatus);
这里有两个方法,前面的是有数据成功时的调用,后面是失败时的调用,

private function onshowresult(p:Object):void{textarea.text = "";var showarray:Array = new Array();showarray = p["serverInfo"]["initialData"];for (var i:uint; i < showarray.length; i++){//showmessage.text += "\n QQ:"+showarray[i][2];if (showarray[i][3] != ""){textarea.text += String("\n 昵称:" + showarray[i][1]);textarea.text += "\n 帮派:" + showarray[i][3];}else{textarea.text += String("\n 昵称:" + showarray[i][1]);textarea.text += "\n 世界:" + showarray[i][4];}textarea.text += "\n===================================";}}
private function onshowstatus(p:Object):void{inputtxt.text = "连接出错";}
如果看过烽烟ol客户端源码的小伙伴会发现,烽烟ol的源码是严格按这种模式来写的,甚至方法名都一样,不过烽烟ol用的是sokect连接,不要弄混了,

代码下载在这里
好了,最后我们说说,如何连接redis,memcached前面的博客有提到如何简单使用,go语言的话,因为它直接集成了memcached(不能叫集成,因为memcached作者是Go语言开发团队的一员,所以go语言直接包括了memcached的功能

以c#为例,连接

RedisClient client=new RedisClient("localhost",6379);

Set<string>(client,"username","swordfishx");

Set<int>(client,"pwd","123456");

client.Save();
Console.Ready();

这就是大概的redis保存流程,好了,我们下一篇再见。









0 0
原创粉丝点击