软件工程 2016.7.4日报
今天我进行的主要工作包括了完成服务器端功能的搭建,以及客户端socket通信功能架构的搭建以及部分功能的实现。
对服务器端,在周五的时候我对于接受消息、处理消息部分的功能还没有实现,今天将代码补全,构建出了一个较完善的服务端代码。
今天具体实现的代码如下:
主要实现了检查本地是否包含用户所上的全部课程的聊天室,返回特定聊天室的聊天记录给用户,向特定聊天室记录文件中添加吐槽,以及移除在线好友,处理非法信息等。
在实现的过程中运用的主要技术包括C#文件操作、JSON封装/解析数据、socket TCP通信等。
1 #region --- Check Room List --- 2 /// <summary> 3 /// Check the existence of every room in room list received from client 4 /// </summary> 5 /// <param name="msg">string of room list</param> 6 private void CheckRoomList(string s_roomList) 7 { 8 // TODO : check the existence of chat file of each room 9 List<string> roomList = (List<string>)JsonConvert.DeserializeObject(s_roomList, typeof(List<string>)); 10 11 foreach (string room in roomList) 12 { 13 string roomFile = room + ".txt"; 14 if (!File.Exists(@roomFile)) 15 { 16 FileStream fs = new FileStream(roomFile, FileMode.Create); 17 fs.Close(); 18 } 19 } 20 21 } 22 #endregion 23 24 #region --- Get Room Message --- 25 /// <summary> 26 /// get the history message of the specific chat room 27 /// </summary> 28 /// <param name="clientIP">the client IP</param> 29 /// <param name="msg">the room ID</param> 30 private void GetRoomMsg(string clientIP, string roomId) 31 { 32 // TODO : get the history of specific chat room 33 string roomFile = roomId + ".txt"; 34 35 List<string> msgList = new List<string>(); 36 37 String sendMsg = ""; 38 39 if (File.Exists(@roomFile)) 40 { 41 StreamReader sr = new StreamReader(roomFile, Encoding.Default); 42 43 String lineMsg; 44 while ((lineMsg = sr.ReadLine()) != null) 45 msgList.Add(lineMsg); 46 sendMsg = JsonConvert.SerializeObject(msgList); 47 } 48 else 49 { 50 FileStream fs = new FileStream(roomFile, FileMode.Create); 51 fs.Close(); 52 } 53 54 SendMessage(clientIP, REQUEST_ROOM_MSG, sendMsg); 55 } 56 #endregion 57 58 #region --- Add Message To File --- 59 /// <summary> 60 /// put the message into the specific room 61 /// </summary> 62 /// <param name="clientIP">the client IP</param> 63 /// <param name="msg">the string include the room id and received message</param> 64 private void AddMsgToFile(string clientIP, string msg) 65 { 66 // TODO : put the message into the specific room 67 MsgHandler msgHandler = (MsgHandler)JsonConvert.DeserializeObject(msg, typeof(MsgHandler)); 68 69 string roomFile = msgHandler.roomId + ".txt"; 70 71 FileStream fs = new FileStream(roomFile, FileMode.OpenOrCreate); 72 StreamWriter sw = new StreamWriter(fs); 73 sw.WriteLine(msgHandler.msg); 74 sw.Close(); 75 fs.Close(); 76 } 77 #endregion 78 79 #region --- Remove Offline User --- 80 /// <summary> 81 /// remove off line user 82 /// </summary> 83 /// <param name="clientIP">the client IP</param> 84 private void RemoveOfflineUser(string clientIP) 85 { 86 Console.WriteLine("User IP : " + clientIP + " has went off line."); 87 88 if (dictSocket.ContainsKey(clientIP)) 89 { 90 dictSocket[clientIP].Close(); 91 dictSocket.Remove(clientIP); 92 } 93 94 if (dictThread.ContainsKey(clientIP)) 95 { 96 Thread tmp = dictThread[clientIP]; 97 dictThread.Remove(clientIP); 98 tmp.Abort(); 99 } 100 101 } 102 #endregion 103 104 #region --- Invalid Message --- 105 /// <summary> 106 /// Handle the situation of invalid message 107 /// </summary> 108 /// <param name="clientIP">the client ip</param> 109 private void InvalidMsg(string clientIP) 110 { 111 // TODO : send invalid warning to client 112 SendMessage(clientIP, INVALID_MESSAGE, ""); 113 } 114 #endregion
在客户端我构建了一个程序的架子,并且实现了部分功能。留下没有实现的功能涉及到和UI端的交互问题,目前我还没有想的比较清楚要如何完成这一部分的交互。因为我client在收到消息时是不太容易能够让UI端知道 的,所以要通知UI端对控件内容作更改目前也没有比较好的解决方法。目前想到的方法就是我这边直接去操作UI端的控件,不必通知UI,由我这边直接对空间内容进行修改。但这个方法总觉得不理想,如果有人能够对此类问题有一个较好的解决方法的话请留言告诉我,谢谢!
今天在UI端实现的代码主要如下:
1 #region --- Connect To The Server --- 2 /// <summary> 3 /// Connect to the server 4 /// </summary> 5 public Client() 6 { 7 // get IP address 8 IPAddress address = IPAddress.Parse(ipAddr); 9 // create the endpoint 10 IPEndPoint endpoint = new IPEndPoint(address, port); 11 // create the socket, use IPv4, stream connection and TCP protocol 12 socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 13 try 14 { 15 // Connect to the Server 16 socketClient.Connect(endpoint); 17 18 threadClient = new Thread(ReceiveMsg); 19 threadClient.IsBackground = true; 20 threadClient.Start(); 21 } 22 catch (SocketException se) 23 { 24 MessageBox.Show("[SocketError]Connection failed: " + se.Message); 25 } 26 catch (Exception ex) 27 { 28 MessageBox.Show("[Error]Connection failed: " + ex.Message); 29 } 30 } 31 #endregion 32 33 #region --- Check Room List --- 34 /// <summary> 35 /// check room list 36 /// </summary> 37 /// <param name="roomList"></param> 38 public void CheckRoomList(List<string> roomList) 39 { 40 string s_roomList = JsonConvert.SerializeObject(roomList); 41 42 SendMsg(CHECK_ROOM_LIST, s_roomList); 43 } 44 #endregion 45 46 #region --- Add New Message --- 47 /// <summary> 48 /// add new message 49 /// </summary> 50 /// <param name="roomId"></param> 51 /// <param name="msg"></param> 52 public void AddNewMsg(string roomId, string msg) 53 { 54 MsgHandler msgHandler = new MsgHandler(roomId, msg); 55 string sendMsg = JsonConvert.SerializeObject(msgHandler); 56 57 SendMsg(SEND_MSG, sendMsg); 58 } 59 #endregion 60 61 #region --- Off Line --- 62 /// <summary> 63 /// go off line 64 /// </summary> 65 public void GoOffLine() 66 { 67 SendMsg(DISCONNECT, ""); 68 } 69 #endregion 70 71 #region --- Send Message --- 72 /// <summary> 73 /// Send Message 74 /// </summary> 75 /// <param name="flag">msg type</param> 76 /// <param name="msg">message</param> 77 private void SendMsg(byte flag, string msg) 78 { 79 try 80 { 81 byte[] arrMsg = Encoding.UTF8.GetBytes(msg); 82 byte[] sendArrMsg = new byte[arrMsg.Length + 1]; 83 84 // set the msg type 85 sendArrMsg[0] = flag; 86 Buffer.BlockCopy(arrMsg, 0, sendArrMsg, 1, arrMsg.Length); 87 88 socketClient.Send(sendArrMsg); 89 } 90 catch (SocketException se) 91 { 92 Console.WriteLine("[SocketError] send message error : {0}", se.Message); 93 } 94 catch (Exception e) 95 { 96 Console.WriteLine("[Error] send message error : {0}", e.Message); 97 } 98 } 99 #endregion 100 101 #region --- Receive Message --- 102 /// <summary> 103 /// receive message 104 /// </summary> 105 private void ReceiveMsg() 106 { 107 while (true) 108 { 109 // define a buffer for received message 110 byte[] arrMsg = new byte[1024 * 1024 * 2]; 111 112 // length of message received 113 int length = -1; 114 115 try 116 { 117 // get the message 118 length = socketClient.Receive(arrMsg); 119 120 // encoding the message 121 string msgReceive = Encoding.UTF8.GetString(arrMsg, 1, length-1); 122 123 if (arrMsg[0] == SEND_MSG) 124 { 125 126 } 127 else if (arrMsg[0] == IS_RECEIVE_MSG) 128 { 129 130 } 131 else if (arrMsg[0] == IS_NOT_RECEIVE_MSG) 132 { 133 134 } 135 else if (arrMsg[0] == INVALID_MESSAGE) 136 { 137 138 } 139 else 140 { 141 142 } 143 144 } 145 catch (SocketException se) 146 { 147 //MessageBox.Show("【错误】接收消息异常:" + se.Message); 148 return; 149 } 150 catch (Exception e) 151 { 152 //MessageBox.Show("【错误】接收消息异常:" + e.Message); 153 return; 154 } 155 } 156 } 157 #endregion
在ReceiveMsg中那几个if else中空出来的部分就是涉及到与UI端交互的部分。
除此之外,今天晚上在和组长进行讨论时,发现对于服务端在操作文件时要为每个文件加一个锁,这样才能保证数据的同步。所以这也是之后需要修改的地方。
时间: 2024-12-17 22:15:30