J'ai une application que j'ai écrite pour mon application distribuée dans toute l'entreprise pour m'envoyer des données via notre serveur Windows 2003 (exécutant IIS 6.0). Les petits messages textuels passent, mais les messages plus volumineux contenant plus de données (environ 20 Ko) ne passent pas.TCP Client Connection
Je définis le tampon d'octets sur la taille du tampon du client TCP. J'ai remarqué que mes données étaient reçues sur le serveur; cependant, il a seulement bouclé la routine de réception une fois, et mes gros fichiers ont toujours exactement la taille de la taille du tampon, soit 8 Ko sur notre serveur. En d'autres termes, mon code ne fait que passer une boucle avant que le serveur ne ferme la connexion socket. En pensant qu'il pourrait y avoir un problème avec le remplissage de la mémoire tampon, j'ai essayé de limiter mes lectures/écritures à seulement 1 Ko, mais cela a eu pour résultat que notre serveur ferme le socket après avoir reçu 1 Ko avant de fermer la connexion.
Je renvoie le message d'erreur du serveur au client pour que je puisse l'afficher. Le message d'erreur spécifique que je reçois du client:
“Unable to write data to the transport connection: An established connection was aborted by the software in your host machine.”
Je mis à jour mon application serveur afin que le socket TCP sous-jacente utiliserait « garder alive » avec cette ligne:
client.Client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, true);
Maintenant, chaque fois que je tente d'envoyer un message, le client reçoit l'erreur:
“Unable to write data to the transport connection: An existing connection was forcibly closed by the remote host.”
administrateur notre réseau m'a dit qu'il ne dispose pas d'un pare-feu ou des ports bloqués sur notre serveur interne. En recherchant les erreurs, j'ai trouvé des messages suggérant que les gens essayent de se connecter au serveur par telnet. Je leur direction telnet sur le serveur, mais je ne suis pas sûr que faire de la réponse:
C:> telnet Welcome to Microsoft Telnet Client
Escape Character is ‘CTRL+]’
Microsoft Telnet> open cpapp 500 Connecting To cpapp…
C'est tout ce que je reçois. Je ne reçois jamais une erreur, et l'écran Telnet de Microsoft finira par changer à "Appuyez sur n'importe quelle touche pour continuer ..." - Je suppose que cela expire, mais mon code est en quelque sorte capable de se connecter. J'ai essayé d'autres ports dans le code et via Telnet y compris 25, 80 et 8080. Telnet envoie le port 25, mais mon application semble lire la première boucle quel que soit le port que je lui dis de lancer.
Voici mon code qui fonctionne sur les clients:
int sendUsingTcp(string location) {
string result = string.Empty;
try {
using (FileStream fs = new FileStream(location, FileMode.Open, FileAccess.Read)) {
using (TcpClient client = new TcpClient(GetHostIP, CpAppDatabase.ServerPortNumber)) {
byte[] riteBuf = new byte[client.SendBufferSize];
byte[] readBuf = new byte[client.ReceiveBufferSize];
using (NetworkStream ns = client.GetStream()) {
if ((ns.CanRead == true) && (ns.CanWrite == true)) {
int len;
string AOK = string.Empty;
do {
len = fs.Read(riteBuf, 0, riteBuf.Length);
ns.Write(riteBuf, 0, len);
int nsRsvp = ns.Read(readBuf, 0, readBuf.Length);
AOK = Encoding.ASCII.GetString(readBuf, 0, nsRsvp);
} while ((len == riteBuf.Length) && (-1 < AOK.IndexOf("AOK")));
result = AOK;
return 1;
}
return 0;
}
}
}
} catch (Exception err) {
Logger.LogError("Send()", err);
MessageBox.Show(err.Message, "Message Failed", MessageBoxButtons.OK, MessageBoxIcon.Hand, 0);
return -1;
}
}
Voici mon code qui fonctionne sur le serveur:
SvrForm.Server = new TcpListener(IPAddress.Any, CpAppDatabase.ServerPortNumber);
void Worker_Engine(object sender, DoWorkEventArgs e) {
BackgroundWorker worker = sender as BackgroundWorker;
string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Application.CompanyName);
if (Directory.Exists(path) == false) Directory.CreateDirectory(path);
Thread.Sleep(0);
string eMsg = string.Empty;
try {
SvrForm.Server.Start();
do {
using (TcpClient client = SvrForm.Server.AcceptTcpClient()) { // waits until data is avaiable
if (worker.CancellationPending == true) return;
client.Client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, true);
string location = Path.Combine(path, string.Format("Acp{0:yyyyMMddHHmmssff}.bin", DateTime.Now));
byte[] buf = new byte[client.ReceiveBufferSize];
try {
using (NetworkStream ns = client.GetStream()) {
if ((ns.CanRead == true) && (ns.CanWrite == true)) {
try {
int len;
byte[] AOK = Encoding.ASCII.GetBytes("AOK");
using (FileStream fs = new FileStream(location, FileMode.Create, FileAccess.Write)) {
do {
len = ns.Read(buf, 0, client.ReceiveBufferSize);
fs.Write(buf, 0, len);
ns.Write(AOK, 0, AOK.Length);
} while ((0 < len) && (ns.DataAvailable == true));
}
byte[] okBuf = Encoding.ASCII.GetBytes("Message Received on Server");
ns.Write(okBuf, 0, okBuf.Length);
} catch (Exception err) {
Global.LogError("ServerForm.cs - Worker_Engine(DoWorkEvent)", err);
byte[] errBuf = Encoding.ASCII.GetBytes(err.Message);
ns.Write(errBuf, 0, errBuf.Length);
}
}
}
}
worker.ReportProgress(1, location);
}
} while (worker.CancellationPending == false);
} catch (SocketException) {
// See MSDN: Windows Sockets V2 API Error Code Documentation for detailed description of error code
e.Cancel = true;
} catch (Exception err) {
eMsg = "Worker General Error:\r\n" + err.Message;
e.Cancel = true;
e.Result = err;
} finally {
SvrForm.Server.Stop();
}
}
Pourquoi pas ma demande continuer à lire à partir du TCP Client ? Ai-je négligé de mettre quelque chose qui dit au Socket de rester ouvert jusqu'à ce que j'aie fini? Le code serveur ne voit jamais une exception car le client TCP n'est jamais arrêté, donc je sais qu'il n'y a pas d'erreur. Notre administrateur réseau n'a pas encore reçu son diplôme d'associé, donc s'il s'avère que ce soit un problème avec le serveur, veuillez le décrire dans votre description de la façon de le résoudre, car nous pourrions ne pas comprendre ce que vous dites . Je m'excuse d'être si long, mais je veux m'assurer que les gens savent ce que je fais - et peut-être même éclaircir certaines informations de ma technique!
Merci de votre aide! ~ Joe
Sans blague? Je suppose que cela a du sens maintenant. J'ai continué à penser que quelque chose devait être installé sur le serveur. Cela aide un * lot *! Je vous remercie! – jp2code
comment ferais-je cela? "précéder le contenu envoyé avec la longueur de ce contenu" je n'ai pas la longueur du contenu envoyé? –
Si vous ne connaissez pas la longueur, alors évidemment vous n'envoyez pas la longueur sur le fil. – Amy