軟體工程 2016.7.5日報

來源:互聯網
上載者:User

標籤:

軟體工程 2016.7.5日報 

  今天我的主要工作是晚場了用戶端功能的搭建、串連了用戶端UI與用戶端Socket部分的功能,為服務端增加了檔案鎖避免多個線程對同一檔案同時操作。

  具體實現的工作有:

  用戶端功能搭建:

    在用戶端完成了通訊功能的實現:

  補全了昨天空缺的代碼,在收到訊息時進行相應的處理:

 1                     if (arrMsg[0] == SEND_MSG) 2                     { 3                         ReceiveMsgFromServer(msgReceive); 4                     } 5                     else if (arrMsg[0] == IS_RECEIVE_MSG) 6                     { 7                         Application.Current.Dispatcher.Invoke(new Action(delegate 8                         { 9                             MessageBox.Show("發送訊息成功");10                         }));11                     }12                     else if (arrMsg[0] == IS_NOT_RECEIVE_MSG)13                     {14                         Application.Current.Dispatcher.Invoke(new Action(delegate15                         {16                             MessageBox.Show("[Error]發送訊息失敗");17                         }));18                     }19                     else if (arrMsg[0] == INVALID_MESSAGE)20                     {21                         Application.Current.Dispatcher.Invoke(new Action(delegate22                         {23                             MessageBox.Show("[Error]通訊過程出錯");24                         }));25                     }26                     else27                     {28                         Application.Current.Dispatcher.Invoke(new Action(delegate29                         {30                             MessageBox.Show("[Error]通訊過程出錯");31                         }));32                     }

  其中,ReceiveMsgFromServer(string str);的具體實實現如下:

 1         #region --- Receive Room History Message --- 2         /// <summary> 3         ///     Receive Message 4         /// </summary> 5         /// <param name="msgReceive"></param> 6         private void ReceiveMsgFromServer(string msgReceive) 7         { 8             MsgHandler msgHandler = (MsgHandler)JsonConvert.DeserializeObject(msgReceive, typeof(MsgHandler)); 9             string roomId = msgHandler.roomId;10             List<string> msgList = msgHandler.msgList;11 12             Application.Current.Dispatcher.Invoke(new Action(delegate13             {14                 tucaoWall.Document.Blocks.Clear();15                 string room = (string)courseList.SelectedItem;16                  if (room.Equals(roomId))17                     foreach (string msg in msgList)18                     {19                         // TODO : 將訊息逐一添加到顯示框中20                         Paragraph newParagraph = new Paragraph();21 22                         InlineUIContainer inlineUIContainer = new InlineUIContainer()23                         {24                             Child = new TextBlock()25                             {26                                 Foreground = new SolidColorBrush(Colors.Black),27                                 TextWrapping = TextWrapping.Wrap,28                                 Text = msg + "\r\n"29                             }30                         };31                         newParagraph.Inlines.Add(inlineUIContainer);32 33                         tucaoWall.Document.Blocks.Add(newParagraph);34                     }35                  36             }));37         }38         #endregion

  用戶端UI與用戶端Socket的串連

   添加了響應控制項的響應,使用者點擊不同的按鈕會調用不同的方法與伺服器進行互動。由於代碼過於瑣碎,在此不做列舉。

  

  伺服器端修改了部分邏輯,同時對檔案增加了讀寫鎖。

   由於原來在服務端對每個使用者都建立了一個線程,保證了在接受訊息端是同步的。但是卻沒有保證發送訊息、處理檔案等的並發性(可以同時操縱多個檔案)。所以將相關的方法封裝為一個類,對於每一個新連結的使用者建立一個該類對象,這樣每個使用者就可以通過自己儲存的類對象進行相關的操作,而互不影響。此部分功能實現代碼如下:

   添加從使用者ip索引處理對象的字典

        public static Dictionary<string, Handler> dictHandler = new Dictionary<string, Handler>();

   處理對象Handler封裝的方法包括

        public void CheckRoomList(string s_roomList);        public void AddMsgToFile(string clientIP, string msg);        public void InvalidMsg(string clientIP);        public void SendMessage(string clientIP, byte flag, string msg);

   使用特定ip對應的Handler對象的方法為

 1 if (msgReceiver[0] == CHECK_ROOM_LIST) 2     dictHandler[socketKey].CheckRoomList(msg); 3 else if (msgReceiver[0] == REQUEST_ROOM_MSG) 4     dictHandler[socketKey].GetRoomMsg(socketKey, msg); 5 else if (msgReceiver[0] == SEND_MSG) 6     dictHandler[socketKey].AddMsgToFile(socketKey, msg); 7 else if (msgReceiver[0] == DISCONNECT) 8      RemoveOfflineUser(socketKey); 9 else10      dictHandler[socketKey].InvalidMsg(socketKey);

   實現上述功能之後,還需要處理檔案讀寫同步的問題,同一檔案在同一時間不能被多個線程操作,所以為解決此問題需要為每個檔案添加一個讀寫鎖,來控制檔案讀寫同步的問題。

   在程式中建立由檔案名稱索引到讀寫鎖的字典

public static Dictionary<string, Object> dictLocker = new Dictionary<string, object>();

   在每次操作檔案時都需要進行並發控制,檢測相應讀寫鎖的使用方式,使用例子如下:

 1 lock(Server.dictLocker[room]) 2 { 3     FileStream fs = new FileStream(roomFile, FileMode.Create); 4     fs.Close(); 5  6     lock (Server.dictLocker["room"]) 7     { 8         string romFile = "room.txt"; 9 10         FileStream f = File.OpenWrite(romFile);11 12         f.Position = f.Length;13 14         byte[] writeMsg = Encoding.UTF8.GetBytes(room+"\r\n");15 16         f.Write(writeMsg, 0, writeMsg.Length);17 18         f.Close();19     }20 }

  通過上述方式,實現了檔案的讀寫控制。

軟體工程 2016.7.5日報

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.