-2

Ok, sorry about first question which was a bad question. Second try. I created a web server (or a responder?) using C# and System.Net libraries. Here is server public variables:

#region "Variables"
    private TcpListener _TcpListener;
    private Thread _ListenThread;
    private string _ServerDataPath = "";

    private string _Log = "[XMS LOG] Date : " + DateTime.Now.ToString("r") + "\r\n";

    public List<string> Defaults;
    public Dictionary<string, string> Mimes;
    #endregion

    private int _SendBufferSize = 2048;
    private int _ReceiveBufferSize = 2048;

    #region "Properties"
    public int SendBufferSize
    {
        get { return _SendBufferSize; }
        set
        {
            if (value <= 0)
            {
                return;
            }
            _SendBufferSize = value;
        }
    }

    public int ReceiveBufferSize
    {
        get { return _ReceiveBufferSize; }
        set
        {
            if (value <= 0)
            {
                return;
            }
            _ReceiveBufferSize = value;
        }
    }

    public TcpListener Listener
    {
        get { return _TcpListener; }
    }

    public Thread ListenThread
    {
        get { return _ListenThread; }
    }

    public String Path
    {
        get { return _ServerDataPath; }
    }
    #endregion

Here is code from my listen method:

private void Listen()
{
    Socket cur = null;
    try
    {
       // Infinite loop
       while(true)
       {
           // Accept incoming socket
           cur = _TcpListener.AcceptSocket();
           // Limit socket buffers
           cur.SendBufferSize = SendBufferSize; cur.ReceiveBufferSize = ReceiveBufferSize;
           // Get request
           byte[] Request = new byte[ReceiveBufferSize];
           int RequestSize = cur.Receive(Request);
           string RequestStr = Encoding.Default.GetString(Request);
           // Clients send empty requests filled with nulls
           // To prevent lag if request is empty then directly close stream
           if (string.IsNullOrWhiteSpace(RequestStr) || string.IsNullOrEmpty(RequestStr))
           {
               cur.Close();
           }
           else
           {
               // Process request
               Process(cur, RequestStr);
               cur.Close();
           }
        }
    }
    catch (Exception ex)
    {
        SendError(cur, "TCPClient Listening Error", "500", "Runtime Exception", ex);
    }
}

This method is running on a thread. Here is my Process method that processes http requests:

        private void Process(Socket skt, string Request)
        {
        try
        {
            // Split all the request from line terminators
            string[] RequestSplit = Request.Split(new string[] { "\r", "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            // Get Request at top of this split array
            string GetRequest = RequestSplit[0];
            // Trim
            GetRequest = GetRequest.Trim();
            // Is it a get request?
            if (!GetRequest.StartsWith("GET"))
            {
                // Send error and return
                SendError(skt, "Bad Request : " + GetRequest, "400", "Bad Request");
                return;
            }
            // Split Get Request
            string[] GetRequestSplit = GetRequest.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
            // Is Request Legal?
            // Classical GET requests generally has 3 parts:
            // GET {FileName} HTTP/1.1
            // If we get length smaller than 3 then send error
            if (GetRequestSplit.Length < 3)
            {
                SendError(skt, "Bad Request : " + GetRequest, "400", "Bad Request");
                return;
            }
            Log(GetRequest);

            // As usual middle one is file
            string File = GetRequestSplit[1];
            // We patch server path directory to this file string
            File = _ServerDataPath + File;
            // Control if it is a directory
            // If it is a directory then control default files
            bool IsIndex = false;
            if (System.IO.Directory.Exists(File))
            {
                // This must be an index file
                IsIndex = true;
            }
            // Not index file? No problem
            // I just control that if there
            // Is a file called like that

            if (!IsIndex)
            {
                // Oops accidents happen.
                // Cannot find the file that you requested.
                if (!System.IO.File.Exists(File))
                {
                    SendError(skt, "Cannot find selected file", "404", "Not Found");
                    return;
                }
                // Ok we a legal file
                // Go out and send it!
            }
            // But if file is an index?
            // Simple, loop over every default file
            else
            {
                // No defaults defined by user?
                // Sorry, we do not serve index files.
                if (Defaults.Count == 0)
                {
                    SendError(skt, "Default files are not allowed", "404", "Not Found");
                    return;
                }

                for (int i = 0; i < Defaults.Count; i++)
                {
                    if (System.IO.File.Exists(File + "\\" + Defaults[i]))
                    {
                        // Get the index file. Patch it.
                        File += "\\" + Defaults[i];
                        goto send;
                    }
                }
                // Does not contain any default?
                // Send error again.
                SendError(skt, "Cannot find default file in requested directory", "404", "Not Fount");
                return;
            }
        send:
            // Here we are, sending data...
            // Byte buffer for sending
            byte[] Buffer = System.IO.File.ReadAllBytes(File);
            // Mime?
            string Mime = GetMime(File);
            // Directly send while it is hot already!
            SendMessage(skt, Buffer, true, "200", "OK", Mime);
        }
        catch (Exception ex)
        {
            SendError(skt, "Unknown exception", "500", "Internal Exception");
        }
    }

and my send message method:

        public void SendMessage(Socket skt, byte[] message, bool includeHeader = false, string statusCode = "200", string statusMessage = "OK", string mime = "text/plain")
    {
        if (skt == null) { return; }
        string header = "";
        if (includeHeader)
        {
            header = "HTTP/1.1 " + statusCode + " " + statusMessage + "\r\n";
            header += "Server: XMServer Module\r\n";
            header += "Date: " + DateTime.Now.ToString("r") + "\r\n";
            header += "Content-Type: " + mime + "; charset=utf-8\r\n";
            header += "Connection: Closed";
            header += "\r\n\r\n";
        }
        List<byte> buffer = Encoding.Default.GetBytes(header).ToList();
        buffer.AddRange(message);
        skt.Send(buffer.ToArray());
    }

I think there is no problem in SendError, GetMime or StrIsFile methods so I don't put them here. This is a class named XMServer. Here is my start code:

XMServer server = new XMServer(8080, "..\\web\\", 4096, 1024);
server.Mimes = MIMES;
server.Defaults = DEFAULTS;
server.Start();

Problem is, server directory is defined as ..\web\ I put an index.html file there and type 127.0.0.1:8080 in browser and server sends index.html page. This is good and what I am trying to implement. I created a folder called "docs" in "web" folder and put an "images" folder in "docs" folder. And put a index.html file in "docs" folder. index.html content:

<html>
    <head>
        <title> Documentation </title>
        <meta charset="utf-8"/>
    </head>
    <body>
        <!-- This is where error pops out -->
        <img src="images/logo.png"/>
    </body>
</html>

Server sends index.html file correctly. But page sends a request to server like "GET /images/logo.png HTTP/1.1" (Just an example. I am not sure request is perfectly equal to this one). Server tries to send "..\web\images\logo.png", not "..\web\docs\images\logo.png" and log an error to file (I created a method to do this). Same thing happens when we try to give link to another html file in sub idrectories of web folder. How can I beat this? And I am sure my code is inefficient please show me my mistakes. any help will be appreciated.

Yahya Gedik
  • 97
  • 1
  • 12
  • 1
    please read guid on how to write a good question before posting – Hisham Maudarbocus Jul 22 '16 at 10:43
  • Welcome to Stack Overflow! I do not find it very clear what your problem is... Remember to be clear and thorough, and do include examples (if possible and suitable). Please share some code so that we have something to go on when helping you. -- Good things to read for new members are [How to ask](http://stackoverflow.com/help/how-to-ask) and the [Tour](http://stackoverflow.com/tour). – Visual Vincent Jul 22 '16 at 10:47

1 Answers1

0

Nailed it. I used HttpListener instead of TCPListener. Currently server is working well and can preprocess PHP files as well.

Yahya Gedik
  • 97
  • 1
  • 12