questions patterns net mvc exam developing asp applying applications and c# sockets

c# - patterns - developing asp.net mvc web applications



C#streaming sockets, cómo separar mensajes? (6)

Un título un poco largo, pero de todos modos ...

He estado viendo estos ejemplos, específicamente en las partes sobre cómo escribir y leer el tamaño del mensaje en las secuencias de bytes
http://doc.trolltech.com/4.4/network-fortuneclient-client-cpp.html
http://doc.trolltech.com/4.4/network-fortuneserver-server-cpp.html

Pero no puedo entenderlo en C #.

StreamWriter writer = new StreamWriter(tcpClient.GetStream()); writer.Write(data.Length + data);

Esto no funciona muy bien en absoluto. ¿Podría alguien darme un empujón en la dirección correcta?


Cuando dices: "Esto no funciona del todo bien", me gustaría saber qué es lo que no funciona. ¿Son aplicaciones .NET en ambos extremos del socket? Si es así, ignora esta respuesta. Si no, ¿podría el problema ser el ordenamiento de bytes del número entero? ¿Un pequeño problema endian vs big endian? Este hilo aquí lo discute:

http://bytes.com/forum/thread225649.html

http://books.google.es/books?id=2zT5b2BS1OUC&pg=PA64&lpg=PA64&dq=c%23+sockets+integers+byte+ordering&source=web&ots=_ISzZZ6HHT&sig=tUHdNT0NGv0uxusmHG9YjFw6j9k&hl=en&sa=X&oi=book_result&resnum=2&ct=result

Otro problema si ambos extremos no son .NET podría ser que el otro extremo espera cadenas ANSI mientras que usted está enviando Unicode.


En general, enviarías la longitud primero. Ambos extremos deben coincidir en el aspecto de una longitud, por ejemplo, puede que te guste utilizar el prefijo fijo de 4 bytes como binario:

byte[] data = ... int len = data.Length; byte[] prefix = Bitconverter.GetBytes(len); stream.Write(prefix, 0, prefix.Length); // fixed 4 bytes stream.Write(data, 0, data.Length);

Obviamente, quien llama debe hacer lo mismo, es decir, leer los primeros 4 bytes para obtener la longitud. Para leer, el receptor debe tener cuidado de no leer demasiados datos. Una forma es con un flujo limitante, por ejemplo, esta clase se puede usar para obtener un flujo que no se leerá demasiado.

Si no desea que la sobrecarga de enviar siempre 4 bytes, algunas codificaciones más interesantes son posibles, por ejemplo, utilizando el msb como un bloque de continuación.

Para obtener información, protobuf-net es un serializador binario diseñado en torno al formato basado en mensajes de "búferes de protocolo" de Google. Maneja muchos detalles para usted, y puede ser de interés si no quiere perder mucho tiempo escribiendo código de serialización. Hay ejemplos de sockets en el proyecto QuickStart, por ejemplo aquí


En lugar de data.Length , intente:

writer.Write(chr(data.Length) + data);

Esto prefigurará cada bloque de datos con un byte que indica su longitud (hasta 255 bytes de longitud). Como lo solicitó, esto es solo un empujoncito. :)

Actualización: Acabo de recordar que C # es todo Unicode y demás, por lo que chr () probablemente te dé más de un byte. Ajustar para encajar.


Supongo que esto debería hacer eso: (supongo que tus datos son una cadena)

Stream stream = tcpClient.GetStream(); Encoding encoding = Encoding.GetEncoding("encoding name"); byte[] bytes = encoding.getBytes(data); stream.Write(BitConverter.GetBytes((short)bytes.Length),0,2); // hope data isn''t longer that 64k stream.Write(bytes,0,bytes.Length);


También podría, si desea conservar la claridad, especificar un tamaño máximo específico y rellenar el número mediante una cadena. Formato. (Digamos por ejemplo solo permitir 4 caracteres en la longitud) Esto evita los problemas de números en el flujo de datos útil, y también simplifica la decodificación.

Una solución final de texto claro es poner un carácter específico entre longitud y datos, como -, luego tomar caracteres individuales a la vez hasta que toques un menos, decodificar la cadena recuperada (Ignorando el menos del curso) y luego usar eso para determinar el longitud de la cadena restante, y su código de salida que simplemente necesita ser cambiado para agregar ese carácter en el medio.


Use WriteLine en lugar de Write, ReadLine en lugar de Read ...

Si está hablando enviando mensajes textuales puros, agregue el carácter Newline al final de sus mensajes. Luego, lea los bytes hasta que encuentre este carácter Newline y convierta los bytes en una cadena. Para su comodidad, cualquier System.IO.StreamReader y System.IO.StreamReader implementan este comportamiento en un único método (WriterLine o ReadLine) writer.WriteLine ("Line to send"); string lineSent = reader.ReadLine ();