Exemplo n.º 1
0
        /**/
        /*
        static byte[] GetBytes(string str)
        
        NAME
            GetBytes - converts a string into an array of bytes.
        
        SYNOPSIS
            static byte[] GetBytes(string str)
         
            str     --> the string to be converted.
         
         DESCRIPTION
            Because sockets send information back and forth as arrays of bytes,
            throughout the program it is necessary to convert back and forth between strings, arrays of bytes,
            and arrays of strings. This function will be used by both the clients and server to convert a string into bytes.
         
         RETURNS
            An array of bytes holding the equivalent data that was in string str.
         
         AUTHOR
            David Wilson
         */
        /**/
        public static byte[] GetBytes(string str)
        {
            byte[] bytes = new byte[str.Length * sizeof(char)];
            System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
            return bytes;
        }

        /**/
        /*
        static string GetString(byte[] bytes)
        
        NAME
            GetBytes - converts a string into an array of bytes.
        
        SYNOPSIS
           static string GetString(byte[] bytes)
         
            bytes     --> An array of bytes to be converted.
         
         DESCRIPTION
            Because sockets send information back and forth as arrays of bytes,
            throughout the program it is necessary to convert back and forth between strings, arrays of bytes,
            and arrays of strings. This function will be used by both the clients and server to convert an array of bytes into a single string.
         
         RETURNS
            A string that holds the equivalent data that was in the bytes array.
         
         AUTHOR
            David Wilson
         */
        /**/
        public static string GetString(byte[] bytes)
        {
            char[] chars = new char[bytes.Length / sizeof(char)];
            System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);

            string charst = new string(chars);
            charst = charst.Replace("\0", string.Empty);

            return charst;
        }

        /**/
        /*
        static int SendResponse(int clientnum, byte[] move)
        
        NAME
            SendResponse - Send a message to a connected client.
        
        SYNOPSIS
            static int SendResponse(int clientnum, byte[] move)
         
            int clientnum - The position in the array of clients the move should be sent to
            move - The message to be sent.
         
         DESCRIPTION
            Sends a message to a client containing either cards (what's left in the deck to be drawn) 
            or an error code (indicating an invalid move).         
         
         RETURNS
            int - 0 sucessful return
         
         AUTHOR
            David Wilson
         */
        /**/
        static int SendResponse(Socket[] clients, int clientnum, byte[] move)
        {
            int byteCount = 0;

            byte[] Messagesize = BitConverter.GetBytes(move.Length);

            int opp = (clientnum == 0) ? 1 : 0;

            try
            {
                clients[clientnum].Send(Messagesize, 0, Messagesize.Length, SocketFlags.None);

                int size = BitConverter.ToInt32(Messagesize, 0);

                do
                {
                    byteCount += clients[clientnum].Send(move, byteCount, (size-byteCount), SocketFlags.None);
                } while (byteCount < size);
            }

            catch (SocketException e)
            {
                Console.WriteLine("{0} Error code: {1}.", e.Message, e.ErrorCode);

                if (e.ErrorCode == 10054)
                {
                    Byte[] resp = GetBytes("E6");
                    if (!(clients[opp].Poll(1, SelectMode.SelectRead) && clients[opp].Available == 0))
                      SendResponse(clients, opp, resp);
                    Environment.Exit(0);
                }
            }

            return 0;
        }

        /**/
        /*
        static int RecieveMove(int clientnum, ref byte[] movebuff)
        
        NAME
            RecieveMove - Receive a message from a connected client.
        
        SYNOPSIS
            static int RecieveMove(int clientnum, ref byte[] movebuff)
         
            int clientnum - The position in the array of clients the move should be received from
            movebuff - byte array in which the move will be stored.
         
         DESCRIPTION
            Receives a message from a client containing indexes into their array of cards,
            indicating which cards are part of the move they will play        
         
         RETURNS
            int - 0 sucessful return
         
         AUTHOR
            David Wilson
         */
        /**/
        static int RecieveMove(Socket[] clients, int clientnum, ref byte[] movebuff)
        {
            int byteCount = 0;

            //Populate a byte array in this function which can be processed in the loop below
            byte[] Messagesize = new byte[sizeof(int)];
            byte[] message = new byte[4096];

            int opp = (clientnum == 0) ? 1 : 0;

            try
            {
                //Set time out
                clients[clientnum].ReceiveTimeout = 30000;
                clients[clientnum].Receive(Messagesize, 0, Messagesize.Length, SocketFlags.None);

                int size = BitConverter.ToInt32(Messagesize, 0);

                do
                {
                    byteCount += clients[clientnum].Receive(message, byteCount, (size-byteCount), SocketFlags.None);
                } while (byteCount < size);
            }

            catch (SocketException e)
            {
                Console.WriteLine("{0} Error code: {1}.", e.Message, e.ErrorCode);

                if (e.ErrorCode == 10060)
                {
                    Byte[] resp = GetBytes("E5");
                    SendResponse(clients, clientnum, resp);
                    return 1;
                }

                if (e.ErrorCode == 10054)
                {
                    Byte[] resp = GetBytes("E6");
                    if (!(clients[opp].Poll(1, SelectMode.SelectRead) && clients[opp].Available == 0))
                        SendResponse(clients, opp, resp);
                    Environment.Exit(0);
                }
            }

            movebuff = message;
            return 0;
        }

        /**/
        /*
        static string[] ProcessMessage(byte[] message)
        
        NAME
            static string[] ProcessMessage(byte[] message) - Divide a message up into its parts (coma-seperated cards to be played)
        
        SYNOPSIS
            static string[] ProcessMessage(byte[] message)
         
            message - 
         
         DESCRIPTION
            Receives a message from a client containing indexes into their array of cards,
            indicating which cards are part of the move they will play and divides it into individual cards.       
         
         RETURNS
            string[] - the message divided into an array of strings
         
         AUTHOR
            David Wilson
         */
        /**/
        static string[] ProcessMessage(byte[] message)
        {
            string result = GetString(message);
            result = result.Substring(0, result.Length - 1);
            Char delimiter = ',';
            String[] messages = result.Split(delimiter);

            return messages;
        }

        static int HandleBeginning(Socket[] clients, ref Game G)
        {
            int turn, turn2;

            //Deal out cards initially and send them to players
            byte[] p1cards = G.Buildmessagecards(0, G.AIdeck);
            byte[] p2cards = G.Buildmessagecards(1, G.pdeck);

            SendResponse(clients, 0, p1cards);
            SendResponse(clients, 1, p2cards);

            //First thing to do is find out who has the ace of diamonds
            if (G.AIdeck.FindCard(1, Suite.diamonds))
                turn = 0;
            else
                turn = 1;

            turn2 = (turn == 0) ? 1 : 0;

            byte[] turni = BitConverter.GetBytes('T');
            byte[] nturni = BitConverter.GetBytes('N');
            SendResponse(clients, turn, turni);
            SendResponse(clients, turn2, nturni);

            return turn;
        }

        static bool HandleEnd(Socket[] clients, int turn, ref byte[] movebuff)
        {
            string winmsg = "WIN";
            byte[] winresp = GetBytes(winmsg);
            SendResponse(clients, turn, winresp);
            RecieveMove(clients, turn, ref movebuff);

            string winnerresponse = GetString(movebuff);

            turn = (turn == 0) ? 1 : 0;
            string lossmsg = "LOS";
            byte[] lossresp = GetBytes(lossmsg);
            SendResponse(clients, turn, lossresp);

            Array.Clear(movebuff, 0, movebuff.Length);
            RecieveMove(clients, turn, ref movebuff);
            string loserresponse = GetString(movebuff);

            if (winnerresponse == "RP" && loserresponse == "RP")
            {
                byte[] playagin = GetBytes("PA");
                SendResponse(clients, 0, playagin);
                SendResponse(clients, 1, playagin);
                return true;
            }

            return false;
        }

        /**/
        /*
        static void Main(string[] args)
        
        NAME
            Main - Entry point for the application handles the main task of playing the game according
            to the functions defined in the Game class.
        
        SYNOPSIS
            static void Main(string[] args)
         
            args - command line arguments
         
         DESCRIPTION
            static void Main(string[] args) - The entry point for the server console app
            1. Starts up server and waits for clients to connect
            2. Facilitates game by continuing to send and recieve messages (cards, errors, etc).
         
         RETURNS
           N/A
         
         AUTHOR
            David Wilson
         */
        /**/
        static void Main(string[] args)
        {

                //
                // Create a Sockets based echo server.
                //
                const int CONNECTION_BACKLOG = 5;
                const int BUFFER_SIZE = 4096;

                Socket soc = null;
                try
                {
                    //Create a socket using port 7007
                    soc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    soc.Bind(new IPEndPoint(IPAddress.Any, 7007));
                    soc.Listen(CONNECTION_BACKLOG);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Server failed to initialized.  Exception: " + e.Message);
                }

                byte[] incomingMessageBuffer = new byte[BUFFER_SIZE];	// Receive buffer

                bool response;

                do
                {

                 //An Array used to keep all the connections to the server (clients) organized
                Socket[] clients = new Socket[numplayers];

                // Wait for a client connection
                for (int i = 0; i < clients.Length; i++)
                {
                    try
                    {
                        clients[i] = soc.Accept();

                        // Display the client endpoint
                        Console.WriteLine("Server: Received connection request from client {0} at " + clients[i].RemoteEndPoint, i);
                    }
                    catch (Exception ex)
                    {
                        // Handle errors (will happen after Dispose is called)
                        Console.WriteLine("Server Error (will be called after Dispose): " + ex.Message);

                        if (clients[i] != null && clients[i].Connected)
                        {
                            // Close the client
                            clients[i].Close();
                        }
                    }
                }

            
                bool winindicator = false;
                
                Game G = new Game();

                int turn = HandleBeginning(clients, ref G);

                byte[] movebuff = new byte[4096];
                
                //Turn taking loop
               while (true) {
                    Array.Clear(movebuff, 0, movebuff.Length);

                    int rret = RecieveMove(clients, turn, ref movebuff);

                    if (rret == 1) continue;

                    string charst = GetString(movebuff);

                    if (charst == "Pass")
                    {
                        SendResponse(clients, turn, BitConverter.GetBytes('N'));

                        turn = (turn == 0) ? 1 : 0;
                        SendResponse(clients, turn, BitConverter.GetBytes('T'));

                        G.ResetLP();

                        byte[] p1 = G.Buildmessage(0, G.AIdeck);
                        byte[] p2 = G.Buildmessage(1, G.pdeck);

                        SendResponse(clients, 0, p1);
                        SendResponse(clients, 1, p2);

                        continue;
                    }

                    string[] cards = ProcessMessage(movebuff);

                   int ec;

                   if (turn == 0)
                        ec = G.VerifyHand(cards, turn,ref G.AIdeck);
                   else
                        ec = G.VerifyHand(cards, turn,ref G.pdeck);

                    if (ec == 0)
                    {
                        G.PlayCards();

                        if ((winindicator = G.Checkwin()) == true)
                            break;

                        byte[] p1 = G.Buildmessage(0,G.AIdeck);
                        byte[] p2 = G.Buildmessage(1,G.pdeck);

                        SendResponse(clients, 0, p1);
                        SendResponse(clients, 1, p2);

                    }
                    else
                    {
                        G.ResetTD();
                        string msg = "E" + ec.ToString();
                        Byte[] resp = GetBytes(msg);
                        SendResponse(clients, turn, resp);
                        continue;
                    }

                    turn = (turn == 0) ? 1 : 0;
               };

               response = HandleEnd(clients, turn, ref movebuff);
     
            }
            while (response);
		}