2011-02-24 4 views
1

.NET 소켓과 NetworkStream은 모두 사용할 수있는 데이터가 없을 때 차단하는 Read 메서드를 제공합니다. 문제는 클라이언트가 메시지의 크기를 알지 못하면 서버가 메시지를 보낼 때 이해할 수있는 확실한 방법이 없다는 것입니다.HTTP 수준에서 .NET 소켓 읽기를 중지하는시기를 알아야합니다.

내 질문은 - 어떤 원칙을 높은 수준의 라이브러리 (예 : HTTP 수준의 WebRequest) 소켓에서 읽기를 중지하고 모든 종류의 읽기 시간 제한을 사용하지 않고 클라이언트에 전체 메시지를 표시하는 데 사용합니까? HTTP 프로토콜이 "EOF"토큰을 제공하지 않는 것 같습니다 ...

답변

3

HTTP 1.1은 두 가지 메커니즘 중 하나를 사용하여이를 관리합니다. content-length이 머리글로 전송되거나 chunked transfer encoding이 사용됩니다. Chunked Transer Encoding은 HTTP 1.0을 통한 HTTP 1.1의 큰 장점 중 하나입니다. Content-Length가 전송되지 않은 경우 전송 끝을 신뢰할 수 없게 검색 할 수 없으므로 전송 문제와 실제 페이로드 끝 사이에 모호성이 생깁니다 . HTTP를 통한 오디오 스트림과 같은 일부 경우에는 전송 길이를 나타내는 콘텐츠 길이 또는 다른 인코딩이 없지만이 경우 클라이언트에게 중요하지 않습니다.

+0

고마워, 정확히 내가 필요로했던 것! – Konstantin

0

HTTP에서 content-length HTTP 헤더는 소켓을 닫을 수있는시기를 정의합니다.

TCP에서 이것은 임의적이며 일반적으로 클라이언트 또는 서버는 연결이 종료되었음을 알리는 특수 메시지를 보냅니다.

1

소켓에 데이터가 보류 중인지 확인하는 몇 가지 방법이 있습니다. 하나는 단순히 각 소켓의 Pending 속성을 확인하고 데이터가 있으면 Receive 만 호출하는 것입니다. 그러나 이것은 전혀 잘 확장되지 않으며, 단 한 번의 연결만으로 응용 프로그램에서 사용하는 것이 좋습니다.

Socket.Select 함수는 소켓의 IList를 취할 수 있으며 잠시 후에 보류중인 데이터가있는 소켓 만 포함하도록이 목록을 줄입니다. 차단없이 안전하게 수신 할 수 있습니다.

다른 방법이 비동기 소켓 API를 사용하는 것이 좋습니다. (BeginReceive 또는 NetworkStream의 BeginRead)로 전화하십시오. 이러한 경우 호출이 차단되지 않으며 호출 후 코드를 계속 실행할 수 있습니다. 데이터가 소켓에서 보류 중일 때 실행될 인수로 함수를 전달합니다. 이 문제는 .NET 스레드 풀의 백그라운드 스레드에서 처리되므로 앞의 두 메서드와 달리 여기에 관련된 동시성 문제가 있습니다. 비동기식 작업은 OS에서 훨씬 낮은 수준에서 이루어지며, Select와 같이 반복적으로 데이터를 폴링하는 대신 인터럽트를 사용하여 데이터가 네트워크에서 대기 중일 때 CPU에 알려줍니다.

+0

'Socket.Select'는 윈도우에서'select' 호출을 사용하지 않습니까? :(즉, 정말 바보 같은 구현이 아니라면 "반복적으로 폴링"하지 않아야합니다. (내가 아는 다른 언어/라이브러리에서는이를 수행하지 않습니다.) –

+0

select가 어떻게 구현되는지 모르지만, 비동기 메서드에서는 폴링 할 필요가 없지만 데이터가 보류 중일 때만 중단됩니다. –

+0

[빠른] 경우 선택이 올바르게 사용되지 않습니다. 폴링 - 아이디어는 핸들이 읽기/쓰기/oob을 위해 사용 가능하게 될 때까지 기다리는 것입니다. (그리고 그 시간까지 또는 [선택 사항] 타임 아웃이 발생하거나 다른 방법으로 중단되었을 때까지 호출이 차단 될 것입니다.) 그 자체로 설정하는 것은 까다로운 일입니다. 나는 'Begin/End' 제안에 동의한다. –