All pastes #1844320 Raw Edit

Socket Chat Server

public text v1 · immutable
#1844320 ·published 2010-03-18 04:28 UTC
rendered paste body
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);
                        }
                    }
                }
            }
        }
    }
}