Haute performance serveur TCP en C#
Je suis expérimenté, développeur C#, mais je n'ai pas développé un serveur TCP application de la mesure. Maintenant, je dois développer une solution hautement évolutive et haute performance du serveur qui peut gérer au moins 5 à 10 mille connexions simultanées: arriver -raw - octets de données via GPRS GPS.
Une commune du processus de communication devrait ressembler à ceci:
- GPS de l'appareil établit une connexion à mon serveur
- mon serveur réponses, si je veux obtenir les données
- appareil envoie des données GPS
- mon serveur envoie un rapport à l'appareil à propos de l'obtenir (sg comme la somme de contrôle)
- obtenir de nouvelles données de GPS, reportm et cela arrive encore et encore
- plus tard, le DISPOSITIF de GPS ferme la connexion
Donc, à mon serveur, j'ai besoin de
- trace connecté/clients actifs
- fermer n'importe quel client à partir du serveur de côté
- attraper le cas, lorsqu'un appareil ferme la connexion
- obtenir de l'octet de données
- envoyer des données aux clients
J'ai commencé à lire sur ce sujet sur internet, mais il semble être un cauchemar pour moi. Il y a beaucoup de façons, mais je ne pouvais pas savoir qui est le meilleur.
Async méthodes socket semble le mieux pour moi, mais l'écriture de code dans cet async style est terrible et pas facile à déboguer.
Donc ma question est: qui pensez-vous que la meilleure façon de mettre en œuvre une haute performance serveur TCP en C#? Connaissez-vous une bonne composant open source pour ce faire? (J'en ai essayé plusieurs, mais je ne pouvais pas trouver un bon.)
- Pas sûr que je suis à la compréhension de l'écoulement. Que signifie "mon serveur envoie le rapport à l'appareil sur" veut dire? Aussi, pourquoi avez-vous besoin de garder la connexion ouverte? Pourquoi ne pas simplement ouvrir qu'en cas de besoin?
- Pouvez-vous expliquer pourquoi vous dites "l'écriture de code dans ce async style est terrible et pas facile à déboguer" ?
- Donc, il doit rester ouverte, car ils sont les connexions GPRS et GPS, et lorsqu'ils se connectent - surtout lorsqu'ils sont en itinérance - il coûte de l'argent. Donc, il est tout au sujet de l'argent, plus de connexion = plus de frais. Rapport: le serveur doit envoyer un rapport à l'appareil qu'il obtenir les données. (Ils sont quelques octets) Lorsque le dispositif d'obtenir ce rapport, il peut supprimer des données envoyées à partir de sa mémoire, si ce n'est pas ce rapport, essaie d'envoyer cette poche de nouveau.
- Je suis en train de travailler sur le même projet. (Je pense que vous êtes buildind un système de suivi GPS ou quelque chose de similaire n'est-ce pas?). Je voudrais partager l'expérience avec vous. Il n'y a pas de messagerie Privée sur StackExchange. Pouvez-vous me contacter? Adresse : (mon-pseudo-nom À gmail.com) (rapidement avant que ce post est supprimé :p) je vous Remercie.
Vous devez vous connecter pour publier un commentaire.
Il doit être asynchrone, il n'y a pas moyen de contourner cela. Hautes performances et évolutivité, ne pas mélanger avec un thread par socket. Vous pouvez jeter un oeil à ce StackExchange font eux-mêmes, voir async Redis attendent BookSleeve qui tire profit de la CTP fonctionnalités de la prochaine C# version (donc sur le bord et sujet à des changements, mais c'est cool). Pour encore plus avant-gardistes et les solutions évoluent autour de levier Classe SocketAsyncEventArgs qui prend les choses un peu plus loin en éliminant les allocations de fréquentes de async gestionnaires associés à "classiques" async C# traitement:
Longue histoire courte: apprendre async ou mourir en essayant...
BTW, si vous vous demandez pourquoi asynchrone, puis de lire les trois articles liés à partir de ce post: Les Fenêtres à haut Rendement des programmes. L'ultime réponse est: l'OS sous-jacent de la conception exige.
the default range of ephemeral ports used by *client applications*
. Aussi découvrez cet article technet et de la recherche pour "sortant".Que Remus dit ci-dessus, vous devez utiliser asynchrone pour garder des performances de haut. C'est le début.../Fin... méthodes .NET.
Sous le capot pour les sockets, ces méthodes, l'utilisation de IO Ports de fin qui semble être le plus performant moyen de traitement d'un grand nombre de sockets sur les systèmes d'exploitation Windows.
Comme le dit Jim, la classe TcpClient peut aider ici, et il est assez facile à utiliser. Voici un exemple d'utilisation de la TcpListener pour écouter les connexions entrantes et la TcpClient à gérer, avec les initiales BeginAccept et BeginRead des appels asynchrones.
Cet exemple suppose un message de protocole est utilisé sur les sockets et qui est omis, sauf que les 4 premiers octets de chaque transmission est la longueur, mais qui vous permet d'utiliser une Lecture synchrone sur le stream pour obtenir le reste des données qui sont déjà mises en mémoire tampon.
Voici le code:
Il montre comment gérer les appels asynchrones, mais il aura besoin de la gestion d'erreur en ajoutant à assurez-vous que le TcpListener est toujours d'accepter de nouvelles connexions et plus de la gestion d'erreur lorsque les clients se déconnecter de façon inattendue. Aussi, il semble bien y avoir quelques cas où toutes les données arrivent dans un passe qui aurait besoin de manipulation trop.
Vous pouvez faire cela avec le TcpClient classe, bien qu'à vrai dire je ne sais pas si vous pourriez avoir 10 mille ouvrir des sockets. C'est tout un lot. Mais j'utilise régulièrement
TcpClient
pour gérer des dizaines de connexions simultanées sockets. Et le modèle asynchrone est vraiment très agréable à utiliser.Votre plus gros problème n'est pas de faire de la
TcpClient
travail. Avec 10 mille connexions simultanées, je suis en train de penser de la bande passante et l'évolutivité allez avoir des problèmes. Je ne sais même pas si une machine peut gérer tout ce trafic. Je suppose que cela dépend de la taille des paquets et comment souvent ils vont venir dans. Mais vous feriez mieux de faire plusieurs allers-de-la-estimation de l'enveloppe avant de vous engager à mettre en œuvre tout cela sur un seul ordinateur.Je pense que vous êtes également à la recherche pour les techniques. Pour les 10k de clients, il est rapide, mais le problème est que vous avez à mettre en œuvre Accusé de réception pour chaque message que vous avez reçu le message. En UDP, vous n'avez pas besoin d'ouvrir un socket pour chaque client, mais nécessité de mettre en œuvre battement de coeur/mécanisme de ping après x secondes pour vérifier le client est connecté ou pas.
Vous pouvez utiliser mon TCP CSharpServer j'ai faite, C'est très simple à mettre en œuvre, mettre en Œuvre IClientRequest sur l'une de vos Classes.
BinaryBuffer vous permet de lire les données envoyées au serveur vraiment facile.
L'ensemble de ce Projet est sur GitHub CSharpServer