Pergunta

Eu estou usando a classe TcpClient em C #.

Cada vez que há uma nova solicitação de conexão TCP, a prática usual é a de criar uma nova thread para lidar com isso. E deve ser possível para o segmento principal de rescindir estes threads para tratamento a qualquer hora.

A minha solução para cada um deles thread handler é a seguinte:

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.

O problema com esta abordagem de pesquisa é que todos esses tópicos manipulador será tendo-se recursos significativos do processador e, especialmente, por isso, se há um grande número destes tópicos. Isto torna altamente ineficiente.

Existe uma maneira melhor de fazer isso?

Foi útil?

Solução

Asynchronous Servidor soquete Exemplo para aprender como fazer isso o "caminho .NET", sem criar novos tópicos para cada solicitação.

Outras dicas

Acredite ou não que 1000 carrapato sono vai realmente manter as coisas funcionando suave.

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);
    }   
}

Lembro-me de trabalhar em um tipo semelhante de serviço do Windows. Foi um NTRIP Server que pode levar cerca de 1000 conexões TCP e encaminhar os dados para um NTRIP Caster.

Se você tem um servidor dedicado para esta aplicação, então não vai ser um problema a menos que você adicionar mais código para cada thread (File IO, banco de dados etc - embora no meu caso eu também tinha processamento de banco de dados para registrar o in / out para cada conexão).

As coisas que atente para:

  1. largura de banda quando os tópicos sobe para 600 ou assim. Você vai começar a ver desconexões quando a janela de buffer TCP é sufocada por algum motivo ou a largura de banda disponível é insuficiente
  2. O sistema operacional no qual você está executando esta aplicação pode ter algumas restrições, que podem causar desconexões

O poder acima não ser aplicável no seu caso, mas eu só queria colocá-lo aqui, porque eu enfrentei em seguida, durante o desenvolvimento.

Você está certo de que você não quer que todos os seus tópicos "ocupado espera" (ou seja, executando um pequeno laço mais e mais). Você quer quer que eles bloqueio, ou você quer usar assíncrono I / O.

Como John Saunders mencionado, E / S assíncrona é o "caminho certo" para fazer isso, uma vez que pode escalar até centenas de conexões. Basicamente, você chama BeginRead () e passá-lo uma função de chamada de retorno. BeginRead () retorna imediatamente, e quando chega de dados, a função de retorno de chamada é invocado em um thread do pool de threads. A função callback processa os dados, chama BeginRead () novamente, e em seguida, retorna, que libera parte de trás linha para dentro da piscina.

No entanto, se você só vai estar segurando um punhado de conexões abertas ao mesmo tempo, é perfeitamente possível criar um thread para cada conexão. Em vez de verificar a propriedade DataAvailable em um loop, vá em frente e chamar Read (). O fio irá bloquear, consumindo sem CPU, até que os dados estão disponíveis para ler. Se a conexão for perdida, ou fechá-lo de outro segmento, o () chamada de leitura irá lançar uma exceção, que você pode manipular terminando seu segmento leitor.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top