본문 바로가기

C#/근웹 연대기

c#으로 근본 없는 웹서버 개발기 3 : 브라우저 요청 값 확인

⚠WARNING
ASP.NET에 대한 포스팅이 아닙니다
나가실 문은 오른쪽 하단입니다

 

 

웹서버가 하는 일은 브라우저가 보낸 요청에 응답하는 것이다.
서버에서 먼저 브라우저쪽으로 요청하는 일은 없다. 
그렇다.

브라우저가 먼저 다가와주지 않으면 소통하지 못하는 고독한 존재이다.

그래서 언제 있을지 모르는 브라우저의 요청에 만전을 기해야 한다.

우선 전전편의 소스에서 리퀘스트와 리스폰스로 구분을 지었다.

static void Main(string[] args)
{
    IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 80);
    Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    server.Bind(ipep);
    server.Listen(100);

    while (true)
    {
        Socket client = server.Accept();
        try
        {
            request(client); //리퀘스트
            response(client); //리스폰스
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
        finally
        {
            client.Close();
        }
    }
}
public static void response(Socket client)
{
    var sendData = @"<html><head>
            <link rel='icon' type='image/png' href='data:image/png;base64,iVBORw0KGgo='>
            </head><body>hello world</body></html>";
    StringBuilder sb = new StringBuilder(100);
    sb.AppendLine("HTTP/1.1 200 ok");
    sb.AppendLine("date: " + DateTime.UtcNow.ToString("ddd, dd MMM yyy HH':'mm':'ss 'GMT'", Util.culInfo));
    sb.AppendLine("server: test server");
    sb.AppendLine("Content-Length: " + sendData.Length);
    sb.AppendLine("content-type:text/html; charset=UTF-8");
    sb.AppendLine();
    sb.AppendLine(sendData);
    var bytes = Encoding.UTF8.GetBytes(sb.ToString());
    client.Send(bytes);
}

검은색 바탕에 있는 형형색색의 글자를 보고 있자면, 1 tick의 시간만으로도 코드가 눈에 들어온다.
그렇다. 그것은 마치 파블로프의 개마냥 전두엽이 조건반사를 하는것이다.

파블로프의 개

코딩할 때는 검은색 바탕을 쓰는 인구가 많을거라는 예상과 함께, 티스토리에서 기본으로 제공하는 코드하이라이트가 너무 밋밋한거 같아 vscode것을 그대로 쓰기로 했다. 그대로 적용을 하면 흰바탕이 되기에, html모드에서 배경색과 약간의 작업을 해줘야 하는 수고스러움이 있긴한데, 티스토리의 기본제공은 너무 기본적인것이다. 

 

... 그리고 나서 리퀘스트 값을 콘솔로 확인하는 소스를 작성하였다.

public static Dictionary<string, string> request(Socket client)
{
    byte[] data = new byte[8192];
    client.Receive(data);
    var strs = Encoding.UTF8.GetString(data).Trim('\0');
    String[] split = strs.Split("\r\n".ToCharArray());
    var dic = new Dictionary<String, String>();

    Dictionary<string, string> AddErr(String msg)
    {
        dic.Add("err", msg);
        Console.WriteLine(msg);
        return dic;
    }

    var top = split.FirstOrDefault();
    if (top == null || !Regex.IsMatch(top, "^(GET|POST) "))
        return AddErr("Bad request: Invaild method");

    dic = "method,url,http".Split(',')
    .Zip(top.Split(' '), (a, b) => new { a, b })
    .ToDictionary(x => x.a, x => x.b.Trim());

    if (!dic.ContainsKey("url")) return AddErr("Bad request: Can't find url");

    var infos = split.Skip(1)
    .Where(x => x.Trim().Length > 0)
    .Select(x => x.Split(':',2))
    .ToDictionary(x => x[0].Trim(), x => x.LastOrDefault()?.Trim());

    dic = dic.Concat(infos).ToDictionary(x => x.Key, x => x.Value);

    Console.WriteLine($"-------------[{DateTime.Now}]--------------");
    foreach (var t in dic)
    {
        Console.WriteLine($"{t.Key}: {t.Value}");
    }

    return dic;
}

트랜디하게, 함수형 프로그래밍을 하고 싶긴한데, 자바스크립트와는 그 그본이 달라 일일이 타입을 지정해야하는 에로사항이 있어, 생각의 전환이 쉽지가 안다. 그냥 Linq를 남발하며 아쉬움을 달래었다.
그리고 이상하게도 클라이언트 데이터를 리시브 해줘서 그런지 Thread.Sleep을 하지 않아도 전전편의 오류가 사라졌다.
뇌피셜100%로 클라이언트(브라우저)가 자기가 보낸 데이터가 완료 되었는지 확인을 할 수도 있겠는지 싶다.


오는 데이터는 막지말고, 가는 데이터는 붙잡지 않으면 만사형통이 된다는 나만의 뇌피셜이다.

 

... 그리고 콘솔창을 확인하였다.

오전 6시 15분: 이후에 나오는 4줄을 제외 하고는 뭘 뜻하는지는 모르겠다.

우선은 아는것에 집중 하고싶다.

つづく