2010-08-08 8 views
0

따라서 약간의 배경 : 이 클래스는 HTTP 형식으로 원격 호출을 수락하고 응답하도록 생성됩니다.이상한 행동 : TcpListener

문제는 요청 방법이 POST인데 요청이 올바르게 처리되는 경우가 대부분이지만 클래스가 응답하지 않는 경우가 대부분입니다. 또한 "Debug1"및 "Debug2"행은 요청이 올바르게 처리 된 경우에도 콘솔에 기록되지 않습니다. "Debug3"줄은 요청이 올바르게 처리 될 때만 나타납니다.

나는 이것이 어질러 보일 것임을 알고있다. C#은 나를위한 취미 일 뿐이며, 나는 배우고있다. 이 코드를 통과하는 데 시간을 할애 해 주셔서 감사합니다!

class WebServer 
{ 
    private TcpListener myListener; 

    public WebServer(int port) 
    { 
     //Threading the listener 
     try 
     { 
      myListener = new TcpListener(IPAddress.Any, port) ; 
      myListener.Start(); 

      Thread th = new Thread(new ThreadStart(StartListen)); 
      th.Start() ; 
     } 
     catch(Exception e) 
     { 
      Logs.Add("WebServer|An Exception Occurred while Listening :" +e.ToString()); 
     } 
    } 
    private void StartListen() 
    { 
     int iStartPos = 0; 
     string sHttpVersion; 
     string sResponse = ""; 
     string sCode = " 200 OK"; 

     while(true) 
     { 
      //Accept a new connection 
      Socket mySocket = myListener.AcceptSocket(); 
      if(mySocket.Connected) 
      { 
       Byte[] bReceive = new Byte[1024]; 
       int i = mySocket.Receive(bReceive,bReceive.Length,SocketFlags.None); 
       string sBuffer = Encoding.ASCII.GetString(bReceive).TrimEnd('\0'); 

       iStartPos = sBuffer.IndexOf("HTTP",1); 
       sHttpVersion = sBuffer.Substring(iStartPos,8); //http version (ex: "HTTP/1.1") 

       if (sBuffer.StartsWith("GET/")) 
       { 
        Logs.Add("WebServer|Connected:" + mySocket.RemoteEndPoint.ToString()); 
        sResponse = ArrayToJson(); 
       } 
       else if (sBuffer.StartsWith("POST")) 
       { 
        Console.WriteLine("Debug1"); 

        //This is a POST request, so more data is waiting to be retreived... 
        bReceive = new Byte[2048]; 
        i = mySocket.Receive(bReceive,bReceive.Length,SocketFlags.None); 
        sBuffer = Encoding.ASCII.GetString(bReceive).TrimEnd('\0'); 

        Console.WriteLine("Debug2"); 

        //Parsing the request 
        string[] sParams = sBuffer.Split(','); 
        Console.WriteLine(sParams.Length); 
        Console.WriteLine("Debug3: {0} - {1} - {2} - {3} - {4}", sParams[0], sParams[1], sParams[2], sParams[3], sParams[4]); 

        //I do what needs to be done here 

        Logs.Add("WebServer|BotStartRequest:" + mySocket.RemoteEndPoint.ToString()); 
        sResponse = "Accepted"; 
       } 

       //Sending response and closing socket 
       SendHeader(sHttpVersion, "text/html", sResponse.Length, sCode, ref mySocket); 
       SendToBrowser(sResponse, ref mySocket); 
       mySocket.Close(); 
      } 
     } 
    } 
} 

}

+0

수신 버퍼의 크기를 올리려고 했습니까? 브라우저가> 2048 바이트를 보내는 경우에는 요청의 일부만 읽었을 때 대화가 '사기성 상태'로 남을 수 있다고 예상 할 수 있습니다. –

+0

그 시체가 2048 바이트에 근접한 것을 본 적이 없으므로 그것이 문제가 될지 의심 스럽습니다. 또한 몇 가지 다른 리퀘스트로 테스트를 해봤는데, 대부분이 똑같은 몸체를 가지고 있으며, 여전히 무작위로 작동합니다 ... – Ben

+0

이것은 포팅 된 C++이며 관용적 인 C#이 아니기 때문에 디버깅이 매우 어렵습니다. while 루프 안에 try/catch + 로그가 필요하다. 버퍼를 처리하는 방식은 비효율적이며 문제의 원인 일 가능성이 큽니다. –

답변

4

HTTP 구현/1.1은 간단한 일이 아니다 : 여기

는 코드입니다. 기본 프로토콜은 매우 단순 해 보이지만 적어도 서버 구현을 올바르게 구현하는 것은 매우 어렵습니다. POST의 경우에는 Expect : 100-continue 헤더의 헤더를 올바르게 구문 분석하여 지속적 연결에 대해 생각해보십시오. , 그리고 훨씬 더.

기존 라이브러리/코드를 살펴 보는 것이 좋습니다. 예를 들어, HttpListener 클래스는 .NET Framework에 내장되어 있으며 아마도 필요한 모든 기능을 제공 할 것입니다.

처음부터 서버를 구현하려면 Microsoft Cassini, Ms-PL 라이선스가있는 C#으로 작성된 간단한 HTTP 서버를 살펴보십시오.

+0

고마워, 내가 제대로 작동하지 않는다면 아마 끝날거야. 그러나 그것을 사용하는 것이 너무 간단해서 기존의 라이브러리를 사용하지 않고 자신 만의 라이브러리를 만들고 싶었 기 때문입니다. – Ben