c# - mensaje - enviar archivos por sockets java
Enviar/recibir archivo a través de TCP (1)
Posible duplicado:
TcpClient envía datos y recibe datos a través de la red
Bucle hasta que la respuesta de TcpClient sea completamente leída
Estoy tratando de enviar un archivo de un servidor a un cliente a través de TCP.
Código del lado del servidor, enviando archivo:
NetworkStream netStream = client.GetStream();
FileStream fs = new FileStream("usb.exe",FileMode.Open, FileAccess.Read);
byte[] data = new byte[fs.Length];
fs.Read(data,0, data.Length);
fs.Flush();
fs.Close();
netStream.Write(data, 0, data.Length);
netStream.Flush();
Código del lado del cliente, recibir archivo:
FileStream str = new FileStream("usb.exe", FileMode.Create, FileAccess.Write);
byte[] data = new byte[1024];
while ((dataCitit = netStream.Read(data,0, data.Length)) > 0)
{
Thread.Sleep(25);
Application.DoEvents();
str.Write(data, 0, dataCitit);
totalbytes += dataCitit;
}
str.Close();
¿Puede alguien señalar dónde estoy equivocándome?
El archivo tiene 1036 kb, y envía solo 1032 kb y luego se atasca, no saldrá del bucle while del lado del cliente.
Además, si cierro el servidor y lo abro realmente rápido, envía los últimos bytes y los archivos se envían por completo. (este archivo se abre perfectamente)
Creo que es un problema en el lado del servidor no enviar todos los bytes, sino por qué y dónde ...
Bueno, este es un problema en su código del lado del servidor para comenzar:
fs.Read(data,0, data.Length);
Estás ignorando el valor devuelto por Read
. Nunca hagas eso Con FileStream
posiblemente estés bien, pero personalmente no confiaría en él de todos modos. Si usa .NET 4, no necesita hacer esto de todos modos, solo use Stream.CopyTo
.
En el código del lado del cliente, su mayor problema inicial es que está haciendo todo esto en el hilo de la interfaz de usuario. Esa es una idea terrible: la IU se congelará si hay una falla en la red, ya que la llamada de Read
está bloqueando.
De nuevo, solo use Stream.CopyTo
, pero hágalo en un hilo de fondo.
Además, en todos estos casos, use una instrucción de using
para las transmisiones, para que las cierre de forma clara pase lo que pase.
Eso es solo higiene general . Ahora, en cuanto a por qué estás colgando ...
... no estás cerrando la transmisión de red en el lado del servidor. Por lo tanto, nunca llega al final de la secuencia en el lado del cliente. Si solo necesita usar la conexión para un solo archivo, la respuesta es simple: simplemente cierre la conexión en el lado del servidor.
Sin embargo, si necesita usar la misma conexión para múltiples archivos, entonces necesita más protocolo; necesita alguna forma de indicar el final de los datos. Hay tres formas comunes de hacerlo:
- Escriba la longitud de los datos antes de los datos, luego en el lado de lectura, primero lea la longitud, luego lea tantos bytes, fallando si la secuencia finaliza antes de que lo haya hecho. Esto requiere que sepa cuántos datos va a escribir antes de comenzar a escribir.
- Use un marcador de "fin de datos" que puede detectar en el lado de lectura; esto es un dolor en general, ya que requiere escaparse del marcador si aparece en el texto mismo.
- Una variación en el primer enfoque, donde se escribe un fragmento con prefijo de longitud a la vez, luego un fragmento de longitud cero para indicar "fin de los datos". Esto es bastante flexible, pero obviamente un poco más trabajo que el primer enfoque si el primer enfoque realmente funciona para usted.