C# read binary data from socket
I'm working on an application that reads and writes binary data from and to a socket. So first I create a socket with TcpClient. But I'm stuck on reading the data from the socket. Are there any code samples on how to rea开发者_如何学JAVAd binary data from the socket?
Concrete, there are 2 things I don't understand. First, how do I know if a message is "received"? Do I need to create some kind of loop for this? And second: what is the best way to read this data, since the data I receive is binary and not just an ordinary string.
Thanks
The TCPClient documentation from Microsoft is actually pretty useful.
How do read the data from the TCPClient
The key part in the Microsoft example for reading the data from the socket is this:
// Get the stream
NetworkStream stream = client.GetStream();
Byte[] data = new Byte[256];
// String to store the response ASCII representation.
String responseData = String.Empty;
// Read the first batch of the TcpServer response bytes.
int bytes = stream.Read(data, 0, data.Length);
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
They use the GetStream method of the TCPClient class and read all the available data (up to 256 bytes) from the stream.
This is slightly cheating though, as they are just receiving one lot of data and assuming it is a complete and correct message. It will work fine so long as your client is 100% predicable in that it always sends the same thing then disconnects.
Better way of handling this below...
How do you know if a message is received?
You don't, you just keep receiving data until there is no more then check what you have received (or check as you go).
To do this, you have to design the message to include some way of telling the length (integer at the start indicating length), or have some end of message marker (e.g. carriage return) or have a fixed length message.
For example your message specification might be like this:
DATA hello friend
END
By looking for END followed by a carriage return you will know you have found the end of the message. Likewise the DATA
marker at the beginning helps you to tell where a message starts and split out the message data.
What is the best way to read this data?
All data sent/received will be in binary, you need to Encode and Decode the data. In the example, they are converting binary data to string (and the other way round) using the built in ASCII Encoding class GetString and GetBytes methods.
Consider implementing a known protocol
I would recommend to (where possible) use an established protocol rather than just sending plain text over TCP. There are standards for almost anything and anyone connecting to your application will find it easier to follow a known and defined standard.
There are also many pre-built libraries for commonly used protocols saving you and your clients the hastle.
In this instance I will defer to the MSDN. Specifically, working with TcpClients (maintaining a connection - which you are doing already), TcpListeners (accepting connections and beginning to communicate) as well as serialization (converting the data to/from binary).
All data sent over a socket is binary. It's up to you to interpret it as something else, for instance a string. You can use functions like these to send or receive data. You can call them with a NetworkStream that you get from your NetworkStream stream = client.GetStream();
. Note that these functions send an int with the size of the data first.
public void send(NetworkStream stream, byte[] buf) {
stream.Write(BitConverter.GetBytes(buf.Length), 0, 4);
stream.Write(buf, 0, buf.Length);
}
public byte[] receive(NetworkStream stream) {
byte[] lengthBytes = new byte[4];
int read = stream.Read(lengthBytes, 0, 4);
// read contains the number of read bytes, so we can check it if we want
int length = BitConverter.GetInt32(lengthBytes);
byte[] buf = new byte[length];
stream.Read(buf, 0, buf.length);
return buf;
}
The first step is to call GetStream on the TcpClient instance, which gives you a reference to the NetworkStream with which you send and receive binary data. You can wrap that in a BinaryReader and BinaryWriter to send and receive .NET primitives (like Int32s, Strings et cetera) or use the NetworkStream methods directly for byte arrays. You will find the NetworkStream.Read, NetworkStream.BeginRead and NetworkStream.DataAvailable members useful; see http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream_members.aspx for more info.
精彩评论