2010-03-21 10 views
0

가능한 가장 짧은 단어로 문제를 설명하려고 시도합니다. 저는 C++ 빌더 2010을 사용하고 있습니다.비정상적으로 연결이 끊긴 TCP 소켓 및 쓰기 제한 시간

TIdTCPServer를 사용 중이며 음성 패킷을 연결된 클라이언트 목록에 보냅니다. 모든 것은 클라이언트가 비정상적으로 연결이 끊어지기 전까지는 정상적으로 작동합니다. 예를 들어 정전 등. 연결된 클라이언트의 이더넷 연결을 절단하여 유사한 연결을 재현 할 수 있습니다.

이제 연결이 끊긴 소켓이 있지만 알다시피 서버 측에서 아직 감지되지 않았으므로 서버는 계속 해당 클라이언트로 데이터를 보내려고합니다.

그러나 서버가 연결이 끊어진 클라이언트에 데이터를 쓰려고 할 때 ...... Write() 또는 WriteLn()이 쓰려고하는데 거기에 Write timeout의 몇 가지 종류에 대해 wating하는 것과 같습니다. 이렇게하면 홀 패킷 배포 프로세스가 중단되어 다른 모든 클라이언트에 대한 데이터 전송이 지연됩니다. 몇 초 후에 "Socket Connection Closed"예외가 발생하고 데이터 흐름이 계속됩니다.

여기

try 
{ 
EnterCriticalSection(&SlotListenersCriticalSection); 
for(int i=0;i<SlotListeners->Count;i++) 
{ 
    try 
    { 

     //Here the process will HANG for several seconds on a disconnected socket 
     ((TIdContext*) SlotListeners->Objects[i])->Connection->IOHandler->WriteLn("Some DATA"); 

    }catch(Exception &e) 
    { 
    SlotListeners->Delete(i); 
    } 
} 
}__finally 
{ 
LeaveCriticalSection(&SlotListenersCriticalSection); 
} 

가 좋아 난 이미이 비활성 n 초 후 소켓을 분리 살아 메커니즘을 계속 가지고있는 코드를입니다. 그러나 당신이 상상할 수 있듯이,이 브로드 캐스팅 루프는 거의 항상 작동하기 때문에이 메 치즘은이 브로드 캐스팅 루프와 정확히 동기화되지 않습니다.

그래서 iohandler 같은 것을 통해 지정할 수있는 쓰기 제한 시간이 있습니까? "Detecting tcp socket Detecting"에 대한 많은 스레드를 보았습니다.하지만 제 문제는 조금 다릅니다. 필자는 쓰기 시도 중 몇 초 동안 그 hangup을 피할 필요가 있습니다.

그래서 해결책이 있습니까?

아니면 방송 루프가 일종의 FIFO 버퍼에 데이터 패킷을 넣고 클라이언트 스레드가 사용 가능한 데이터를 지속적으로 확인하여 선택하여 전달하는 것과 같은 데이터 브로드 캐스팅을위한 다른 메커니즘을 사용해야한다고 생각합니까? 이 방법은 하나의 쓰레드가 멈 추면 전체 배포 쓰레드를 멈추거나 지연시키지 않습니다.

어떤 아이디어로주세요? 시간과 도움에 감사드립니다.

감사

걸림

답변

0

는 인디에서 구현 더 쓰기 시간 제한이 없습니다. 이를 위해서는 TIdSocketHandle.SetSockOpt() 메서드를 사용하여 소켓 수준 제한 시간을 직접 설정해야합니다.

FIFO 버퍼가 더 좋은 옵션입니다 (일반적으로 더 좋은 디자인입니다). 예 :

void __fastcall TForm1::IdTCPServer1Connect(TIdContext *AContext) 
{ 
    ... 
    AContext->Data = new TIdThreadSafeStringList; 
    ... 
} 

void __fastcall TForm1::IdTCPServer1Disconnect(TIdContext *AContext) 
{ 
    ... 
    delete AContext->Data; 
    AContext->Data = NULL; 
    ... 
} 

void __fastcall TForm1::IdTCPServer1Execute(TIdContext *AContext) 
{ 
    TIdThreadSafeStringList *Queue = (TIdThreadSafeStringList*) AContext->Data; 
    TStringList *Outbound = NULL; 
    TStringList *List = Queue->Lock(); 
    try 
    { 
     if(List->Count > 0) 
     { 
      Outbound = new TStringList; 
      Outbound->Assign(List); 
      List->Clear(); 
     } 
    } 
    __finally 
    { 
     Queue->Unlock(); 
    } 

    if(Outbound) 
    { 
     try 
     { 
      AContext->Connection->IOHandler->Write(Outbound); 
     } 
     __finally 
     { 
      delete Outbound; 
     } 
    } 

    ... 
} 

... 

try 
{ 
    EnterCriticalSection(&SlotListenersCriticalSection); 
    int i = 0; 
    while(i < SlotListeners->Count) 
    { 
     try 
     { 
      TIdContext *Ctx = (TIdContext*) SlotListeners->Objects[i]; 
      TIdThreadSafeStringList *Queue = (TIdThreadSafeStringList*) Ctx->Data; 
      Queue->Add("Some DATA"); 
      ++i; 
     } 
     catch(const Exception &e) 
     { 
      SlotListeners->Delete(i); 
     } 
    } 
} 
__finally 
{ 
    LeaveCriticalSection(&SlotListenersCriticalSection); 
} 
관련 문제