0

I implemented a Client and Server model that uses Socket with thread

When I want to pass only a string from Client to the Server, it works. But I want to pass an object and it throws this error: "Attempting to deserialize an empty stream"

Here is the code:


Client:

ASCIIEncoding asen = new ASCIIEncoding();

MemoryStream memoryStream = new MemoryStream();
BinaryFormatter binaryFormatter = new BinaryFormatter();
Command command = new Command("meuLogin", "minhaSenha");
binaryFormatter.Serialize(memoryStream, command);

stream.Write(memoryStream.ToArray(), 0, memoryStream.ToArray().Length);

Server:

byte[] message = new byte[4096];
int bytesRead = 0;
bytesRead = clientStream.Read(message, 0, 4096);

MemoryStream memoryStream = new MemoryStream(bytesRead);
BinaryFormatter bf1 = new BinaryFormatter();
memoryStream.Position = 0;

Command command = (Command)bf1.Deserialize(memoryStream); 

Another question: I copied the class Command from Client and pasted at Server to deserialize. Is this correct?

Thank you

4
  • How is the Command class defined? Refer to codeproject.com/KB/cs/objserial.aspx for guidance. Commented Jun 24, 2010 at 15:31
  • 1
    I agree with Andrey, WCF will make your life a ton easier. Commented Jun 24, 2010 at 15:32
  • Another agreement with @Andrey: WCF will make your life so much easier. Commented Jun 24, 2010 at 15:34
  • I will study this WCF, thanks!! Commented Jun 24, 2010 at 16:21

6 Answers 6

2

I also recommend WCF. But if you continue using sockets, the key element that you're missing in your protocol is message framing.

Sign up to request clarification or add additional context in comments.

1 Comment

I will check the WCF and message framing! Thank you!
2

You never use the message that you read from the stream. The memory stream you are reading from is thus empty.

On a side note, why do you use these intermediate MemoryStreams?

4 Comments

I assume the MemoryStream is used because the object has already been read from the clientStream. @Alan will need to reconsider his protocol design.
well, i was going to use after this line: Command command = (Command)bf1.Deserialize(memoryStream); but the problem occurs in this line
@Alan, how do you want to deserialize an object from an empty stream??? The memory stream is empty when you run this line.
The server has a more serious problem though, as there's nothing to distinguish/check whether his clientStream.Read(..) call read 1 or 2, or e.g. 2 and a half objects.
1

To answer your second question: for maximum maintainability, the class Command should be in a separate assembly that both Client and Server reference.

To answer your first question: you are attempting to deserialize from an empty stream on your server, just as the exception tells you. You need to copy the bytes you read from the clientStream into the memoryStream before you deserialize from the memoryStream. Alternatively, use the clientStream directly rather than using the memoryStream; this may require reconsidering your protocol.

Finally, I wholeheartedly agree with @Andrey: consider using WCF. It's way way way better than raw sockets.

1 Comment

i will see this WCF thanks! but I didn't understand what you mean about the first question.. the client send the bytes to the server and then the server read it. When I debug at Server, the bytes were 381 or something. If I didn't understand you, please show me some pseudo-code. Thank you
0

If you change your server code to use a different MemoryStream constructor, the problem will go away.

MemoryStream memoryStream = new MemoryStream(message, 0, bytesRead);

However, I agree with Stephen and others. Either use WCF, or use Message framing.

1 Comment

Not sure this is actually true. Tried this against a Pex suite and Pex still threw the exception when tracing regardless of the constructor used.
0

Another question: I copied the class Command from Client and pasted at Server to deserialize. Is this correct?

No. The namespace for your Client and Server are likely different, so the Server will be trying to deserialize a stream that matches its namespace.

You should create your Command Class using its own namespace and reference that from both your Client and the Server.

After that...

Client:

static void StreamToServer(TcpClient client, Command obj) {
  using (NetworkStream ns = client.GetStream()) {
    using (MemoryStream ms = new MemoryStream()) {
      BinaryFormatter formatter = new BinaryFormatter();
      formatter.Serialize(ms, obj);
      byte[] buf = ms.ToArray();
      ns.Write(buf, 0, buf.Length);
    }
  }
}

Server:

static Command ReadStream(TcpListener listener) {
  Command obj = null;
  using (TcpClient client = listener.AcceptTcpClient()) { // waits for data
    using (NetworkStream ns = client.GetStream()) {
      byte[] buf = new byte[client.ReceiveBufferSize];
      int len = ns.Read(buf, 0, buf.Length);
      using (MemoryStream ms = new MemoryStream(buf, 0, len)) {
        BinaryFormatter formatter = new BinaryFormatter();
        obj = formatter.Deserialize(ms) as Command;
      }
    }
  }
  return obj;
}

WCF or Message framing may be easier, but I don't often have the opportunity at work to sit around and read a book.

Comments

0

Instead of passing bytesRead to the MemoryStream which is actually the length of the byte stream, you should pass 'message', as it is the actual stream of bytes. Like,

MemoryStream memoryStream = new MemoryStream(message);

As you are passing an integer variable, the compiler is throwing exception that the stream is empty.

As for WCF, it is remarkable framework, but for applications that require low latency and high performance, WCF is a horrible answer because of its overheads, it is built upon sockets. So if you use sockets, that will be the lowest level implementation and thus, the fastest. That depends on your application which paradigm you should choose...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.