C# Pourquoi ne pas “Vider” force les octets vers le bas le flux réseau?
J'ai un projet où je suis en train d'envoyer un objet sérialisé pour le serveur, puis d'attendre pour un "OK" ou "ERREUR" message de revenir.
Je semble avoir un problème similaire à l'affiche de : TcpClient envoyer/fermer problème
Le problème est que la seule façon qui me semblent être en mesure d'envoyer l'objet d'origine est de fermer la connexion, mais alors, évidemment, je ne peux pas attendre pour voir si l'objet a été traité avec succès par le serveur.
private void button4_Click(object sender, EventArgs e)
{
RequestPacket req = new RequestPacket();
///... Fill out request packet ...
///Connect to the SERVER to send the message...
TcpClient Client = new TcpClient("localhost", 10287);
using (NetworkStream ns = Client.GetStream())
{
XmlSerializer xml = new XmlSerializer(typeof(RequestPacket));
xml.Serialize(ns, req);
///NOTE: This doesn't seem to do anything....
/// The server doesn't get the object I just serialized.
/// However, if I use ns.Close() it does...
/// but then I can't get the response.
ns.Flush();
//Get the response. It should be "OK".
ResponsePacket resp;
XmlSerializer xml2 = new XmlSerializer(typeof(ResponsePacket));
resp = (ResponsePacket)xml2.Deserialize(ns);
///... EVALUATE RESPONSE ...
}
Client.Close()
}
Mise à JOUR: En réponse à un commentaire, je ne pense pas que le client peut être en faute. Il est tout simplement en attente pour l'objet, et l'objet ne vient jamais jusqu'à ce que je ferme la socket.... cependant, si je me trompe, je serai heureux de manger crow publiquement. =) Voici le client:
static void Main(string[] args)
{
//Read the port from the command line, use 10287 for default
CMD cmd = new CMD(args);
int port = 10287;
if (cmd.ContainsKey("p")) port = Convert.ToInt32(cmd["p"]);
TcpListener l = new TcpListener(port);
l.Start();
while (true)
{
//Wait for a socket connection.
TcpClient c = l.AcceptTcpClient();
Thread T = new Thread(ProcessSocket);
T.Start(c);
}
}
static void ProcessSocket(object c)
{
TcpClient C = (TcpClient)c;
try
{
RequestPacket rp;
////Handle the request here.
using (NetworkStream ns = C.GetStream())
{
XmlSerializer xml = new XmlSerializer(typeof(RequestPacket));
rp = (RequestPacket)xml.Deserialize(ns);
}
ProcessPacket(rp);
}
catch
{
//not much to do except ignore it and go on.
}
}
Ouais.... c'est aussi simple que cela.
Le ProcessPacket ligne n'est jamais atteint. J'ai un point d'arrêt.
avez-vous essayé d'utiliser
C.GetStream().Read()
à la place? Avez-vous essayé de vous connecter à l'exception que vous avez ne obtenir? Lire sur les flux orienté vs message oriented protocoles de transmission et vous allez voir pourquoi.A) je ne suis pas une exception. Je ne suis pas d'obtenir quoi que ce soit. B) Comment est C. GetStream().Read() différent de ce que je suis en train de faire? C) j'ai cassé c'est à cause de ça éléments de base (Lire(byteBuffer), Écrire(byteBuffer), WriteLine(byteBuffer)...) en vain.
Avez-vous essayé de faire une capture WireShark pour voir exactement quand les octets envoyés sur le réseau (ce qui nécessiterait exécutant le client sur une machine et le serveur sur un autre)? Il se peut que les données sont physiquement envoyé, mais que le cours d'eau récepteur est mise en mémoire tampon des données et de ne pas le relâcher jusqu'à ce que la connexion est interrompue par l'auteur.
OriginalL'auteur Jerry | 2011-02-15
Vous devez vous connecter pour publier un commentaire.
Uh oh, vous pouvez le blâme L'algorithme Nagle. Il n'a rien à voir avec le C#, c'est un comportement par défaut de la pile TCP/IP. Activer NoDelay option de socket à l'aide de SetSocketOption méthode. Mais attention, la désactivation de l'algorithme Nagle révise à la baisse le débit.
Je ne suis pas sûr que le flux que vous utilisez sur le dessus de la douille, comme je ne suis pas un développeur C#, mais essayez de supprimer une instance de sorte qu'il ne fait qu'écrire pour vous 🙂
J'ai couru dans presque la même question lors de la communication avec d'automatisation industrielle, de l'équipement, et le réglage de la
NoDelay
bien fonctionné pour moi, bien que je n'étais pas à l'aide de laGetStream
méthode.Avez-vous été capable de faire une communication à deux voies aller et retour sur le même flux?? Je ne suis pas en mesure de le faire, même avec le NoDelay option.
L'algorithme Nagle ne pas retarder les paquets jusqu'à ce que le socket est fermé. Le délai maximum est d'environ 200 millisecondes. Ce n'était pas suffisant pour rendre compte de cette question.
OriginalL'auteur
La version courte est apparemment, lors de l'utilisation de XmlSerializer (ou tout autre gros blob) pour pousser données NetworkStream, il sera tout simplement tenir la ligne ouverte indéfiniment en attente pour plus d'informations écrites. Il ne bouffées de la connexion une fois que vous le fermez. Cela crée une situation où cette méthode est idéal pour l'envoi, mais pas de réception. Ou vice-versa. Il devient un moyen de communication, et inutile pour la suite de va-et-vient de la communication sur la même connexion.
C'est le genre de merde que j'ai eu à travailler autour de quelque chose qui semble si élégante sur la surface, mais de revenir à mon ancien C jours, j'ai eu recours à l'envoi d'un "nombre d'octets" paquets d'abord, puis les effectifs des paquets. Cela me permet de LIRE à l'autre extrémité, le nombre exact d'octets donc je n'ai jamais pris dans une situation de blocage.
À simplifier ma vie, j'ai créé une classe qui détient quelques méthodes statiques pour l'envoi et de la réception. Cette classe permet d'envoyer un XML-classe sérialisable sur le réseau, donc c'est ce que j'en ai besoin pour le faire.
Si quelqu'un a une solution plus élégante, je serais à l'écoute.
L'utilisation de cette classe, j'ai tout simplement besoin d'appeler
PacketTransit.SendPacket(myTcpClient, SomePacket)
pour envoyer toute donnée XML-objet Sérialisable. Je peux alors utiliserPacketTransit.GetResponsePacket
ouPacketTransit.GetRequestPacket
de le recevoir à l'autre extrémité.Pour moi, cela fonctionne très bien, mais il était beaucoup plus d'une séance d'entraînement que prévu à l'origine.
OriginalL'auteur Jerry
vous devez utiliser un StreamWriter/Lecteur lié à votre flux réseau, .Flush ne fait rien sur un NetworkStream, voir ici:
http://www.c-sharpcorner.com/UploadFile/dottys/SocketProgDTRP11222005023030AM/SocketProgDTRP.aspx
J'ai essayé aussi bien... toujours pas de la chance. Ce fut ma première pensée.
OriginalL'auteur Davide Piras
Je crois que le vrai problème ici, peut être que le XmlDeserializer ne peut pas revenir jusqu'à ce qu'il a lu EOS à partir du flux. Vous devrez peut-être l'arrêt de l'envoi de flux de sortie à force de ce faire.
OriginalL'auteur user207421