2010-08-13 3 views
3

문제 개요 : 지금까지 사용자 지정 http 서버 응용 프로그램을 작성하는 중이었습니다. 내 웹 브라우저가 내 서버 앱에 연결되면 요청이 처리되기 전에 (Chrome에 따라) 0.5-1 초의 "대기 시간"이 발생한다는 것을 알았습니다. [밀리 초가 걸릴 수도 있습니다]연결을 시도하는 브라우저와 Socket.Accept() 간의 지연이 ~ ~ 1s입니다.

결국 시도했습니다. 문제를 찾아 낼 더미 프로그램을 만들려면 :

using System.Text; 
using System.Net; 
using System.Net.Sockets; 

namespace SlowHTTPServer 
{ 
    class FailServer 
    { 
     static void Main() 
     { 
      //Create socket object, bind it, listen to 80 
      Socket listenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
      listenerSocket.Bind(new IPEndPoint(IPAddress.Any, 80)); 
      listenerSocket.Listen(64); 

      while (true) 
      { 
       Socket clientConn = listenerSocket.Accept();   //Accept 
       System.DateTime startTime = System.DateTime.Now; 

       byte[] buffer = new byte[1024];       //Request header buffer 
       clientConn.Receive(buffer);        //Recieve request header 

       string reqHeader = Encoding.ASCII.GetString(buffer); //Get the string version of it 
                     //We completely ignore most of the request header lol 

       //Normally i'd send a response header but... 
       if (reqHeader.IndexOf("script1") != -1)     //script1.js - document.title='hai dere' 
        clientConn.Send(Encoding.ASCII.GetBytes("document.title='hai dere';")); 
       else if (reqHeader.IndexOf("script2") != -1)   //script2.js - Get a pretty background color onload 
        clientConn.Send(Encoding.ASCII.GetBytes("window.onload=function(){document.body.style.backgroundColor='#FF99FF';};")); 
       else if (reqHeader.IndexOf("iframe") != -1)    //Noob iframe that just has text. 
        clientConn.Send(Encoding.ASCII.GetBytes("blargh zargh nargh dargh pikachu tangerine zombie destroy annihilate")); 
       else             //hai dere is the body.innerHTML, load script1.js and script2.js 
        clientConn.Send(Encoding.ASCII.GetBytes("<html><head><script src='script1.js'></script><script src='script2.js'></script></head><body>mainPage<iframe src='iframe.html'>u no haz iframe</iframe></body></html>")); 

       clientConn.Close();          //Close the connection to client. We've done such a good job! 

       System.Console.WriteLine((System.DateTime.Now - startTime).TotalMilliseconds); 
      } 
     } 
    } 
} 

을 ... 그리고, 지금은 완전히 혼란 스러워요 위의 프로그램은 2 번째 스팬 [이상 웹 브라우저 페이지 + 스크립트 + iframe이 서비스를 제공하기 때문에 로컬 호스트에서 로컬 호스트로 연결, Windows 방화벽 + 바이러스 백신 해제]. Apache와 같은 서버를 사용하면 요청은 [당연히 파일 시스템에서 미리 만들어진 파일을 사용하여] 100 밀리 초 이내에 처리됩니다.

내가 볼 수있는 코드에서 내가 게시 한 코드는 극단적으로 삭제 된 http 서버입니다. 응답 헤더를 보내거나 보내지 않으면 성능이 변경되지 않습니다.

이 문제는 완전히로드 페이지 20 + 초를 가지고, 내가 30 + 자바 스크립트 스크립트 파일이 프로젝트가있을 때 매우 성가신된다 [스크립트가있을 때 받아 들일 수있는 모든 < 10킬로바이트]

당신이 보는 경우 스크립트에서 소켓을 허용 할 때와 닫을 때를 추적하고 처리 시간은 보통 1-10 밀리 초이며 이는 HTTP 서버와 웹 브라우저 사이에 있음을 의미합니다. [연결 전에 수락 되셨습니까?]

나는 곤란하며 도움이 필요합니다. 감사합니다. .

기타 참고 사항 : - 내가 작성한 "실제"서버는 클라이언트 연결을 수락하고 작업을 수행하기 위해 다른 스레드로 전달하므로 바이트를 보내고 연결을 닫는 작업이 그만한 이유는 아닙니다. 지연.
가 난을 만들어 문제를 시뮬레이션하기 위해 시도 :
Chrome's developer tools showing the load times


추가 프로그램 : - 프로그램을 실행하는 코드를 테스트하고 http://127.0.0.1/ 또는 http://localhost/

이미지로 이동, 포트 80에 바인딩 매우 간단한 서버/클라이언트 프로그램 ... 문제는 재현되지 않았고 연결 시간은 1 밀리 초였습니다. 내가 더

using System; 
using System.Text; 
using System.Net; 
using System.Net.Sockets; 
using System.Threading; 

namespace SlowSocketAccept 
{ 
    class Program 
    { 
     static DateTime connectionBeginTime; 
     static bool listening = false; 
     static void Main(string[] args) 
     { 

      new Thread(ClientThread).Start(); 
      Socket listenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
      listenerSocket.Bind(new IPEndPoint(IPAddress.Any, 80)); 
      listenerSocket.Listen(80); 

      listening = true; 
      Socket newConn = listenerSocket.Accept(); 
      byte[] reqHeader = new byte[1024]; 
      newConn.Receive(reqHeader); 
      newConn.Send(Encoding.ASCII.GetBytes("Response Header\r\n\r\nContent")); 
      newConn.Close(); 

      Console.WriteLine("Elapsed time: {0} ms", (DateTime.Now - connectionBeginTime).TotalMilliseconds); 

     } 
     static void ClientThread() 
     { 
      while (listening == false) ; //Busy wait, whatever it's an example 
      System.Threading.Thread.Sleep(10); //Wait for accept to be called =/ 

      Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
      connectionBeginTime = DateTime.Now; 
      s.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 80)); 
      s.Send(Encoding.ASCII.GetBytes("Request Header")); 
      byte[] response = new byte[1024]; 
      s.Receive(response); 
     } 
    } 
} 

을 난처한 상황에 빠진하고 [a와 b입니다 스레드]
가) 실행 스레드 'B'
b)는 통화 중 대기, A는이
가) 소켓을 만들고 연결 괜찮아 말하는 플래그를 설정까지, 80을 청취하기 시작, B에 알리는 플래그를 설정하십시오.
b) 소켓을 만들고 현재 시간을 저장하고 127.0.0에 연결하십시오.1:80 [로컬 호스트 : 80]
a) 스레드가 연결을 받아 들여서 듣기를 시작합니다.
b) 스레드가 더미 문자열을 전송합니다 [우리의 요청 헤더]
a) 더미 문자열을 받아 들인 다음 더미 문자열 [response header + 내용]
A) 밀접한 관계

경과 시간은 약 1 밀리 초입니다 =/

답변

2

당신은 콘텐츠 길이 헤더를 포함하지 않는 한 - 그리고 하나는 HTTP 1.0을 사용하고 있는지, 또는 그 지정 연결이 닫혀 야합니다 - 브라우저가 연결이 닫혀 있음을 알 때까지 내용을 계속 읽습니다 (시간이 걸릴 수 있음).

앱이 Content-Length 헤더와 "Connection : close"를 보내고 있는지 확인하십시오.

또한 클라이언트 소켓을 닫기 전에 닫아야합니다. 이 말은 .net (그리고 아마도 다른 쪽, 나는 잊는다)은 데이터 전송을 마쳤고 네트워크로 플러시되고 연결이 재설정되어야한다는 것을 의미한다. Close은 코드 측면의 것입니다. Shutdown은 실제로 클라이언트의 관점에서 연결을 닫는 것입니다.

+0

필자는 127.0.0.1로 갈 경우 솔루션이 내로드 시간을 [30 초에서 1 초로] 많이 낮 춥니 다. 그러나, 대신 localhost로 이동하는 경우로드 시간은 여전히 ​​호스트 파일에 따라 localhost == 127.0.0.1 이래로 나에게 이해가되지 않는 20 초 이상 지속됩니다. 어떤 아이디어가 계속 될 수 있습니까? 바이러스 백신을 사용할 수 없습니다. 192.168.0.194 [내 네트워크의 내 IP]로 이동하면로드 시간도 30 초가 아니라 1 초가됩니다. – Warty

+0

총계는 여기 있지만 헤더를 보았습니까? "Host : localhost"헤더를 추가하면 1024 바이트를 초과하는 헤더 크기가 발생하고 (1024 바이트를 읽는 것만 큼 헤더를 확인하지 않기 때문에) 문제가 발생할 수 있습니다. 서버는 이전에 브라우저는 무엇이든받을 것으로 예상됩니다. 사실상 대기 시간이 없으므로 localhost에서 특히 눈에.니다. – cHao

+0

사실, 코드는 헤더를보고 있어야하며 유효한 요청이 있는지 확인해야합니다. 브라우저는 일반적으로 옳은 일을하지만 위 참조. 덜 맛있는 캐릭터는 느슨한 검사를 활용할 수있는 방법을 찾게됩니다. – cHao

관련 문제