问题
I am facing a big issue in TCP client application return in c#. Normal case it's working fine but in some case server send simultaneous response to a particular client, so this case all the simultaneous response are received as a single message in client side.So this case client failed to identify individual message. So such a case my client application failed to handle a particular activity. Is it possible to read as individual message in client side ?. So for solving this issue, I have some choices but i don't know if it is correct way.
1- Using a fixed length buffer in client side(But my message are variable length).
2- Add a delimiter to each response message.
If any one know the solution for resolving such problem please help me.
回答1:
TCP is stream based, you get a stream of data from a client to server. You need to "deserialize" what you're expecting from the stream, if you can't build an application protocol that ensures each message sent is separately (which usually isn't a wise idea anyway with TCP).
So, you need to send with each message something that allows you to differentiate what the data is. This is often done with tag or type data at the start of each message. Sometimes a byte will do (depending on how many different message types you have). You then read that byte from the stream and decide what to deserialize next. e.g. if you want to send a string, you might serialize '1', then the string
. If you want to send a date/time, you might serialize '2' then the DateTime
. On the server, if both of those objects got sent about the same time, you could simply deserialize the byte
, and if it was '1', deserialize a string
, then continue deserializing: get the next byte
, and if it's a '2', deserialize a DateTime
.
It's important to remember that TCP is a stream-based protocol, not a message-based protocol. Message-based needs to be implemented at the application level--e.g. something like the above.
And by "serialize" and "deserialize" I mean the typical built-in serializers and deserializers as described in Serializing Objects in the .NET documentation. The same would hold true for JSON serializers included in libraries like JSON.NET or the built-in DataContractJsonSerializer
and JavaScriptSerializer
.
回答2:
Just make sure that each message has its length as first few bytes, this way you can split the whole into single messages.
For example, suppose that you receive this 20 bytes message from your server:
1 2
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| 2 | 4 | 6 | 1 | 5 | 3 | 3 | 2 | 6 | 3 | 4 | 1 | 6 | 2 | 3 | 5 | 3 | 0 | 4 | 6 |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
^ ^ ^ ^ ^ ^
The first byte says that the first message has 2 bytes of data, so you can retrive that message as bytes 1 and 2. Next you read byte 3 which tells you that the second message has only 1 byte of additional data (byte 4). The third and the fourth message have 3 bytes of data (as bytes 5 and 9 indicate), then there's a 2 bytes message and a 3 bytes one.
回答3:
Using a fixed length header which contains at least the body length is the easiest way to go. Then depending on the body you might need additional information (like the type name if you want to use something like JSON to serialize/deserialize the actual message).
If you don't want to take care of everything yourself you could use a networking library like mine. Scroll down to the end of the article to see a JSON RPC sample implementation. You can take most of that to get a JSON based communication channel.
来源:https://stackoverflow.com/questions/12352125/tcp-client-side-issue