2016-03-25 4 views
0

Situation

Nous utilisons le code suivant pour accepter les requêtes HTTP entrantes.Combien de temps devrions-nous attendre pour vérifier les données disponibles après avoir accepté une connexion?

var localEndPoint = new IPEndPoint(IPAddress.Any, Port); 

var serverSocket = new Socket(
    AddressFamily.InterNetwork, 
    SocketType.Stream, 
    ProtocolType.Tcp); 

serverSocket.Bind(localEndPoint); 
serverSocket.Listen(backlog: 25); 

while (true) 
{ 
    using (var clientSocket = serverSocket.Accept()) 
    { 
     if (clientSocket.Available > 0) 
     { 
      var builder = new StringBuilder(); 

      while (clientSocket.Available > 0) 
      { 
       var currentBytes = new byte[clientSocket.Available]; 
       var bytesReceived = clientSocket.Receive(currentBytes); 

       var currentBytesString = 
        new string(Encoding.UTF8.GetChars(currentBytes)); 

       builder.Append(currentBytesString); 
      } 
     } 
    } 
} 

Problème

Parfois clientSocket.Available est égal à zéro, même si la connexion de données. La solution que nous avons implémentée consiste à attendre après avoir accepté la connexion avant de vérifier si les données sont disponibles. Nous le faisons comme ceci:

var start = DateTime.Now; 
var duration = new TimeSpan(0); 
while (clientSocket.Available <= 0 || duration.Milliseconds < 1000) 
{ 
    duration = DateTime.Now - start; 
    Thread.Sleep(100); 
} 

Question

Après avoir accepté une connexion, combien de temps nous devons nous attendre avant que les données de la connexion seront disponibles dans la prise?

Solution de travail

Merci à SZYM pour l'inspiration pour cette approche. Cela fonctionne pour le moment.

while (true) 
{ 
    using (var clientSocket = serverSocket.Accept()) 
    { 
     var builder = new StringBuilder(); 

     do 
     { 
      var currentBytes = new byte[50]; 
      var bytesReceived = clientSocket.Receive(currentBytes); 

      var currentBytesString = 
       new string(Encoding.UTF8.GetChars(currentBytes)); 

      builder.Append(currentBytesString); 
     } 
     while (clientSocket.Available > 0); 
    } 
} 
+1

Pourquoi ne pas simplement appeler Read et le laisser bloquer jusqu'à ce que des données soient disponibles? –

+0

Je ne sais pas. Qu'est-ce qui est disponible pour dans ce cas? –

Répondre

1

En général, vous devrez peut-être attendre un certain temps (pensez réseaux merdiques avec d'énormes temps aller-retour), le délai d'attente par défaut sur certaines plates-formes est de 20 secondes!

Toutefois, l'approche de vérification Available dans une sleepy-loop est l'interrogation et est une perte de CPU. Vous devez soit bloquer sur Receive qui attendra simplement l'arrivée des données (peut-être générer un thread si vous devez gérer plusieurs connexions), ou utiliser une approche non bloquante.

Pour citer le documentation (Souligné par l'auteur): Si vous utilisez un non-bloquant Socket

, disponible est un bon moyen de déterminer si les données sont mis en attente pour la lecture, avant d'appeler recevoir. Les données disponibles correspondent à la quantité totale de données mises en file d'attente dans le tampon réseau pour la lecture. Si aucune donnée n'est mise en file d'attente dans le tampon réseau, Retours disponibles 0.

+0

Où est cette méthode 'Read' dont vous parlez? –

+0

Les docs ne répertorient pas une telle méthode. https://msdn.microsoft.com/en-us/library/system.net.sockets.socket%28v=vs.110%29.aspx –

+1

Désolé, mis à jour avec 'Receive' qui est le nom dans les sockets .NET. – szym