// Method: maintaining communication with other server. // Executed on separated thread. private void ServerCommunicate(Object obj) { ClientConnection s = (ClientConnection)obj; // First thing to do after successfully connect to that server: // Inform the other server that this server is on, along with info _packetSent.title = MsgTitle.server_on.ToString(); _packetSent.time = _now; _packetSent.IP = _localEndPoint.ToString(); _packetSent.content = null; _packetSent.sender = this.ServerName; s.sendMsg(_packetSent); Console.WriteLine("Server " + s.Name + " is online"); bool notDone = true; try { // Begin receiving info from other server. while (notDone) { _packetReceived.title = MsgTitle.connect_to_server.ToString(); int bytesRec = s.ClientSocket.Receive(s.ReceiveBuffer); string stringRec = Encoding.ASCII.GetString(s.ReceiveBuffer, 0, bytesRec); var serializer = new JavaScriptSerializer(); var serializedResult = serializer.Deserialize <Packet>(stringRec); _packetReceived = serializedResult; string sender = _packetReceived.sender; // When server has new client if (_packetReceived.title.Equals(MsgTitle.add_client.ToString())) { if (!_peerUsers.ContainsKey(sender)) { _peerUsers[sender] = new List <string>(); } _peerUsers[sender].Add(_packetReceived.content); Console.WriteLine("Server " + sender + " add new client: " + _packetReceived.content); } // or server removes one client, else if (_packetReceived.title.Equals(MsgTitle.remove_client.ToString())) { _peerUsers[sender].Remove(_packetReceived.content); Console.WriteLine("Server " + sender + " remove client: " + _packetReceived.content); } // or server has a new chat room, else if (_packetReceived.title.Equals(MsgTitle.add_chatroom.ToString())) { if (!_peerChatrooms.ContainsKey(sender)) { _peerChatrooms[sender] = new List <string>(); } _peerChatrooms[sender].Add(_packetReceived.content); Console.WriteLine("Server " + sender + " add new chat room: " + _packetReceived.content); } // or server removes a chat room, else if (_packetReceived.title.Equals(MsgTitle.remove_chatroom.ToString())) { _peerChatrooms[sender].Remove(_packetReceived.content); Console.WriteLine("Server " + sender + " remove chat room: " + _packetReceived.content); } // or theres a new client to a chat room, else if (_packetReceived.title.Equals(MsgTitle.client_to_chatroom.ToString())) { string[] content = _packetReceived.content.Split(); // content[0] = room name, // content[1] = client name. if (!_peerClientInCR.ContainsKey(content[0])) { _peerClientInCR[content[0]] = new List <string>(); } _peerClientInCR[content[0]].Add(content[1]); Console.WriteLine("Server " + sender + " add client " + content[1] + " to chat room: " + content[0]); } // or theres a client leaving chat room, else if (_packetReceived.title.Equals(MsgTitle.client_outof_chatroom.ToString())) { string[] content = _packetReceived.content.Split(); // content[0] = room name, // content[1] = client name. _peerClientInCR[content[0]].Remove(content[1]); Console.WriteLine("Server " + sender + " remove client " + content[1] + " to chat room: " + content[0]); } // or if server is on, else if (_packetReceived.title.Equals(MsgTitle.server_on.ToString())) { if (!_peerServerDict.ContainsKey(sender)) { _peerServerDict[sender] = s; Console.WriteLine("Server " + sender + " is online"); } } // or if server is off. else if (_packetReceived.title.Equals(MsgTitle.server_off.ToString())) { if (_peerServerDict.ContainsKey(sender)) { _peerServerDict.Remove(sender); Console.WriteLine("Server " + sender + " is offline"); } _peerChatrooms.Remove(sender); _peerUsers.Remove(sender); break; } } } catch (Exception e) { Console.WriteLine(e.ToString()); notDone = false; } }
// Method: server listening to client request. public void StartListening() { // Establish the local endpoint for the socket // using the DNS name of the local computer. _ipHostInfo = Dns.GetHostEntry(Dns.GetHostName()); _ipAddress = _ipHostInfo.AddressList[0]; _localEndPoint = new IPEndPoint(_ipAddress, 3000); // Proxy endpoint. _proxyEndPoint = new IPEndPoint(_ipAddress, 4000); // New socket to connect with proxy. Socket proxySocket = new Socket(_ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); // Create a TCP/IP socket to listen for connections. Socket listener = new Socket(_ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); try { // Bind the socket to the local endpoint and // listen for incoming connections. listener.Bind(_localEndPoint); listener.Listen(100); // Create a new thread just for checking clients' status. Thread checkThread = new Thread(TestClientStatus); checkThread.Name = "check thread"; checkThread.IsBackground = true; checkThread.Start(); // Name main thread. Thread.CurrentThread.Name = "main thread"; // Connect with proxy proxySocket.Connect(_proxyEndPoint); _proxyConnection = new ClientConnection(proxySocket); // Make a new thread to maintain proxy connection. Thread proxyThread = new Thread(ProxyCommunicate); proxyThread.Name = "proxy thread"; proxyThread.IsBackground = true; proxyThread.Start(); // Add main hall to list of chat room. _localCR.Add(_mainHall); while (true) { Console.WriteLine("Waiting for a connection..."); // Start an asynchronous socket to handle client request. // Program will pause here until request accepted. Socket handler = listener.Accept(); // Once accepted, create a ClientConnection object // and a UserInfo object to contain that particular // user information. ClientConnection clientState = new ClientConnection(handler); UserInfo newUser = new UserInfo(clientState); // Assign name for connected client. newUser.UserName = "******" + _clientCount.ToString(); clientState.GetUser(newUser); // Update server's client list. _userList.Add(newUser); // Add user to main hall. _mainHall.AddUser(newUser); // Update user's current room = main hall. newUser.CurrentChatRoom = _mainHall; _clientCount++; // Create new thread to asynchronously handle client request. Thread clientThread = new Thread(RequestHandler); clientThread.Start(clientState); // Name the thread after client name. clientThread.Name = newUser.UserName; // Set the thread to be running in background. clientThread.IsBackground = true; // This thread (main thread) will pause here until the client // thread created above signal that it has created successfully. _mainThread.WaitOne(); } } catch (Exception e) { Console.WriteLine(e.ToString()); // Informing proxy that this server is going offline. _packetSent.title = MsgTitle.server_off.ToString(); _packetSent.sender = this.ServerName; _packetSent.content = null; foreach (var entry in _peerServerDict.Values) { _packetSent.IP = entry.ClientSocket.LocalEndPoint.ToString(); entry.sendMsg(_packetSent); } _proxyConnection.sendMsg(_packetSent); // Shutdown listening socket. listener.Shutdown(SocketShutdown.Both); listener.Close(); } Console.WriteLine("\nPress ENTER to continue..."); Console.Read(); }
// Method: maintaining communication with proxy. // Executed on separated thread. private void ProxyCommunicate() { // Inform proxy that this server is on. _packetSent.title = MsgTitle.server_on.ToString(); _packetSent.time = _now; // use local EP of this server so that proxy can send this EP // to other servers, then they can connect to this server. _packetSent.IP = _localEndPoint.ToString(); _packetSent.content = null; _packetSent.sender = this.ServerName; _proxyConnection.sendMsg(_packetSent); Console.WriteLine("proxy is online"); bool notDone = true; try { // Begin receiving info from proxy. while (notDone) { int bytesRec = _proxyConnection.ClientSocket.Receive(_proxyConnection.ReceiveBuffer); string stringRec = Encoding.ASCII.GetString(_proxyConnection.ReceiveBuffer, 0, bytesRec); var serializer = new JavaScriptSerializer(); var serializedResult = serializer.Deserialize <Packet>(stringRec); _packetReceived = serializedResult; //Console.WriteLine(_packetReceived.content); //Console.WriteLine(_packetReceived.IP); //Console.WriteLine(_packetReceived.sender); //Console.WriteLine(_packetReceived.title); // When proxy is checking whether this server is still online. if (_packetReceived.title.Equals(MsgTitle.are_you_online.ToString())) { // Inform proxy that this server is still online. _packetSent.title = MsgTitle.online.ToString(); _packetSent.time = _now; _packetSent.IP = _proxyConnection.ClientSocket.LocalEndPoint.ToString(); _packetSent.content = "online"; _packetSent.sender = this.ServerName; _proxyConnection.sendMsg(_packetSent); } // Proxy inform that there is a new server online. else if (_packetReceived.title.Equals(MsgTitle.server_on.ToString())) { // content will be name of server online // IP is the IP of that server. // create new thread and call the servercommunicate function // create/update server ClientConnection //Console.WriteLine("sender is " + _packetReceived.sender); // New socket to connect with proxy. Socket serverSocket = new Socket(_ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); // Generate endpoint for server. IPEndPoint remoteEP = createIPEndPoint(_packetReceived.IP); serverSocket.Connect(remoteEP); // Create new instance of ClientConnection to hold info. ClientConnection newServerConn = new ClientConnection(serverSocket); UserInfo serverInfo = new UserInfo(newServerConn); newServerConn.GetUser(serverInfo); newServerConn.Name = _packetReceived.content; // Add this server to server dict. //Console.WriteLine("content " + _packetReceived.content); _peerServerDict[_packetReceived.content] = newServerConn; // Make a new thread to maintain servers connection. Thread serverThread = new Thread(ServerCommunicate); serverThread.Name = newServerConn.Name; //Console.WriteLine(serverThread.Name); serverThread.IsBackground = true; serverThread.Start(newServerConn); } else if (_packetReceived.title.Equals(MsgTitle.server_off.ToString())) { // Content is the name of the server. if (_peerServerDict.ContainsKey(_packetReceived.content)) { _peerServerDict.Remove(_packetReceived.content); Console.WriteLine("Server " + _packetReceived.content + " is offline"); } } } } catch (Exception e) { Console.WriteLine(e.ToString()); notDone = false; } }