Check Out Dave's New game for iPhone and iPod Touch: Smiled Out!

Chat Client/Server Part 3: The Connection Class

Pages: 1 2 3

Sending Data

Now for the fun code! We know how to open a connection. Just instantiate a Connection object and tell it what server and port to connect to.

But how do we send data using our connection? That is the purpose of the next function: SendData. Isn’t that a good, original name?

Lets implement this function in pieces, so I can explain each piece as we go along.

Step 5: Add the following function SendData.

1
2
        public void SendData(Packet p)
        {

First things first. All data that is sent over the network should be defined through the Packet class, or any derivative class. Do you see now why in Part 1 and Part 2 we implemented our Packets this way? This way the Connection class can accept a generic class and send data in the correct format, regardless of the type of data being sent.

Let’s continue with some more code.

1
2
3
            if (c.Connected)
            {
                NetworkStream ns = c.GetStream();

We are only going to send the data if the client object is connected. That is why we have a check here to only send data if we have an open connection.

Now, we are going to actually conduct the business of sending and receiving using the “NetworkStream” class. Each connection has a stream object readily available, which we convert into a network data stream here. This way we can Read and Write data using standard stream methods.

1
2
3
4
5
                if (ns.CanWrite)
                {
                    byte[] data = p.ToByteArray();
                    byte[] packetID = BitConverter.GetBytes(p.PacketTypeCode);
                    byte[] len = BitConverter.GetBytes(data.Length);

Now that we have our network stream object, we check to see if we can write to it. If we can’t write to our network stream for any reason, then we can’t send data.

The next part is a bit complicated, but necessary. First it runs the Packet method ToByteArray() to convert the packet to a series of bytes. Remember implementing that in Part 2 of this series? Now it should make sense. We have to get a series of bytes to send over the network stream, and since our packet objects implement this function themselves it will always correctly convert itself to a byte array.

The next line of code takes the packet type code and converts it into a byte array. You might wonder why we need to do this. We cannot send an integer directly over the stream, so we have to convert that stream into an array of bytes. An integer is nothing more than bytes put together to form a 32 bit number, so it is not a stretch to think of an int as a byte array.

The next line populates a byte array with the length of the packet data. The reason this needs to be done is that the packets can be any length, and so we will need to transmit along with each packet how many bytes the total packet is. If our packet is 10 bytes, then we will transmit 10. This way the receiving end knows how much memory it needs to allocate and then read in order to get the full packet.

1
2
3
4
5
6
7
8
                    ns.Write(packetID, 0, packetID.Length);
                    ns.Write(len, 0, len.Length);
                    ns.Write(data, 0, data.Length);
 
                    ns.Flush();
                }
            }
        }

In these 3 lines of code, we just write the values we got to the stream. They must be written in the order here. The receiving end must also read them in this order. The first thing sent is the type of packet, so the receiving end will know what packet class to use to interpret the results. The second value sent is the length of the data that is about to be sent, which I explained above. The last value sent is the full data of the packet.

We then flush the stream to make sure all the data in the stream buffers gets pushed to the network.

Pages: 1 2 3


Follow Dave on Twitter

Leave a Reply