WebSocket 網頁聊天室的實現(伺服器端:.net + windows服務,前端:Html5)

來源:互聯網
上載者:User

標籤:最簡   連接埠   nbsp   keyword   basic   ref   href   ack   port   

websocket是HTML5中的比較有特色一塊,它使得以往在用戶端軟體中常用的socket在web程式中也能輕鬆的使用,較大的提高了效率。廢話不多說,直接進入題。

網頁聊天室包括2個部分,後端伺服器+前端頁面。 
1、後端服務部分:.net4.0 + windows服務。相比寄宿在iis中,寄宿在進程中的windows服務更加的穩定可靠(文章中的例子用windows控制台程式示範,後面給出完整的windows服務的代碼)。 
2、前端部分:html5 + jQuery + bootstrap。基本的前端快速開發利器。

一、分析一下聊天室的情境需求,以便構建合適的資料結構。

1、線上使用者類 OnlineUser 使用者的基本特徵為姓名Name(性別年齡啥的先忽略),當然在系統設計中,姓名並不能很好的區分不同使用者,所以得需要一個唯一識別碼Id。另外,由於可能存在多個聊天室,因此聊天室的編號RoomId也是使用者的特徵之一。綜上,可得線上使用者類OnlineUser的結構為:

///  <summary>///  線上使用者資訊///  <summary>public class OnlineUser{    public int Id { get; set; }    public string Name { get; set; }    public string RoomId { get; set; }    public string SessionId { get; set; }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

PS:SessionId是後續加入的屬性,此處可先忽略。

2、訊息類 Message 訊息是聊天室最核心的部分,我最簡單的訊息機構應包含如下成員,訊息寄件者FromUserId,訊息接受者ToUserId,訊息類型Type,訊息內容Content,訊息時間Time。

public class Message{    public int FromUserId { get; set; }    public int ToUserId { get; set; }    public int Type { get; set; }    public string Time { get; set; }    public string Content { get; set; }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

PS:這裡Type用的是int類型表示的,是出於後續訊息傳遞時,以便於將其包裹成Json格式傳遞。但在判斷時,會將其轉換成MessageType格式的枚舉型,MessageType暫訂包含以下幾種狀態,

public enum MessageType{    /// <summary>    /// 新使用者進入    /// <summary>    NewUserIn = 1,    /// <summary>    /// 使用者離開    /// <summary>    UserExit = 2,    /// <summary>    /// 新使用者提供自身資訊    /// <summary>    ReprotUserInfo = 3,    /// <summary>    /// 新文字訊息    /// </summary>    NewTextMessage = 4,    /// <summary>    /// 廣播基本資料    /// </summary>    BroadcastBasicInfo = 5}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

二、項目結構

1、服務端項目結構如下: 

這是一個windows控制台程式,Program.cs是入口,ChatWebSocket.cs是核心代碼快,外部參考的dll包括Json操作類庫和Socket操作類庫。 
其中,Model檔案夾下的是上面提到的一些基本資料結構,這裡看一下核心的代碼ChatWebSocket。這當中用到的SuperSocket已經將socket的主要操作封裝的很完備了,使用方法如下:

/* 偵聽地址(注意,此處的地址一定要和前端js中的地址一致!!) */const string IP = "127.0.0.1";/* 偵聽連接埠 */const int PORT = 2016;/* SuperWebSocket中的WebSocketServer對象 */WebSocketServer wsServer = null;/* 當前線上使用者列表 */List<OnlineUser> olUserList = new List<OnlineUser>();/* 定時通知用戶端線程 */BackgroundWorker bkWork = null;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

這裡,WebSocketServer是SuperSocket中封裝好的Socket服務端類,olUserList 是線上使用者列表,bkWork 是後台線程,負責定時向用戶端發送一些系統資訊。

建構函式中:

public ChatWebSocket(){    /* 初始化 以及 相關事件註冊 */    wsServer = new WebSocketServer();    /* 有新會話握手並串連成功 */    wsServer.NewSessionConnected += WsServer_NewSessionConnected;    /* 有會話被關閉 可能是服務端關閉 也可能是用戶端關閉 */    wsServer.SessionClosed += WsServer_SessionClosed;    /* 有新簡訊被接收 */    wsServer.NewMessageReceived += WsServer_NewMessageReceived;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

WebSocketServer有幾個比較重要的事件, 
1、NewSessionConnected 有新會話握手並串連成功 
2、SessionClosed 有會話被關閉 可能是服務端關閉 也可能是用戶端關閉 
3、NewMessageReceived 有新簡訊被接收 
其中NewMessageReceived事件是訊息傳遞的重要事件,也是我們重點處理的事件,下面將3個事件的方法體列出:

// 有新會話握手並串連成功private void WsServer_NewSessionConnected(WebSocketSession session){    LogHelper.Write(session.SessionID.ToString() + " Connect!");}// 有新簡訊被接收private void WsServer_NewMessageReceived(WebSocketSession session, string value){    LogHelper.Write("Receive Message:" + value);    var msg = JsonConvert.DeserializeObject<Message>(value);    MessageType mt = (MessageType)msg.Type;    switch (mt)    {        /* 使用者報告自己資訊,將UserId與SessionId關聯 */        case MessageType.ReprotUserInfo:            olUserList.Add(new OnlineUser            {                SessionId = session.SessionID,                 Id = msg.FromUserId,                 RealName = msg.FromUserName,                 RoomId = msg.RoomId             });            /* 通知其他使用者 */            SendMessage(session, new Message            {                FromUserId = msg.FromUserId,                FromUserName = msg.FromUserName,                ToUserId = 0,// 同一房間的人                Type = (int)MessageType.NewUserIn,                Content = "",                Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),                RoomId = msg.RoomId            });            break;        /* 使用者文字(圖片)訊息,伺服器進行轉寄 */        case MessageType.NewTextMessage:            /* 通知其他使用者 */            msg.Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");            SendMessage(session, msg);            break;        default: break;    }}// 有會話被關閉 可能是服務端關閉 也可能是用戶端關閉private void WsServer_SessionClosed(WebSocketSession session, CloseReason value){    LogHelper.Write(session.SessionID.ToString() + " Exit!");    var u = olUserList.Find(m => m.SessionId == session.SessionID);    if (u == null)    {        return;    }    olUserList.Remove(u);    // 通知其他使用者    SendMessage(session, new Message    {        FromUserId = u.Id,        FromUserName = u.RealName,        ToUserId = 0,// 同一房間的人        Type = (int)MessageType.UserExit,        Content = "",        RoomId = u.RoomId    });}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71

其中,SendMessage(WebSocketSession session, Message msg)方法如下:

private void SendMessage(WebSocketSession session, Message msg){    // -1:全體;0:同一房間;剩下:特定的使用者    var users = msg.ToUserId == -1 ? olUserList : msg.ToUserId == 0 ? olUserList.Where(m => m.RoomId == msg.RoomId).ToList() : olUserList.Where(m => m.Id == msg.ToUserId).ToList();    users.ForEach(u =>    {        var ss = session.AppServer.GetAppSessionByID(u.SessionId);        if (ss != null)        {            ss.Send(JsonConvert.SerializeObject(msg));        }     });}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

另外,WebSocketServer的啟動和停止也非常的簡單:

public void Start(){    if (!wsServer.Setup(IP, PORT))    {        throw new Exception("設定WebSocket服務偵聽地址失敗!");    }    if (!wsServer.Start())    {        throw new Exception("啟動WebSocket服務偵聽失敗!");    }}public void Stop(){    if (wsServer != null)    {        wsServer.Stop();    }}

WebSocket 網頁聊天室的實現(伺服器端:.net + windows服務,前端:Html5)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.