2011-03-22 2 views
1

네트워크 대기 시간을 전송에 적용하는 "man-in-middle"스타일 응용 프로그램을 만들었습니다. 악의적 인 용도로 사용하지 말고 선언해야합니다.타이머를 기반으로 구조체의 개별 데이터 출력

그러나 데이터 구조 (LinkedList<string> buffer = new LinkedList<string>();)의 올바른 출력 메커니즘에 문제가 있습니다. 어떻게해야합니까

: clientA에서 구조로

  • 데이터 읽기. ClientB에 데이터를 해제 할 때 추적 개별적 또는 전체적인 타이머 사용

    if (buffer.First != null && buffer.Last != null) { buffer.AddAfter(buffer.Last, ServerRead.ReadLine().ToString());
    } else buffer.AddFirst(ServerRead.ReadLine().ToString());

  • . (대기 시간을 조정할 수있는 조정 가능한 타이머)

  • 구조의 항목에 대한 타이머가 트리거되어 clientB에 패킷을 릴리스합니다.
  • 정리 무료 데이터 구조 노드

    if (buffer.First != null) {
    clientWrite.WriteLine(buffer.First.Value.ToString());
    clientWrite.Flush();
    buffer.RemoveFirst(); }

그러나 나는 clientB에 데이터 출력을 처리하는 스레드를 트리거하는 글로벌 타이머를 만들 수 System.Windows.Forms.Timer를 사용하려고하고있다. 그러나이 기술은 너무 느릴 때도 마찬가지입니다. myTimer.Interval = 1; 이것은 목록을 지우고 추가 할 때 동시 처리 문제를 만듭니다. 일시적인 해결책은 자원을 잠그는 것입니다. 그러나 이것이 느린 것을 추가하는 것 같아요. 데이터 출력의 성능.

질문 : 나는 데이터에 (달걀 타이머 효과와 같은) 타이머를 데이터 구조에 데이터를 저장하고 적용 할 수있는 솔루션에 대한 몇 가지 아이디어가 저장이 필요하고 타이머가 다 떨어지기 때에 전송됩니다 다른 고객들에게가는 길.

감사합니다.

답변

3

링크 된 목록이 제대로 작동하고 제대로 잠그지 않으면 성능이 저하 될 수 있습니다. ConcurrentQueue을 사용하면 훨씬 편리 할 것입니다. 스레드로부터 안전하므로 명시 적 차단을 수행 할 필요가 없습니다.

Windows Forms 타이머 대신 System.Threading.Timer을 사용하는 것이 좋습니다. 하지만 여전히 약 15ms 해상도로 제한 될 것입니다. 즉, 타이머 간격이 1 인 경우에도 유효 지연 시간은 1ms가 아닌 15 ~ 25ms입니다. 타이머가 구현되는 방식 일뿐입니다.

또한 지정된 시간 (각 항목이 일정하다고 가정) 동안 각 항목을 지연하려면 "현재 시간"이라는 개념이 필요합니다. DateTime.Now 또는 그 변형을 사용하지 않는 것이 좋습니다. 시간이 변경 될 수 있기 때문입니다. 오히려 응용 프로그램 별 시간을 얻으려면 Stopwatch을 사용합니다.

또한 항목의 출시 시간을 추적 할 수있는 방법이 필요합니다. 항목을 보관하는 클래스 및 전송할 시간입니다. 다음과 같음 :

class BufferItem 
{ 
    public string Data { get; private set; } 
    public TimeSpan ReleaseTime { get; private set; } 
    public BufferItem(string d, TimeSpan ts) 
    { 
     data = d; 
     ReleaseTime = ts; 
    } 
} 

좋아요. 모두 정리해 봅시다.

// the application clock 
Stopwatch AppTime = Stopwatch.StartNew(); 
// Amount of time to delay an item 
TimeSpan DelayTime = TimeSpan.FromSeconds(1.0); 
ConcurrentQueue<BufferItem> ItemQueue = new ConcurrentQueue<BufferItem>(); 
// Timer will check items for release every 15 ms. 
System.ThreadingTimer ReleaseTimer = new System.Threading.Timer(CheckRelease, null, 15, 15); 

항목을 수신 :

// When an item is received: 
// Compute release time and add item to buffer. 
var item = new BufferItem(data, AppTime.Elapsed + DelayTime); 
ItemQueue.Add(item); 

타이머 proc 디렉토리.

void CheckRelease(object state) 
{ 
    BufferItem item; 
    while (ItemQueue.TryPeek(out item) && item.ReleaseTime >= AppTime) 
    { 
     if (ItemQueue.TryDequeue(out item)) 
     { 
      // send the item 
     } 
    } 
} 

성능이 우수해야하며 동시성 문제가 없어야합니다.

항목이없는 경우에도 15ms 타이머가 항상 똑딱 거리는 것을 좋아한다면 타이머를 원샷으로 만들고 CheckRelease 메서드가 다음 릴리스 시간으로 다시 초기화되도록 할 수 있습니다 아이템을 dequeing 한 후. 물론 처음 수신 코드를 초기화하거나 대기열에 항목이없는 경우에도 수신 코드를 초기화해야합니다. 타이머 업데이트에 대한 액세스를 동기화하려면 잠금이 필요합니다.

+0

은 타이머의 정확도에 대한 제한점에 대해 흥미로운 점이지만 타이머를 만드는 데 소요되는 오버 헤드에는 의미가 있습니다. 당신의 대답은 많은 의미를 갖습니다. 그것이 어떻게 수행되는지 볼 수 있습니다. 감사. – House

+0

'TimeSpan.FromSeconds (1.0);이 변수가 동적 인 경우, 항목을 큐에서 빼낸 후에 새 값으로 다시 초기화해야합니다 (위 단락에서 말한 것처럼). 감사. – House

관련 문제