문제

C#에서 TcpClient 클래스를 사용하고 있습니다.

새로운 TCP 연결 요청이 있을 때마다 이를 처리할 새 스레드를 생성하는 것이 일반적인 방법입니다.그리고 메인 스레드는 언제든지 이러한 핸들러 스레드를 종료할 수 있어야 합니다.

이러한 각 처리기 스레드에 대한 내 솔루션은 다음과 같습니다.

1 Check NetworkStream's DataAvailable method
    1.1 If new data available then read and process new data
    1.2 If end of stream then self terminate
2 Check for terminate signal from main thread
    2.1 If terminate signal activated then self terminate
3 Goto 1.

이 폴링 접근 방식의 문제점은 이러한 모든 처리기 스레드가 상당한 프로세서 리소스를 차지한다는 것입니다. 특히 이러한 스레드 수가 엄청나게 많은 경우에는 더욱 그렇습니다.이로 인해 매우 비효율적입니다.

이 작업을 수행하는 더 좋은 방법이 있나요?

도움이 되었습니까?

해결책

보다 비동기 서버 소켓 예제 각 요청에 대한 새 스레드를 작성하지 않고이 작업을 수행하는 방법을 배우기 위해.

다른 팁

믿거 나 말거나 1000 개의 진드기 수면이 실제로 일을 매끄럽게 유지할 것입니다.

private readonly Queue<Socket> sockets = new Queue<Socket>();
private readonly object locker = new object();
private readonly TimeSpan sleepTimeSpan = new TimeSpan(1000);
private volatile Boolean terminate;

private void HandleRequests() 
{
    Socket socket = null;

    while (!terminate)
    {
        lock (locker)
        {
            socket = null;
            if (sockets.Count > 0)
            {
                socket = sockets.Dequeue();
            }
        }

        if (socket != null)
        {
            // process
        }

        Thread.Sleep(sleepTimeSpan);
    }   
}

비슷한 종류의 Windows 서비스에서 작업하는 것을 기억합니다. 약 1000 개의 TCP 연결을 사용하여 데이터를 NTRIP 캐스터로 전환 할 수있는 NTRIP 서버였습니다.

이 애플리케이션에 대한 전용 서버가있는 경우 각 스레드에 더 많은 코드를 추가하지 않으면 문제가되지 않습니다 (파일 IO, 데이터베이스 등 - 내 경우에는 각 연결에 대한 IN/OUT을 로그인하기 위해 데이터베이스 처리가 있었지만) .

조심해야 할 사항 :

  1. 스레드가 600 정도까지 올라갈 때 대역폭. TCP 버퍼 창이 어떤 이유로 질식되거나 사용 가능한 대역폭이 부족할 때 연결 끊김을보기 시작합니다.
  2. 이 애플리케이션을 실행하는 운영 체제에는 일부 제한이있을 수 있으며, 이로 인해 연결이 끊김이 발생할 수 있습니다.

위의 것은 귀하의 경우에 적용되지 않을 수도 있지만 개발 중에 직면했기 때문에 여기에 넣기를 원했습니다.

모든 스레드가 "바쁨 대기"(예:작은 루프를 계속해서 실행합니다.)차단을 원하거나 비동기 I/O를 사용하려고 합니다.

John Saunders가 언급했듯이 비동기 I/O는 수백 개의 연결까지 확장할 수 있으므로 이를 수행하는 "올바른 방법"입니다.기본적으로 BeginRead()를 호출하고 콜백 함수를 전달합니다.BeginRead()는 즉시 반환하고, 데이터가 도착하면 스레드 풀의 스레드에서 콜백 함수가 호출됩니다.콜백 함수는 데이터를 처리하고 BeginRead()를 다시 호출한 다음 반환되어 스레드를 다시 풀로 해제합니다.

그러나 한 번에 소수의 연결만 열어 두는 경우에는 각 연결에 대해 스레드를 만드는 것이 좋습니다.루프에서 DataAvailable 속성을 확인하는 대신 Read()를 호출하세요.스레드는 데이터를 읽을 수 있을 때까지 CPU를 사용하지 않고 차단됩니다.연결이 끊어지거나 다른 스레드에서 연결을 닫으면 Read() 호출에서 예외가 발생하며, 이는 리더 스레드를 종료하여 처리할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top