国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C# > 正文

C#制作簡單的多人在線即時交流聊天室

2020-01-24 01:22:34
字體:
來源:轉載
供稿:網友

實現網頁版的在線聊天室的方法有很多,在沒有來到HTML5之前,常見的有:定時輪詢、長連接+長輪詢、基于第三方插件(如FLASH的Socket),而如果是HTML5,則比較簡單,可以直接使用WebSocket,當然HTML5目前在PC端并沒有被所有瀏覽器支持,所以我的這個聊天室仍是基于長連接+長輪詢+原生的JS及AJAX實現的多人在線即時交流聊天室,這個聊天室其實是我上周周末完成的,功能簡單,可能有些不足,但可以滿足在線即時聊天需求,分享也是給大家提供一個思路,大家可以基于此來實現更好的在線即時聊天工具。

聊天室功能簡介:

1。支持多人進入同一個聊天室聊天;

2。進入即離線均會自動生成通知信息顯示在聊天室中,這樣聊天的人們就知道誰進來了誰離開了;

3。實時顯示在線人員表列;

4。無需數據庫支持,全部存在內存中,當然有條件的可以采用分布式緩存或加一個數據庫來存,這里演示就是用內存來存了。

下面就開始分享我的代碼,由于采用原生的JS及AJAX,所以簡單易懂,代碼分別WEB前端及服務端(有點廢話了)

WEB前端源代碼如下:(ChatPage.html)

<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head>  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  <title></title>  <style type="text/css">    html, body {      margin: 0px;      padding: 0px;      width: 100%;      height: 100%;      background-color: #f8f7f7;      font-family: arial,sans-serif;    }     #layouttable {      margin:0px;      padding:0px;      width:100%;      height:100%;      border:2px solid green;      border-collapse:collapse;      min-width:800px;    }       #layouttable td {        border: 1px solid green;      }     .h100p {      height:100%;    }     .midtr{height:auto;}      .midtr tr td {        height: 100%;      }     #chatmsgbox, #chatonlinebox {      background-color:white;      overflow-x: hidden;      overflow-y: auto;      overflow-wrap: break-word;      height: 100%;    }     #chatonlinebox {      background-color:#f5d0a8;    }     .rc, .sd {      overflow:hidden;    }      .rc p {      float: left;      color: green;    }      .sd p {        float: right;        color: orange;      }  </style> </head><body>  <table id="layouttable">    <colgroup>      <col style="width:auto" />      <col style="width: 200px;" />    </colgroup>    <tr style="height:30px; background-color:lightblue;color:yellow;">      <td>        歡迎進入夢在旅途的網頁即時在線大眾聊天室 - www.zuowenjun.cn:      </td>      <td>        當前在線人員      </td>    </tr>    <tr style="height:auto;" id="midtr">      <td>        <div id="chatmsgbox">        </div>      </td>      <td>        <div id="chatonlinebox">          <ul id="chatnames"></ul>        </div>      </td>    </tr>    <tr style="height:50px;">      <td colspan="2">        <label for="name">聊天妮稱:</label>        <input type="text" id="name" style="width:80px;" />        <input type="button" id="btnsavename" value="確認進入" />        <label for="msg">輸入內容:</label>        <input type="text" id="msg" style="width:400px;" />        <input type="button" id="btnSend" value="發送消息" disabled="disabled" />      </td>    </tr>  </table>  <script type="text/javascript">    var chatName = null;    var oChatmsgbox, oMsg, oChatnames;    var ajaxforSend, ajaxforRecv;     //頁面加載初始化    window.onload = function () {      document.getElementById("btnsavename").onclick = function () {        this.disabled = true;        var oName = document.getElementById("name");        oName.readOnly = true;        document.getElementById("btnSend").disabled = false;        //receiveMsg();        setChatStatus(oName.value,"on");      }       document.getElementById("btnSend").onclick = function () {        sendMsg(oMsg.value);      };       //init      oChatmsgbox = document.getElementById("chatmsgbox");      oMsg = document.getElementById("msg");      oChatnames = document.getElementById("chatnames");      ajaxforSend = getAjaxObject();      ajaxforRecv = getAjaxObject();    }     //離開時提醒    window.onbeforeunload = function () {      event.returnValue = "您確定要退出聊天室嗎?";    }     //關閉時離線    window.onunload = function () {      setChatStatus(chatName, "off");    }     //設置聊天狀態:在線 OR 離線    function setChatStatus(name, status) {      callAjax(getAjaxObject(), "action=" + status + "&name=" + name, function (rs) {        if (!rs.success) {          alert(rs.info);          return;        }        if (status == "on") {          chatName = document.getElementById("name").value;          setTimeout("receiveMsg()",500);        }        loadOnlineChatNames();      });    }     //加載在線人員名稱列表    function loadOnlineChatNames(){      callAjax(getAjaxObject(), "action=onlines", function (rs) {        var lis = "";        for(var i=0;i<rs.length;i++)        {          lis += "<li>"+ rs[i] +"</li>";        }        oChatnames.innerHTML = lis;      });    }     //接收消息列表    function receiveMsg() {      callAjax(ajaxforRecv, "action=receive&name=" + chatName, function (rs) {        if (rs.success) {          showChatMsgs(rs.msgs, "rc");        }        setTimeout("receiveMsg()", 500);      });    }    //發送消息    function sendMsg(msg) {      callAjax(ajaxforSend, "action=send&name=" + chatName + "&msg=" + escape(msg), function (rs) {        if (rs.success) {          showChatMsgs(rs.msgs, "sd");          oMsg.value = null;          //alert("發送成功!");        }      });    }     //顯示消息    function showChatMsgs(msgs, cssClass) {      var loadonline = false;      for (var i = 0; i < msgs.length; i++) {        var msg = msgs[i];        oChatmsgbox.innerHTML += "<div class='" + cssClass + "'><p>[" + msg.name + "] - " + msg.sendtime + " 說:<br/>" + msg.content + "</p></div>";        if (msg.type == "on" || msg.type == "off")        {          loadonline = true;        }      }      if (loadonline)      {        loadOnlineChatNames();      }    }     //調用AJAX    function callAjax(ajax, param, callback) {       ajax.open("post", "ChatHandler.ashx", true);      ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");      ajax.onreadystatechange = function () {        if (ajax.readyState == 4 && ajax.status == 200) {          var json = eval("(" + ajax.responseText + ")");          callback(json);        }      };      ajax.send(param);    }     //獲取AJAX對象(XMLHttpRequest)    function getAjaxObject() {      var xmlhttp;      if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari        xmlhttp = new XMLHttpRequest();      }      else {// code for IE6, IE5        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");      }      return xmlhttp;    }   </script></body></html>

代碼很簡單,并都有注釋,在此就不作說明了,如果有疑問歡迎在下方評論。

服務端(ChatHandler.ashx) 

<%@ WebHandler Language="C#" Class="ChatHandler" %> using System;using System.Web;using System.Collections;using System.Collections.Generic;using System.Linq;using System.Web.Script.Serialization;using System.Threading;using System.Collections.Concurrent; public class ChatHandler : IHttpHandler{   private class Msg  {    public string name { get; set; }    public string sendtime { get; set; }    public string content { get; set; }    public string readednams { get; set; }    public int readedCount { get; set; }    public string type { get; set; }  }   private static List<Msg> msgs = new List<Msg>();  private static ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();  private static object syncObject = new object(),syncObject1 = new object();  private static List<string> onLineNames = new List<string>();   public void ProcessRequest(HttpContext context)  {    string chatName = context.Request.Form["name"];    string msg = context.Request.Form["msg"];    string actionName = context.Request.Form["action"];    JavaScriptSerializer jsSerializer = new JavaScriptSerializer();     object responseObject = null;     switch (actionName)    {      case "receive":        {          responseObject = GetNewMessages(chatName);          break;        }      case "send":        {          responseObject = SendMessage(chatName, msg, "normal");          break;        }      case "on":      case "off":        {          responseObject = SetChatStatus(chatName, actionName);          break;        }      case "onlines":        {          responseObject = onLineNames;          break;        }    }     context.Response.ContentType = "text/json";    context.Response.Write(jsSerializer.Serialize(responseObject));   }   private object SetChatStatus(string chatName, string status)  {    if (status == "on")    {      if (onLineNames.Exists(s => s == chatName))      {        return new { success = false, info = "該聊天妮稱已經存在,請更換一個名稱吧!" };      }      lock (syncObject1)      {        onLineNames.Add(chatName);      }      SendMessage(chatName, "大家好,我進入聊天室了!", status);      return new { success = true, info = string.Empty };    }    else    {      lock (syncObject1)      {        onLineNames.Remove(chatName);      }      SendMessage(chatName, "再見,我離開聊天室了!", status);      return new { success = true, info = string.Empty };    }  }   /// <summary>  /// 獲取未讀的新消息  /// </summary>  /// <param name="chatName"></param>  /// <returns></returns>  private object GetNewMessages(string chatName)  {    //第一種:循環處理    while (true)    {       var newMsgs = msgs.Where(m => m.name != chatName && !(m.readednams ?? "").Contains(chatName)).OrderBy(m => m.sendtime).ToList();      if (newMsgs != null && newMsgs.Count() > 0)      {        lock (syncObject)        {          newMsgs.ForEach((m) =>          {            m.readednams += chatName + ",";            m.readedCount++;          });          int chatNameCount = onLineNames.Count();          msgs.RemoveAll(m => m.readedCount >= chatNameCount);        }         return new { success = true, msgs = newMsgs };      }       Thread.Sleep(1000);    }      //第二種方法,采用自旋鎖    //List<Msg> newMsgs = null;    //SpinWait.SpinUntil(() =>    //{    //  newMsgs = msgs.Where(m => m.name != chatName && !(m.readednams ?? "").Contains(chatName)).OrderBy(m => m.sendtime).ToList();    //  return newMsgs.Count() > 0;    //}, -1);     //rwLock.EnterWriteLock();    //newMsgs.ForEach(m =>    //{    //  m.readednams += chatName + ",";    //  m.readedCount++;    //});    //rwLock.ExitWriteLock();    //return new { success = true, msgs = newMsgs };  }   /// <summary>  ///  /// </summary>  /// <param name="chatName"></param>  /// <param name="msg"></param>  /// <returns></returns>  private object SendMessage(string chatName, string msg, string type)  {    var newMsg = new Msg() { name = chatName, sendtime = DateTime.Now.ToString("yyyy/MM/dd HH:mm"), content =HttpContext.Current.Server.HtmlEncode(msg), readednams = null, type = type };    //rwLock.EnterWriteLock();    lock (syncObject)    {      msgs.Add(newMsg);    }    //rwLock.ExitWriteLock();    return new { success = true, msgs = new[] { newMsg } };  }     public bool IsReusable  {    get    {      return false;    }  } }

代碼也相對簡單,實現原理主要是:

1。聊天消息:循環獲取未讀的消息,在取出讀的消息同時,將其標識為已讀,全部已讀的消息則刪除;--我這里采用了兩種方法,第二種方法被注釋掉了,大家可以取消注釋試試,也是不錯的,比第一種更直觀,建議使用;

2。發送消息:實例化一個消息實例并加入到聊天消息集合中;

3。狀態切換:上線則加入到在線人員集合中,并生成一條上線消息放入到聊天消息集合中,離線則從在線人員集合中移除該人員信息,并生成一條離線消息放入聊天消息集合中;

注意事項,由于采用了全局靜態集合,所以線程同步比較重要。

最終的實現效果展示如下:

 張三:

李四:

小美:

如果覺得不錯的話,給個推薦吧,你的支持是推動我不斷前進的動力及寫作的源泉,我一直堅持:知識在于分享,分享的同時自己也在成長,希望與大家共同成長,謝謝!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 高雄县| 青阳县| 儋州市| 偃师市| 万山特区| 杭州市| 华宁县| 那坡县| 大渡口区| 常山县| 米林县| 湖南省| 阿城市| 闻喜县| 繁昌县| 阿拉善盟| 通渭县| 五峰| 扎赉特旗| 苏州市| 水城县| 宜阳县| 兰溪市| 翼城县| 宁南县| 靖远县| 略阳县| 金乡县| 忻城县| 利川市| 满城县| 延寿县| 天长市| 沐川县| 楚雄市| 天柱县| 偏关县| 隆昌县| 宁陵县| 邻水| 喀喇沁旗|