2012-07-15 2 views
2

내 응용 프로그램 (winsock2.h)에 Windows 소켓을 사용하고 있습니다. 블로킹 소켓은 연결 시간 초과를 제어 할 수 없으므로 블로킹을 사용하지 않습니다. 바로 명령을 내 보낸 후 종료 명령을 사용하여 플러시합니다 (필자는해야만합니다). 시간 제한이 50ms이고 전송할 데이터가 너무 크면 데이터의 일부만 전송하거나 아무것도 보내지 않을 위험이 있습니까? 미리 감사드립니다 ...비 차단 TCP 소켓과 보내기 직후 플러시?

hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    u_long iMode=1; 
    ioctlsocket(hSocket,FIONBIO,&iMode); 
    connect(hSocket, (sockaddr*)(&sockAddr),sockAddrSize); 
    send(hSocket, sendbuf, sendlen, 0); 
    shutdown(hSocket, SD_BOTH); 
    Sleep(50); 
    closesocket(hSocket); 
+0

글쎄, 나는 꽤 잘 소켓을 차단과 함께 잘 작동 확신 - 나는 클라이언트 스레드 내에서 항상 이렇게 - 연결이 끊어진 경우, 그들은 루프 (connect) (시도 및 잠 (2000) 라운드), 성공할 때까지 계속해서 연결을 다시 시도합니다. connect()가 성공한 후에 connect timeout은 소켓 쓰기와 관련이 없으므로 write timeout 형식을 의미한다고 가정합니다. 그렇다면 성능이 좋지 않아 (특히 대기 시간이 긴 링크에서) 연결/연결 끊기 프로토콜 (브라우저/HTTP 제외)을 사용하지 않습니다. –

+0

select()를 사용하여 차단 모드를 제한 시간 초과로 연결할 수 있습니다. 플러시하기 위해 shutdown()을 호출 할 필요가 없습니다. TCl은 데이터를 잃지 않습니다. 그렇지 않으면 인터넷이 작동하지 않습니다. 이 포럼, 아마존, 구글, 등등. 귀하의 질문은 가짜 전제를 기반으로합니다. – EJP

+0

소켓 상태를 "선택"하고 연결 끊김을 확인 하시겠습니까? 최대한 빨리 데이터를 보내고 싶습니다. 또한 가능한 두 가지 경우가 있습니다 : 서버가 너무 오래 연결 또는 수신을 기다립니다. 따라서 연결과 글쓰기 모두가 내 상황에서 시간이 매우 중요하기 때문에 최대 50ms 이내에 완료되어야합니다. 서버가 불필요하게 큰 데이터를 계속 보내고 인터넷 연결이 제한되어 있기 때문에 스트림을 쓰고 읽는 작업을 모두 플러시해야합니다. 사실 나는 심지어 서버에서 단일 바이트 싶지 않아 :) – theGD

답변

-2

감사합니다. EJP와 Martin 덕분에 이제 두 번째 스레드를 확인했습니다. 또한 내 질문에 게시 된 코드에서 "카운터 = 0;"추가했습니다. "send"줄 다음에 줄을 입력하고 종료를 제거합니다. 그것은 내가 지금 원했던 것처럼 작동합니다. 이 이상은 50ms :) 정말 큰 감사

을 기다립니다 결코
unsigned __stdcall SecondThreadFunc(void* pArguments) 

{

while(1) 
{ 
    counter++; 
    if (counter > 49) 
    { 
     closesocket(hSocket); 
     counter = 0; 
     printf("\rtimeout"); 
    } 

    Sleep(1); 
} 
return 0; 

}

+0

나는 이것을 비난 받기를 정말로 거부한다. 그것은 당신의 질문에 대답하지 않습니다. 당신이 생각하는대로 행동하지 않습니다. 비행중인 모든 데이터는 계속 전송되며 닫기 신호가 전송됩니다. 어떤 종류의 타임 아웃도 구현하지 않습니다. – EJP

0

비 차단 TCP 소켓 및 전송 후 바로 세척?

TCP 소켓을 플러시하는 것과 같은 것은 없습니다.

차단 소켓이 나를 연결 시간 초과

거짓을 제어 할 수 없기 때문에

. 블로킹 소켓에 select()을 사용할 수 있습니다.

비 차단 항목을 사용하고 있습니다.

비 연속.

바로 보내기 명령을 내릴 때 종료 명령을 사용하여 플러시합니다 (해야 함).

당신은 할 필요가 없습니다. shutdown()은 아무 것도 플러시하지 않습니다.

내 타임 아웃이

이유는 50ms의입니까? 데이터를 보내는 데 걸리는 시간은 데이터 크기에 따라 다릅니다. 명백하게. 센드에 고정 된 타임 아웃을 사용하는 것은 의미가 없습니다.

내가 보내고 자하는 데이터가 너무 큰 경우 데이터의 일부만 전송하거나 전혀 보내지 않을 위험이 있습니까?

차단 모드에서 가능한 경우 send()에 제공 한 모든 데이터가 전송됩니다. 비 차단 모드에서는 가능한 경우 반환 값 send()으로 표시되는 데이터의 양이 전송됩니다. 두 경우 모두 전송에 실패하면 연결이 재설정됩니다. 당신이 수퍼 임 포즈하는 어떤 타임 아웃 메카니즘이라도 그 중 하나를 변경할 수는 없습니다 : 특히, 타임 아웃 후에 소켓을 비동기 적으로 닫으면 전송되는 데이터에 클로즈가 추가됩니다.이 아닐 경우은 전송을 중단시킵니다.

코드가 사람에게 알려진 코드 검토를 통과하지 못합니다. 오류 검사는 제로입니다. 잠은 완전히 무의미합니다. 닫기 전에 종료가 중복됩니다. 수면 시간 제한을 구현하기위한 것이면 그렇게하지 않습니다.

최대한 빨리 데이터를 보내고 싶습니다.

수 없습니다. TCP는 흐름 제어를 구현합니다. 그것에 대해 할 수있는 일은 정확히 없습니다. 당신은 수신기에 의해 속도 제한됩니다.

는 또한 2 가지 경우가 있습니다 : 서버가 연결

그런 경우가 없습니다에게 동의하는 데 시간이 너무 오래 기다립니다. 클라이언트는 약 1 분의 기본보다 짧은 연결 시간 제한을 구현하려는 경우 서버가 이제까지 accept().를 호출하기 전에 연결을 완료 select().

를 사용하거나받을 수 있습니다.

위 내용을 참조하십시오.

내 상황에서는 시간이 중요하기 때문에 연결 및 쓰기는 모두 최대 50ms에서 이루어져야합니다.

위 참조. 가변 시간을 사용하는 작업에 고정 된 시간 제한을 구현하는 것은 의미가 없습니다. 그리고 50ms는 연결 타임 아웃에 비해 너무 짧습니다. 이것이 진짜 문제라면 연결 지연을 한 번만 발생하도록 연결을 열어 두어야합니다. 사실 TCP 연결을 최대한 길게 유지해야합니다.

나는 모두 쓰기를 플러시해야 읽기 당신은 할 수 없습니다

스트리밍합니다. TCP에는 읽기 스트림 또는 쓰기 스트림을 비우는 조작이 없습니다.

서버가 계속 불필요하게 큰 데이터를 보내고 인터넷 연결이 제한되어 있기 때문입니다.

또 다른 비 연속. 서버가 데이터를 보내는 경우이를 읽어야합니다. 그렇지 않으면 서버를 멈추게 할 것이며 자체 쓰기 스트림을 플러시하는 것과 아무런 관련이 없습니다.

사실 난 서버

불운에서 단일 바이트를 원하지 않는다. 당신은 그것을 읽어야합니다. [BSD Unix에서 입력을 위해 소켓을 종료하면 서버의 데이터가 버려지지만 Windows에서는 작동하지 않으므로 서버가 연결 재설정을 가져옵니다.]

+0

오 코드가 완료되지 않았습니다. 게시 한 코드는 두 번째 스레드에만 있습니다. 3 방향 핸드 셰이크가 완료되고 전송할 데이터가 내 컴퓨터에서 (전선으로) 빠져 있다면 간단히 카운터를 0으로 재설정합니다. 그래서 실제로 작동합니다. 또 하나의 선택은 밀리 초가 아닌 초 단위의 타임 아웃을 허용한다는 것입니다. 마지막으로, 내가 기억하는 한, 버퍼에서 데이터를 플러시하는 것을 의미했습니다. 지금 지연 옵션을 사용하고 있습니다 ... – theGD

+0

당신의 방법은 실패하지 않는 의미에서 작동하지만, 당신이 요구하는 것을 수행하지 않습니다 : 쓰기 타임 아웃을 시행하십시오. 그것이하는 일은 작업 소켓을 gratuitously 닫기입니다. 다시 '다른 것', 당신은 착각합니다. 'select()'는 초와 마이크로 초의 필드를 가진'timeval' 구조체 형태로 타임 아웃을 허용합니다. 'shutdown()'은 여전히 ​​소켓을 플러시하지 않는다. 단지 소켓 보내기 버퍼를 플러시한다는 의미 일 뿐이다. 정상적인 전송이나 리셋 만 가능합니다. – EJP