2012-03-16 4 views
3

Я хочу сделать TCP-сервер, который прослушивает порт 443, чтобы он мог получать HTTP-запросы и отправлять сообщения назад.Как настроить HTTP-запросы на tcp-сервер?

Прямо сейчас я использую Apache & PHP, чтобы сделать это обычным способом, но возможно ли это сделать без веб-сервера?

Например, я создал традиционное клиент/серверное приложение TCP/IP в C# .NET. Можно ли использовать эту реализацию для обработки HTTP-запросов вместо использования веб-сервера?

+1

Уверен, что это возможно. Однако «хочу ли я снова реализовать HTTP снова?» это еще один вопрос. – Jon

+0

Этот проект использует TcpListener для обслуживания HTTP-запросов: http://www.codeproject.com/Articles/1505/Create-your-own-Web-Server-using-C –

+0

Нет, это не так. Если вы обрабатываете HTTP-запросы, у вас есть веб-сервер. Вы спрашиваете: «Как я могу создать свой собственный веб-сервер». – svick

ответ

1

Этот проект может помочь вам создать веб-сервер с нуля: MiniHttpd: an HTTP web server library используя чистый TCP/IP

Но вместо того, чтобы иметь дело с большим количеством ненужных деталей таких как разбор заголовков, сжатие, аутентификация, ssl и т. д. Я бы использовал встроенный класс HttpListener.

Вот упрощенная (но работает) многопоточный WebServer

void CreateWebServer() 
{ 
    HttpListener listener = new HttpListener(); 
    listener.Prefixes.Add("http://*:8080/"); 
    listener.Start(); 

    new Thread(
     () => 
     { 
      while (true) 
      { 
       HttpListenerContext ctx = listener.GetContext(); 
       ThreadPool.QueueUserWorkItem((_) => ProcessRequest(ctx)); 
      } 
     } 
    ).Start(); 
} 

void ProcessRequest(HttpListenerContext ctx) 
{ 
    string responseText = "Hello"; 
    byte[] buf = Encoding.UTF8.GetBytes(responseText); 

    Console.WriteLine(ctx.Request.Url); 

    ctx.Response.ContentEncoding = Encoding.UTF8; 
    ctx.Response.ContentType = "text/html"; 
    ctx.Response.ContentLength64 = buf.Length; 


    ctx.Response.OutputStream.Write(buf, 0, buf.Length); 
    ctx.Response.Close(); 
} 

EDIT

Я изменил серверу немного, чтобы сделать его провести RESTful WebService (MyService). Он возвращает результат как Json. Вы можете назвать это http://localhost:8080/?method=Calc&i=5&j=4 (я просто пропустил множество проверок ошибок)

public class MyService 
{ 
    public Result Calc(int i, int j) 
    { 
     return new Result() { Addition = i + j, Multiplication = i * j }; 
    } 
} 

public class Result 
{ 
    public int Addition { set; get; } 
    public int Multiplication { set; get; } 
} 

void CreateWebServer() 
{ 
    MyService service = new MyService(); 

    HttpListener listener = new HttpListener(); 
    listener.Prefixes.Add("http://*:8080/"); 
    listener.Start(); 

    new Thread(
     () => 
     { 
      while (true) 
      { 
       HttpListenerContext ctx = listener.GetContext(); 
       ThreadPool.QueueUserWorkItem((_) => ProcessRequest(ctx,service)); 
      } 

     } 
    ).Start(); 
} 

void ProcessRequest(HttpListenerContext ctx,MyService service) 
{ 
    try 
    { 
     string responseText = Execute(ctx, service); 

     byte[] buf = Encoding.UTF8.GetBytes(responseText); 

     ctx.Response.ContentEncoding = Encoding.UTF8; 
     ctx.Response.ContentType = "application/json"; 
     ctx.Response.ContentLength64 = buf.Length; 


     ctx.Response.OutputStream.Write(buf, 0, buf.Length); 
    } 
    catch 
    { 
     ctx.Response.StatusCode = (int) HttpStatusCode.NotFound; 
    } 

    ctx.Response.Close(); 
} 

string Execute(HttpListenerContext ctx, MyService service) 
{ 
    System.Collections.Specialized.NameValueCollection nv = HttpUtility.ParseQueryString(ctx.Request.Url.Query); 

    MethodInfo mi = service.GetType().GetMethod(nv["method"]); 
    object[] parameters = mi.GetParameters() 
          .Select(pi => Convert.ChangeType(nv[pi.Name], pi.ParameterType)) 
          .ToArray(); 

    return JsonConvert.SerializeObject(mi.Invoke(service, parameters)); 
} 
+0

Как я могу получить данные из запроса страницы, используя вашу технику? скажем, если я ввел: http: // localhost: 8080 /? name = someName –

+1

@StormKiernan 'System.Collections.Specialized.NameValueCollection nv = HttpUtility.ParseQueryString (ctx.Request.Url.Query);' –

+1

@StormKiernan Я обновил ответьте так, чтобы веб-сервер размещал * webservice *. –

3

На самом низком уровне вы можете сделать это, используя HTTP Listener Class.

http://geekswithblogs.net/Nitin/archive/2008/06/22/using-the-http-listener-class.aspx

я написал что-то подобное, как уни проекта один раз, так что я могу найти код, если у вас есть какие-то конкретные вопросы.

Если вы хотите пойти выше, вы можете посмотреть веб-службы.

Вот часть моего кода ... посмотрите, что вы можете с ним сделать. :

IPAddress address = IPAddress.Parse("127.0.0.1"); 
     IPEndPoint port = new IPEndPoint(address, 9999); //port 9999 

     TcpListener listener = new TcpListener(port); 

     listener.Start(); 

     Console.WriteLine("--Server loaded--"); 

     while (true) //loop forever 
     { 

      Console.WriteLine("Waiting for New Client"); 
      Socket sock = listener.AcceptSocket(); 
      byte[] buffer = new byte[32]; 

      string incomingMessage=""; 

      //read: 
      while (sock.Available > 0) 
      { 
       int gotBytes = sock.Receive(buffer); 
       incomingMessage += Encoding.ASCII.GetString(buffer, 0, gotBytes); 

      } 

      //debugging: 
      //Console.WriteLine(incomingMessage); 

      //Now check whether its a GET or a POST 

      if (incomingMessage.ToUpper().Contains("POST") && incomingMessage.ToUpper().Contains("/DOSEARCH")) //a search has been asked for 
      { 

       Console.WriteLine("Query Has Been Received"); 

       //extracting the post data 

       string htmlPostData = incomingMessage.Substring(incomingMessage.IndexOf("songName")); 

       string[] parameters = htmlPostData.Split('&'); 

       string[] inputs = new string[5]; 

       for (int i=0; i<parameters.Length; i++) 
       { 
        inputs[i] = (parameters[i].Split('='))[1]; 
        inputs[i] = inputs[i].Replace('+',' '); 
       } 

...

byte[] outbuffer = Encoding.ASCII.GetBytes(answerPage.ToString()); 
       sock.Send(outbuffer); 

       Console.WriteLine("Results Sent"); 

       sock.Close(); 
Смежные вопросы