using System; using System.Collections; using System.Net; using System.Net.Sockets; using System.Text; namespace SocketSystem { class ClientConnection { int tcpIndx = 0; int tcpByte = 0; // 4mb Buffer (see if there are better ways to initialize a large recieve buffer) byte[] tcpRecv = new byte[4096*1024]; //////////////////////////////////////// public Socket ClientSocket; //////////////////////////////////////// public String alias; public int Recv(ref string tcpRead) { tcpByte = ClientSocket.Available; if (tcpByte > tcpRecv.Length - tcpIndx) tcpByte = tcpRecv.Length - tcpIndx; tcpByte = ClientSocket.Receive(tcpRecv, tcpIndx, tcpByte, SocketFlags.Partial); tcpRead = Encoding.UTF8.GetString (tcpRecv, tcpIndx, tcpByte); tcpIndx += tcpByte; return tcpRead.Length; } public void FlushBuffer() { tcpByte = 0; tcpIndx = 0; tcpRecv = new byte[4096 * 1024]; } public int SendLine(string tcpWrite) { ClientSocket.Send(Encoding.UTF8.GetBytes(tcpWrite+"\n")); FlushBuffer(); return 0; } public int Send(string tcpWrite) { ClientSocket.Send(Encoding.UTF8.GetBytes(tcpWrite)); FlushBuffer(); return 0; } } class SocketServer { static void PrivateMessage(ClientConnection CurrentClient, String recievedLine, ArrayList ClientList) { foreach (ClientConnection AnotherClient in ClientList) { if (recievedLine.Substring(3).Trim().StartsWith(AnotherClient.alias)) { String message = recievedLine.Substring(3).Trim().Substring(AnotherClient.alias.Length); AnotherClient.SendLine("[" + CurrentClient.alias + "]: " + message); CurrentClient.SendLine("PM > " + AnotherClient.alias + ": " + message); Console.WriteLine("{0} sent {1} a Private Message", CurrentClient.alias, AnotherClient.alias); } } } static void ChangeAlias(ClientConnection CurrentClient, String alias, ArrayList ClientList) { if(alias.StartsWith("&&")) { CurrentClient.SendLine("You cannot be called :" + alias); return; } CurrentClient.SendLine("You are now called " + alias); foreach (ClientConnection AnotherClient in ClientList) { AnotherClient.SendLine(CurrentClient.alias + " is now known as " + alias); } CurrentClient.alias = alias; } static void StatusMessage(ClientConnection CurrentClient, String message, ArrayList ClientList) { Console.WriteLine("{0} {1}", CurrentClient.alias, message); foreach (ClientConnection AnotherClient in ClientList) { AnotherClient.SendLine(CurrentClient.alias + message); } } static void ListUsers(ClientConnection CurrentClient, ArrayList ClientList) { Console.WriteLine("{0} made a userlist request", CurrentClient.alias); CurrentClient.SendLine("Users...:"); foreach (ClientConnection AnotherClient in ClientList) { CurrentClient.SendLine(AnotherClient.alias); } } static void ShowHelp(ClientConnection CurrentClient) { CurrentClient.SendLine("Help..."); CurrentClient.SendLine("/who ... List connected users"); CurrentClient.SendLine("/list ... -\"- --\"-- -\"-"); CurrentClient.SendLine("/nick ... Set your chat nickname"); CurrentClient.SendLine("/me ... e.g. /me waves sends 'nickname waves'"); Console.WriteLine("{0} requested help.", CurrentClient.alias); } static void Kick(ClientConnection CurrentClient, String recievedLine, ArrayList ClientList) { foreach (ClientConnection AnotherClient in ClientList) { if (AnotherClient.alias == recievedLine.Substring(5).Trim()) { int idx = ClientList.IndexOf(AnotherClient); Console.WriteLine("{0} kicked {1}", CurrentClient.alias, AnotherClient.alias); AnotherClient.SendLine("You were kicked by " + CurrentClient.alias); CurrentClient.SendLine("You kicked " + AnotherClient.alias); AnotherClient.ClientSocket.Shutdown(SocketShutdown.Both); AnotherClient.ClientSocket.Close(); ClientList.RemoveAt(idx); break; } } } static void ClearClientConsole(ClientConnection CurrentClient, String recievedLine, ArrayList ClientList) { foreach (ClientConnection AnotherClient in ClientList) { if (AnotherClient.alias == recievedLine.Substring(6).Trim()) { int idx = ClientList.IndexOf(AnotherClient); Console.WriteLine("{0} cleared {1}'s chat log", CurrentClient.alias, AnotherClient.alias); AnotherClient.Send("&&clr"); CurrentClient.SendLine("You cleared " + AnotherClient.alias + "'s chat log"); } } } static void DisconnectClient(ClientConnection CurrentClient, ArrayList ClientList) { CurrentClient.ClientSocket.Shutdown(SocketShutdown.Both); CurrentClient.ClientSocket.Close(); Console.WriteLine("{0} disconnected.", CurrentClient.alias); foreach (ClientConnection AnotherClient in ClientList) { AnotherClient.Send(CurrentClient.alias + " disconnected.\n"); } ClientList.RemoveAt(ClientList.IndexOf(CurrentClient)); } [STAThread] static void Main() { IPHostEntry Iphe = Dns.GetHostEntry(Dns.GetHostName()); IPEndPoint Ipep = new IPEndPoint(Iphe.AddressList[0], 4444); Socket Server = new Socket(Ipep.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); ArrayList ClientList = new ArrayList(); string recievedLine = null; ClientList.Capacity = 256; Server.Blocking = false; Server.Bind(Ipep); Server.Listen(32); Console.WriteLine("{0}: listening to port {1}", Dns.GetHostName(), Ipep.Port); while (true) { if (Server.Poll(0, SelectMode.SelectRead)) { int i = ClientList.Add(new ClientConnection()); ClientConnection CurrentClient = ((ClientConnection)ClientList[i]); CurrentClient.ClientSocket = Server.Accept(); CurrentClient.alias = "Guest" + i; CurrentClient.SendLine("Welcome to the test socket server."); CurrentClient.SendLine("/help for server commands.\n"); for (int j = 0; j < ClientList.Count; j++) { ClientConnection AnotherClient = ((ClientConnection)ClientList[j]); AnotherClient.SendLine(CurrentClient.alias + " connected."); } Console.WriteLine("{0} connected.", CurrentClient.alias); } for (int i = 0; i < ClientList.Count; i++) { ClientConnection CurrentClient = ((ClientConnection)ClientList[i]); if (CurrentClient.ClientSocket.Poll(0, SelectMode.SelectRead)) { if (CurrentClient.Recv(ref recievedLine) > 0) { if (!recievedLine.StartsWith("/")) { Console.WriteLine("{0}: {1}", CurrentClient.alias, recievedLine); foreach (ClientConnection AnotherClient in ClientList) { AnotherClient.Send(CurrentClient.alias + ": " + recievedLine); } } else { String[] command = recievedLine.Split(new Char[]{' ','\n','\r'}); switch (command[0]) { case "/nick": { ChangeAlias(CurrentClient, recievedLine.Substring(5).Trim(), ClientList); break; } case "/me": { StatusMessage(CurrentClient, recievedLine.Substring(3), ClientList); break; } case "/who": case "/list": { ListUsers(CurrentClient, ClientList); break; } case "/help": { ShowHelp(CurrentClient); break; } case "/pm": { PrivateMessage(CurrentClient, recievedLine, ClientList); break; } case "/stfu": case "/gtfo": { Kick(CurrentClient, recievedLine, ClientList); break; } case "/clear": { ClearClientConsole(CurrentClient, recievedLine, ClientList); break; } default: break; } } } else { DisconnectClient(CurrentClient, ClientList); } } } } } } }