zoukankan      html  css  js  c++  java
  • 软件工程 2016.7.5日报

    软件工程 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(delegate
    15                         {
    16                             MessageBox.Show("[Error]发送消息失败");
    17                         }));
    18                     }
    19                     else if (arrMsg[0] == INVALID_MESSAGE)
    20                     {
    21                         Application.Current.Dispatcher.Invoke(new Action(delegate
    22                         {
    23                             MessageBox.Show("[Error]通信过程出错");
    24                         }));
    25                     }
    26                     else
    27                     {
    28                         Application.Current.Dispatcher.Invoke(new Action(delegate
    29                         {
    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(delegate
    13             {
    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 + "
    "
    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 else
    10      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+"
    ");
    15 
    16         f.Write(writeMsg, 0, writeMsg.Length);
    17 
    18         f.Close();
    19     }
    20 }

      通过上述方式,实现了文件的读写控制。

  • 相关阅读:
    java中的Set的使用以及各种遍历方法(较为全面)
    系统图标
    监听按钮
    GUI
    【Avalon】获取隐藏元素的尺寸
    Hooks
    特性节点Attribute
    ngCloak
    邮件
    时间
  • 原文地址:https://www.cnblogs.com/fanfan-blogs/p/5645531.html
Copyright © 2011-2022 走看看