Пример #1
0
        static void Main(string[] args)
        {
            Logging.OpenLogFile();
            myServer = new HTTPServer();

            //check command line arguments
            int    status;
            int    howManyArgs = args.Length;
            string arg1;
            string arg2;
            string arg3;

            switch (howManyArgs)
            {
            case 0: arg1 = "empty"; arg2 = "empty"; arg3 = "empty"; break;

            case 1: arg1 = args[0]; arg2 = "empty"; arg3 = "empty"; break;

            case 2: arg1 = args[0]; arg2 = args[1]; arg3 = "empty"; break;

            case 3: arg1 = args[0]; arg2 = args[1]; arg3 = args[2]; break;

            default: arg1 = arg2 = arg3 = "Invalid"; break;
            }


            status = myServer.CheckArgs(arg1, arg2, arg3);

            if (status == myServer.IsVald)
            {
                //check web root directory
                if (!Directory.Exists(myServer.WebRoot))
                {
                    Console.WriteLine("The Path of Web Root Does not Exist!");
                    Logging.WriteLog("The Path of Web Root Does not Exist!");
                    return;
                }

                TcpListener server = null;

                //Init server
                bool isInit = myServer.InitServer(ref server);

                if (isInit)
                {
                    //receive and respond
                    myServer.ListenAndRespond(ref server);
                }
            }
            else if (status == myServer.IsHelp)
            {
                Console.WriteLine("Usage: myOwnWebServer -webRoot=[website root path] -webIP=[Server IP] -webPort=[Port Number]");
            }
            else
            {
                Console.WriteLine("Invalid command line arguments format! Please use -h switch to check useage manual");
            }
        }
        /*
        *FUNCTION		: InitServer
        *PARAMETERS		: ref TcpListener server
        *RETURNS		: bool : status that whether server is started or not
        *DESCRIPTION	: This method starts the server with IP address and port that user input
        *                 This return false if exception happens, returns true if server is initiated without error
        */
        public bool InitServer(ref TcpListener server)
        {
            bool status = true;

            try
            {
                Int32 Port = Int32.Parse(WebPort);
                IPAddress localAddr = IPAddress.Parse(WebIP);

                //create server
                server = new TcpListener(localAddr, Port);

                //start server
                server.Start();

                //Console.WriteLine("Web Server Online!");
                //Console.WriteLine("Server Root path: {0}", myServer.WebRoot);
                //Console.WriteLine("Server Port: {0}", myServer.WebPort);
                //Console.WriteLine("Server IP: {0}", myServer.WebIP);
                Logging.WriteLog($"Web Server Online! Root path: {WebRoot}, Port: {WebPort}, IP: {WebIP}");

            }
            catch (SocketException e)
            {
                //Console.WriteLine("Socket Exception: {0}", e.Message);
                Logging.WriteLog($"Socket Exception: {e.Message}");
                status = false;
            }
            catch (Exception e)
            {
                //Console.WriteLine("Exception: {0}", e.Message);
                Logging.WriteLog($"Exception: {e.Message}");
                status = false;
            }

            return status;
        }
        /*
        *FUNCTION		: ListenAndRespond
        *PARAMETERS		: ref TcpListener server: server that listen client
        *RETURNS		: no return
        *DESCRIPTION	: This method accept client and create a stream, through the stream it communicate with client
        *                  It enters infinite loop to get clients message in try block, if the stream has problem with connection
        *                  it throws exception.
        */
        public void ListenAndRespond(ref TcpListener server)
        {
            // Buffer for reading data
            Byte[] bytes = new Byte[10240];
            String request = null;

            try
            {
                // Enter the listening loop.
                while (true)
                {
                    //Console.Write("Waiting for a connection... ");

                    // Perform a blocking call to accept requests.
                    // You could also user server.AcceptSocket() here.
                    TcpClient client = server.AcceptTcpClient();
                    //Console.WriteLine("Connected!");

                    request = null;

                    // Get a stream object for reading and writing
                    NetworkStream stream = client.GetStream();

                    int i;

                    // Loop to receive all the data sent by the client.
                    while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
                    {
                        // Translate data bytes to a ASCII string.
                        request = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
                        //Console.WriteLine("Received: {0}", request);

                        // parse the request and return the full response 
                        byte[] respondMsg = ParseRequest(request);


                        //log request header          
                        Logging.WriteLog(HTTPRequestHeader);

                        // string  respondMsg = request.ToUpper();

                        //serialize the response
                        //byte[] msg = System.Text.Encoding.Default.GetBytes(respondMsg);


                        // Send back a response.
                        stream.Write(respondMsg, 0, respondMsg.Length);
                        //Console.WriteLine("Response Sent...");


                        //log response header 
                        Logging.WriteLog(HTTPResponseHeader);
                        //clear the messages
                        HTTPRequestHeader = "";
                        HTTPResponseBody = "";
                        HTTPResponseHeader = "";

                    }

                    // Shutdown and end connection
                    client.Close();
                }
            }

            catch (SocketException e)
            {
                //Console.WriteLine("SocketException: {0}", e.Message);
                Logging.WriteLog($"SocketException: {e.Message}");
            }
            catch (Exception e)
            {
                Logging.WriteLog($"Exception: {e.Message}");
            }


        }
        /*
        *FUNCTION		: ParseRequest
        *PARAMETERS		: string request : The request string from the client
        *RETURNS		: byte[] : A byte array that contains response
        *DESCRIPTION	: This method first,parse header of the request. second, find the file that client request, 
        *                  third, generate header and body of response, forth, combine header and body in byte array form
        *                  It fill the header with error code and error message if errors accur
        */
        public byte[] ParseRequest(string request)
        {

            try
            {

               string requestFirstLine = request.Substring(0, request.IndexOf('\r'));
               string requestTheRest = request.Substring(request.IndexOf('\n') + 1);

                //In the parsed first line the [0] is method, the [1] is file path, the [2] is HTML Version
                string[] parsedRequestFirstLine = requestFirstLine.Split(' ');
                string method = parsedRequestFirstLine[0];
                string filePath = WebRoot + parsedRequestFirstLine[1];

                string requestSecondLine = requestTheRest.Substring(0, requestTheRest.IndexOf('\r'));

                //creat the request header
                HTTPRequestHeader = requestFirstLine + Environment.NewLine + requestSecondLine;

                //method is not GET
                if (method != "GET")
                {
                    StatusCode = "405 Method Not Allowed";

                }
                //file does not exist
               else if(!File.Exists(filePath))
                {
                    StatusCode = "404 Not Found";
                }
                else
                {

                    //check suffix if not found in dictionary  406
                    FileSuffix = Path.GetExtension(filePath);
                     
                    if(!MIMETypes.ContainsKey(FileSuffix))
                    {
                        StatusCode = "406 Not Acceptable";
                    }
                    else
                    {
                        
                        byte[] content = File.ReadAllBytes(filePath);
                        byteBody = content;

                        ContentLength = content.Length;

                        // all OK 200
                        StatusCode = "200 OK";
                    }

                }
                //after parsing build the response
                BuildResponse();
            }
            catch (Exception e)
            {
                // File I/O exceptions 500
                if( e is ArgumentException ||
                    e is ArgumentNullException ||
                    e is PathTooLongException ||
                    e is IOException ||
                    e is UnauthorizedAccessException)
                {
                    StatusCode = "500 Internal Server Error";
                }
                //parse exception 400
                else
                {
                    StatusCode = "400 Bad Request";
                }

                //Console.WriteLine($"Exception:{e.Message}");
                Logging.WriteLog($"Exception:{e.Message}");

                BuildResponse();

            }

            if(StatusCode!="200 OK")
            {

                byteBody = System.Text.Encoding.UTF8.GetBytes(HTTPResponseBody);
            }
            byte[] byteHeader = System.Text.Encoding.UTF8.GetBytes(HTTPResponseHeader + Environment.NewLine + Environment.NewLine);


            return Combine(byteHeader, byteBody);

        }