标签:
在周五我初步搭建了吐槽墙的结构,实现了部分的功能。经过与组长的讨论,我们最终决定使用TCP通信的方式实现功能。因为对于这种比较明显的C/S结构,UDP方式的通信会使得整体处理信息的过程延迟比较大,不符合功能需求。
经过讨论分析,Server和Client通信的信息主要有以下几类:
1、Client向Server发送Client房间列表,Server端check本地是否含有所有房间,若不含的话,需要创建新文件存储响应聊天信息。
2、Client向Server请求特定房间的聊天记录。
3、Client向Server发送特定房间的吐槽消息。
4、Server向Client发送特定房间的聊天记录。
5、Server向Client发送Client端向Server端发送的消息是否更新成功的信息。
由此我定义了一下状态字,存于所有消息的第一位,用于标记消息后续部分的作用:
1 private const byte CHECK_ROOM_LIST = 0; 2 private const byte REQUEST_ROOM_MSG = 1; 3 private const byte SEND_MSG = 2; 4 private const byte DISCONNECT = 3; 5 private const byte IS_RECEIVE_MSG = 4; 6 private const byte IS_NOT_RECEIVE_MSG = 5; 7 private const byte INVALID_MESSAGE = 6;
对于上述消息通信,Client端向Server端发送的消息包含两部分内容,一为房间id,二为吐槽消息,所以需要定义一个结构体保存两部分的内容,而后使用JSON解析工具进行包装、解析等。结构体定义如下:
1 public struct MsgHandler 2 { 3 public string roomId; 4 public string msg; 5 6 public MsgHandler(string r, string m) 7 { 8 roomId = r; msg = m; 9 } 10 }
除此之外,实现了服务端的逻辑框架,以及部分的功能,已实现的代码如下:
开启服务器
1 public void StartServer() 2 { 3 // Create a socket, use IPv4, stream connection and TCP 4 socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 5 6 // create a endpoing which binds the ip and port 7 IPAddress ipAddress = IPAddress.Parse(ipAddr); 8 IPEndPoint endPoint = new IPEndPoint(ipAddress, port); 9 10 try 11 { 12 // bind the watching socket to the endpoint 13 socketWatch.Bind(endPoint); 14 15 // set the length of waiting queue 16 socketWatch.Listen(20); 17 18 // Create a watching thread 19 threadWatch = new Thread(WatchConnection); 20 // Set the background property 21 threadWatch.IsBackground = true; 22 // Start the thread 23 threadWatch.Start(); 24 25 Console.WriteLine(); 26 Console.WriteLine(" ---Server Start---"); 27 Console.WriteLine(); 28 29 return; 30 } 31 catch (SocketException se) 32 { 33 Console.WriteLine("[SocketERROR]" + se.Message); 34 return; 35 } 36 catch (Exception e) 37 { 38 Console.WriteLine("[ERROR]" + e.Message); 39 return; 40 } 41 }
监听客户请求
1 private void WatchConnection() 2 { 3 // keep watching 4 while (true) 5 { 6 Socket socketConnection = null; 7 try 8 { 9 // watch the request, if has, create a socket for it 10 socketConnection = socketWatch.Accept(); 11 string socketKey = socketConnection.RemoteEndPoint.ToString(); 12 13 // save every socket with the key in the form of IP : port 14 dictSocket.Add(socketKey, socketConnection); 15 16 Console.WriteLine("User IP : {0} has connected...", socketKey); 17 18 // Create a thread to watch the data sent from client for every socket 19 // Create the communicate thread 20 Thread threadCommunicate = new Thread(ReceiveMsg); 21 threadCommunicate.IsBackground = true; 22 threadCommunicate.Start(socketConnection); 23 24 dictThread.Add(socketKey, threadCommunicate); 25 26 } 27 catch (SocketException se) 28 { 29 Console.WriteLine("[ERROR]" + se.Message); 30 return; 31 } 32 catch (Exception e) 33 { 34 Console.WriteLine("[ERROR]" + e.Message); 35 return; 36 } 37 } 38 }
监听用户信息
1 private void ReceiveMsg(object socketClientPara) 2 { 3 Socket socketClient = socketClientPara as Socket; 4 string socketKey = socketClient.RemoteEndPoint.ToString(); 5 6 while (true) 7 { 8 // define a buffer for received message 9 byte[] msgReceiver = new byte[1024 * 1024 * 2]; 10 11 // length of received message 12 int length = -1; 13 14 try 15 { 16 length = socketClient.Receive(msgReceiver); 17 } 18 catch (SocketException se) 19 { 20 Console.WriteLine("[ERROR]" + socketKey + " receive error. Message: " + se.Message); 21 22 dictSocket[socketKey].Close(); 23 Thread tmp = dictThread[socketKey]; 24 25 // Remove the error object 26 dictSocket.Remove(socketKey); 27 dictThread.Remove(socketKey); 28 tmp.Abort(); 29 30 return; 31 } 32 catch (Exception e) 33 { 34 Console.WriteLine("[ERROR]" + e.Message); 35 return; 36 } 37 38 string msg = Encoding.UTF8.GetString(msgReceiver, 1, length - 1); 39 40 if (msgReceiver[0] == CHECK_ROOM_LIST) 41 CheckRoomList(msg); 42 else if (msgReceiver[0] == REQUEST_ROOM_MSG) 43 GetRoomMsg(socketKey, msg); 44 else if (msgReceiver[0] == SEND_MSG) 45 AddMsgToFile(socketKey, msg); 46 else if (msgReceiver[0] == DISCONNECT) 47 RemoveOfflineUser(socketKey); 48 else 49 InvalidMsg(socketKey); 50 } 51 }
发送消息
1 private void SendMessage(string clientIP, byte flag, string msg) 2 { 3 try 4 { 5 byte[] arrMsg = Encoding.UTF8.GetBytes(msg); 6 byte[] sendArrMsg = new byte[arrMsg.Length + 1]; 7 8 // set the msg type 9 sendArrMsg[0] = flag; 10 Buffer.BlockCopy(arrMsg, 0, sendArrMsg, 1, arrMsg.Length); 11 12 dictSocket[clientIP].Send(sendArrMsg); 13 } 14 catch (SocketException se) 15 { 16 Console.WriteLine("[SocketERROR] send message error : {0}", se.Message); 17 } 18 catch (Exception e) 19 { 20 Console.WriteLine("[ERROR] send message error : {0}", e.Message); 21 } 22 }
标签:
原文地址:http://www.cnblogs.com/fanfan-blogs/p/5639236.html