All pastes #1844172 Raw Edit

Socket Chat Server

public text v1 · immutable
#1844172 ·published 2010-03-18 00:29 UTC
rendered paste body
using System;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace TcpSock
{
    class TcpSock
    {
        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 tcpSock;
        ////////////////////////////////////////

        public String alias;

        public int Recv(ref string tcpRead)
        {
            tcpByte = tcpSock.Available;

            if (tcpByte > tcpRecv.Length - tcpIndx)
                tcpByte = tcpRecv.Length - tcpIndx;

            tcpByte = tcpSock.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)
        {
            tcpSock.Send(Encoding.UTF8.GetBytes(tcpWrite+"\n"));
            FlushBuffer();
            return 0;
        }

        public int Send(string tcpWrite)
        {
            tcpSock.Send(Encoding.UTF8.GetBytes(tcpWrite));
            FlushBuffer();
            return 0;
        }
    }

    class Tcp
    {
        static void privateMessage(TcpSock currentClient, String recievedLine, ArrayList Client)
        {
            foreach (TcpSock aClientSocket in Client)
            {
                if (recievedLine.Substring(3).Trim().StartsWith(aClientSocket.alias))
                {
                    String message = recievedLine.Substring(3).Trim().Substring(aClientSocket.alias.Length);
                    aClientSocket.SendLine("[" + currentClient.alias + "]: " + message);
                    currentClient.SendLine("PM > " + aClientSocket.alias + ": " + message);
                    Console.WriteLine("{0} sent {1} a Private Message", currentClient.alias, aClientSocket.alias);
                }
            }
        }

        static void newNick(TcpSock currentClient, String alias, ArrayList Client)
        {
            currentClient.SendLine("You are now called " + alias);
            foreach (TcpSock aClientSocket in Client)
            {
                aClientSocket.SendLine(currentClient.alias + " is now known as " + alias);
            }
            currentClient.alias = alias;
        }

        static void meMessage(TcpSock currentClient, String message, ArrayList Client)
        {
            Console.WriteLine("{0} {1}", currentClient.alias, message);
            foreach (TcpSock aClientSocket in Client)
            {
                aClientSocket.SendLine(currentClient.alias + message);
            }
        }

        static void listUsers(TcpSock currentClient, ArrayList Client)
        {
            Console.WriteLine("{0} made a userlist request", currentClient.alias);
            currentClient.SendLine("Users...:");
            foreach (TcpSock aClientSocket in Client)
            {
                currentClient.SendLine(aClientSocket.alias);
            }
        }

        static void showHelp(TcpSock 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(TcpSock currentClient, String recievedLine, ArrayList Client)
        {
            foreach (TcpSock aClientSocket in Client)
            {
                if (aClientSocket.alias == recievedLine.Substring(5).Trim())
                {
                    int idx = Client.IndexOf(aClientSocket);
                    Console.WriteLine("{0} kicked {1}", currentClient.alias, aClientSocket.alias);
                    aClientSocket.SendLine("You were kicked by " + currentClient.alias);
                    currentClient.SendLine("You kicked " + aClientSocket.alias);
                    aClientSocket.tcpSock.Shutdown(SocketShutdown.Both);
                    aClientSocket.tcpSock.Close();
                    Client.RemoveAt(idx);
                    break;
                }
            }
        }

        static void clearClientConsole(TcpSock currentClient, String recievedLine, ArrayList Client)
        {
            foreach (TcpSock aClientSocket in Client)
            {
                if (aClientSocket.alias == recievedLine.Substring(6).Trim())
                {
                    int idx = Client.IndexOf(aClientSocket);
                    Console.WriteLine("{0} cleared {1}'s chat log", currentClient.alias, aClientSocket.alias);
                    aClientSocket.Send("&&clr");
                    currentClient.SendLine("You cleared " + aClientSocket.alias + "'s chat log");
                }
            }
        }

        [STAThread]
        static void Main()
        {
            ////////////////////////////////////////////////////////////////////////////////////////////
            ///class IPHostEntry : Stores information about the Host and is required
            ///for IPEndPoint.
            ///class IPEndPoint  : Stores information about the Host IP Address and
            ///the Port number.
            ///class TcpSock     : Invokes the constructor and creates an instance.
            ///class ArrayList   : Stores a dynamic array of Client TcpSock objects.

            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);

            ////////////////////////////////////////////////////////////////////////////////////////////
            ///Initialize
            ///Capacity : Maximux number of clients able to connect.
            ///Blocking : Determines if the Server TcpSock will stop code execution
            ///to receive data from the Client TcpSock.
            ///Bind     : Binds the Server TcpSock to the Host IP Address and the Port Number.
            ///Listen   : Begin listening to the Port; it is now ready to accept connections.

            ArrayList Client = new ArrayList();
            ArrayList Nicks = new ArrayList();
            string recievedLine = null;

            Client.Capacity = 256;
            Server.Blocking = false;
            Server.Bind(Ipep);
            Server.Listen(32);

            Console.WriteLine("{0}: listening to port {1}", Dns.GetHostName(),
                Ipep.Port);

            ////////////////////////////////////////////////////////////////////////////////////////////
            ///Main loop
            ///1. Poll the Server TcpSock; if true then accept the new connection.
            ///2. Poll the Client TcpSock; if true then receive data from Clients.

            while (true)
            {
                //Accept
                if (Server.Poll(0, SelectMode.SelectRead))
                {
                    int i = Client.Add(new TcpSock());
                    TcpSock currentClient = ((TcpSock)Client[i]);
                    currentClient.tcpSock = Server.Accept();
                    currentClient.alias = "Client " + i;
                    currentClient.SendLine("Welcome to the test socket server.");
                    currentClient.SendLine("/help for server commands.");
                    
                    for (int j = 0; j < Client.Count; j++)
                    {
                        TcpSock aClientSocket = ((TcpSock)Client[j]);
                        aClientSocket.SendLine(currentClient.alias + " connected.");
                    }
                    Console.WriteLine("{0} connected.", currentClient.alias);
                }

                for (int i = 0; i < Client.Count; i++)
                {
                    TcpSock currentClient = ((TcpSock)Client[i]);
                    if (currentClient.tcpSock.Poll(0, SelectMode.SelectRead))
                    {
                        if (currentClient.Recv(ref recievedLine) > 0)
                        {
                            if (!recievedLine.StartsWith("/"))
                            {
                                Console.WriteLine("{0}: {1}", currentClient.alias, recievedLine);
                                foreach (TcpSock aClientSocket in Client)
                                {
                                    aClientSocket.Send(currentClient.alias + ": " + recievedLine);
                                }
                            }
                            else
                            {
                                String[] command = recievedLine.Split(new Char[]{' ','\n','\r'});
                                switch (command[0])
                                {
                                    case "/nick":
                                        {
                                            newNick(currentClient, recievedLine.Substring(5).Trim(), Client);
                                            break;
                                        }
                                    case "/me":
                                        {
                                            meMessage(currentClient, recievedLine.Substring(3), Client);
                                            break;
                                        }
                                    case "/who":
                                    case "/list":
                                        {
                                            listUsers(currentClient, Client);
                                            break;
                                        }
                                    case "/help":
                                        {
                                            showHelp(currentClient);
                                            break;
                                        }
                                    case "/pm":
                                        {
                                            privateMessage(currentClient, recievedLine, Client);
                                            break;
                                        }
                                    case "/stfu":
                                    case "/gtfo":
                                        {
                                            kick(currentClient, recievedLine, Client);
                                            break;
                                        }
                                    case "/clear":
                                        {
                                            clearClientConsole(currentClient, recievedLine, Client);
                                            break;
                                        }
                                    default:
                                        break;
                                }
                            }
                        }
                        else
                        {
                            currentClient.tcpSock.Shutdown(SocketShutdown.Both);
                            currentClient.tcpSock.Close();
                            Client.RemoveAt(i);
                            Console.WriteLine("{0} disconnected.", currentClient.alias);
                            foreach (TcpSock aClientSocket in Client)
                            {
                                aClientSocket.Send(currentClient.alias + " disconnected.\n");
                            }
                        }
                    }
                }
            }
        }
    }
}