OA的即时通讯原理及案例,希望大家能给我点启发。
类似于通达OA:http://oa.tongda2000.com:81

解决方案 »

  1.   


    基本就是轮询,http协议只能这样,或者借助 flash/flex/sl 等插件。
      

  2.   

    ajax轮询
    服务端类       protected void Application_Start(object sender, EventArgs e)
            {
                //初始化  短消息类用于定时轮询!
                Application["TheGlobalMsg"] = new TheGlobalMsgs();
            }    public class TheGlobalMsgs
        {
            const long timerDelay = 60000;//定时器过期时间60秒(1分钟内的短消息保留),客户端最长每30秒一取!        Timer theTimer;
            public static DataTable theMsgsTable = null;
            public TheGlobalMsgs()
            {
                theMsgsTable = new DataTable("TheMsgTable");        //|    建立表, 表名:"TheMsgsTable"
                //System.Data.DataColumn Column1 = new DataColumn("id", typeof(System.Int64)); //|    建立字段, 字段名:"id", 类型: int
                System.Data.DataColumn Column2 = new DataColumn("msgText", typeof(System.String));
                System.Data.DataColumn Column3 = new DataColumn("GetUserID", typeof(System.String));
                System.Data.DataColumn Column4 = new DataColumn("SendUserID", typeof(System.String));
                System.Data.DataColumn Column5 = new DataColumn("SendUserName", typeof(System.String));
                System.Data.DataColumn Column6 = new DataColumn("SendTime", typeof(System.DateTime));            //Column1.AutoIncrement = true;    //| 设置自增ID
                //Column1.AutoIncrementSeed = 1;    //|    ID 起始值
                //Column1.AutoIncrementStep = 1;    //|    递增量            //theMsgsTable.Columns.Add(Column1);
                theMsgsTable.Columns.Add(Column2);
                theMsgsTable.Columns.Add(Column3);
                theMsgsTable.Columns.Add(Column4);
                theMsgsTable.Columns.Add(Column5);
                theMsgsTable.Columns.Add(Column6);
                //设置主键
                //theMsgsTable.PrimaryKey = new System.Data.DataColumn[] { Column1 };            TimerCallback OnTimerTick = new TimerCallback(TimerTick);
                theTimer = new Timer(OnTimerTick, null, timerDelay, timerDelay);        }        /// <summary>
            /// 定时期过期方法 删除表中的两分钟以前的过期值
            /// </summary>
            /// <param name="state"></param>
            private void TimerTick(object state)
            {
                DataView theDV = new DataView(theMsgsTable);
                theDV.AllowDelete = true;
                theDV.AllowEdit = true;
                theDV.AllowNew = true;
                theDV.RowFilter = "SendTime < #" + DateTime.Now.AddMilliseconds(-120000).ToLongTimeString() + "#" ;
                for (int i = 0; i < theDV.Count; i++)
                {
                    theDV.Delete(i);
                }
                theMsgsTable.AcceptChanges();
            }        /// <summary>
            /// 向内存表中添加一个消息
            /// </summary>
            /// <param name="inp_SendUser_ID"></param>
            /// <param name="inp_SendUser_Name"></param>
            /// <param name="inp_GetUser_ID"></param>
            /// <param name="inp_TheMsgText"></param>
            /// <returns></returns>
            public bool AddMsg(string inp_SendUser_ID, string inp_SendUser_Name, string inp_GetUser_ID, string inp_TheMsgText)
            {
                if (inp_GetUser_ID == null || inp_GetUser_ID == "" || !DAL.DBBase.IsInt(inp_GetUser_ID) || inp_TheMsgText == null || inp_TheMsgText == "")
                {
                    return false;
                }
                if (inp_SendUser_ID != null && inp_SendUser_ID != "")
                {
                    if (!DAL.DBBase.IsInt(inp_SendUser_ID))
                    {
                        return false;
                    }
                }            System.Data.DataRow theRow = theMsgsTable.NewRow();     //新行;
                //theRow[id] = ""; 行ID可以自加得到!!!!
                theRow["msgText"] = inp_TheMsgText;                   
                theRow["GetUserID"] = inp_GetUser_ID;
                theRow["SendUserID"] = inp_SendUser_ID;
                theRow["SendUserName"] = inp_SendUser_Name;
                theRow["SendTime"] = System.DateTime.Now;
                theMsgsTable.Rows.Add(theRow);    // 将该行数据添加进表
                theMsgsTable.AcceptChanges();
                return true;
            }        /// <summary>
            /// 得到发给某人的短消息
            /// </summary>
            /// <param name="inp_GetUser_ID">某人的ID</param>
            /// <returns>DataTable</returns>
            public DataTable GetSomeBodyMsgs(string inp_GetUser_ID)
            {
                DataTable theBackTable = null;
                if (inp_GetUser_ID != null && inp_GetUser_ID != "" && DAL.DBBase.IsInt(inp_GetUser_ID))
                {
                    DataView theDV = new DataView(theMsgsTable);
                    theDV.AllowDelete = true;
                    theDV.AllowEdit = true;
                    theDV.AllowNew = true;
                    theDV.RowFilter = "GetUserID = " + inp_GetUser_ID;
                    theDV.Sort = "SendTime";
                    theBackTable = theDV.ToTable();//从视图中取值
                    for (int i = 0; i < theDV.Count; i++)
                    {
                        theDV.Delete(i);
                    }
                    theMsgsTable.AcceptChanges();
                }
                return theBackTable;
            }
        }
      

  3.   


    <%@ Page Title="" Language="C#" MasterPageFile="~/site.master" AutoEventWireup="true" CodeFile="Comet.aspx.cs" Inherits="Comet" %><asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" Runat="Server">
    </asp:Content>
    <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server">
        <script type="text/javascript">
            function SetTimer(p) {
                document.getElementById("time").innerHTML = p;
            }
        </script>
        <div id="time">
        
        </div>
    </asp:Content>using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;public partial class Comet : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {    }
        protected override void Render(HtmlTextWriter writer)
        {
            base.Render(writer);        Response.Buffer = true;
            bool isOutput = false;
            Response.Write("");        Response.Flush();        int lastsecond = 0;        while (Response.IsClientConnected)
            {
                System.Threading.Thread.Sleep(300);
                if (DateTime.Now.Second != lastsecond && !isOutput)
                {
                    lastsecond = DateTime.Now.Second;
                    Response.Write("<script> SetTime('" + DateTime.Now.ToString() + "')\n</script>");
                    Response.Flush();
                    isOutput = true;
                }
                else
                {
                    isOutput = false;
                }
            }
        }
    }刚写的这个能算是Comet(服务器推)技术吗?
      

  4.   

    谢谢4.5楼。
    我发现comet技术做OA应该挺不错。那位能给我贴一些这方面的代码学习下。
      

  5.   

    创建一个临时表一共能要几k内存我还真没统计过,你说的废资源不知从何谈起。只保存一分钟的数据的话。极端情况下,一千个话痨对另一千个在线用户不停的说话,一秒二句,内存表中也不过存了1000*2*60条=12000条。好吧,不算了,就算占用内存200k好了。轮询的压力确实是有的。不过推比这个只大不小。而且更废内存。原来也想做个基于推的后来放弃了。服务器端维持一堆页面对象不回收才是内存杀手呢。你自己比较一下吧。要是想做推的话也不错,不过个人建议自己用socket实现一个。毕竟,aspx是http页面的,我估计不会对长连接做优化。
      

  6.   

    socket 实现 http
      

  7.   

    你的资料好全。。
    多谢了。
    问下:通达的http://oa.tongda2000.com这个OA是用什么方法做的求解。
      

  8.   

    不是PHP么?有扩展名啊。你想问,怎么做?这个请问具体的问题,不要问的这么大。
      

  9.   

    没看对方的程序,可能是用的弹出模式窗口。或用jquery,或jquery控件弹的层模拟窗口。而且弹出窗口也可以指定不显示菜单等内容的。