Click here to Skip to main content
15,892,161 members
Articles / Desktop Programming / MFC
Article

Network Stream Class

Rate me:
Please Sign up or sign in to vote.
3.27/5 (10 votes)
6 May 20032 min read 56.4K   971   25   5
A stream class to prepare data to be sent over the network

Introduction

The Stream class is very useful to network programming because if you want to send some data over network you first need to pack some diffrent structs to one packet, then send it over network and afterwoods you have to reconstruct the old data structure:

datastructure -> stream -> send ->...network...-> receive -> stream -> datastructure

Output of Example program:

Test 1: seemless stream by using the end() method:

 putting 11 bytes to stream...->"1________x"
 putting 21 bytes to stream...->"2________xa________x"
 putting 31 bytes to stream...->"3________x_________xb________x"
 stream complete. Ready to send it over any device (eg. network)
 deleting test data to make sure all data safely are in stream...
 stream looks like:
 -------------------------------------------------------------------
  31 5F 5F 5F 5F 5F 5F 5F 5F 78 00 32 5F 5F 5F 5F 5F 5F 5F 5F 78 61 
  5F 5F 5F 5F 5F 5F 5F 5F 78 00 33 5F 5F 5F 5F 5F 5F 5F 5F 78 5F 5F 
  5F 5F 5F 5F 5F 5F 5F 78 62 5F 5F 5F 5F 5F 5F 5F 5F 78 00 
 -------------------------------------------------------------------
 <63 Data Bytes, 63 Total>

Test 2: stream with header and block information by using the 
endWidthBlockList() method:

 putting 11 bytes to stream...->"1________x"
 putting 21 bytes to stream...->"2________xa________x"
 putting 31 bytes to stream...->"3________x_________xb________x"
 stream complete. Ready to send it over any device (eg. network)
 deleting test data to make sure all data safely are in stream...
 stream looks like:
 -------------------------------------------------------------------
  03 00 00 00 0B 00 00 00 31 5F 5F 5F 5F 5F 5F 5F 5F 78 00 15 00 00 
  00 32 5F 5F 5F 5F 5F 5F 5F 5F 78 61 5F 5F 5F 5F 5F 5F 5F 5F 78 00 
  1F 00 00 00 33 5F 5F 5F 5F 5F 5F 5F 5F 78 5F 5F 5F 5F 5F 5F 5F 5F 
  5F 78 62 5F 5F 5F 5F 5F 5F 5F 5F 78 00 
 -------------------------------------------------------------------
 <63 Data Bytes, 79 Total>
 reconstruct old structure :
 Number of blocks: 3
 Stream Block Nr.  = 1
 Stream Block size = 11 bytes
 Stream Block data = "1________x"
 Stream Block Nr.  = 2
 Stream Block size = 21 bytes
 Stream Block data = "2________xa________x"
 Stream Block Nr.  = 3
 Stream Block size = 31 bytes
 Stream Block data = "3________x_________xb________x"
done. 

Using the code

The way you use this class is easy. You just have to make an instance of stream and then add data to it. When finished you have to call end or endWithBlockList to get the stream. The diffrence between end and endWithBlockList:

  • end() will give you the complete Data in one Block without any header or block information. You will not be able to reconstruct the datastructure from this, but anyway you may need it if you don't need header and blockinformations (eg. voice over ip)
  • endWithBlockList() will give you a complete stream with header and a list of blocks. With this you can reconstruct your data structure.

Here an example on how to use it if you want to send data over network:

Code on the first PC

Stream myStream;
myStream.begin();
    
// fill in some data to stream:
myStream.add("Hello",6); // 5 + '\0'
myStream.add("World",6); // 5 + '\0' 
myStream.add("!",2); // 1 + '\0'
char * myData = (char *) myStream.endWithBlockList();

now you have to send the myData over network and receive it on a second pc(i will not show you how to do that at this time ;-P)

now the code for the second Pc:

// data was received over TCP/IP and stored in char * myData

// get header information
tStreamheader * pStreamheader = (tStreamheader *)myData;
unsigned long * pBlocksize; // this will hold our block lenght
char * pBlockdata = NULL; // this will hold our block data

// offset pointer beginning after header...
unsigned long myoffset = sizeof(tStreamheader); 

for (i = 0; i< (int) pStreamheader->numblocks; i++) // all blocks to be processed
{
  // get our blocksize of next block
  pBlocksize = (unsigned long *) (myData + myoffset); 
  myoffset+=sizeof(unsigned long); // go to it
  pBlockdata = new char[*pBlocksize]; // make room for block data
  memmove(pBlockdata, myData + myoffset,*pBlocksize); // copy the block data
  myoffset+=*pBlocksize; // step to next block (blocksize+blockdata)

  printf("%s ",pBlockdata); // print out blockdata 
  // hint: if its not a zeroterminated string we will get rubbish, 
  // so don't forget the '\0'

  delete [] pBlockdata; // we don't need the data anymore...
  pBlockdata = NULL; // to make shure no one will make unwanted quickreboots
}

program on second PC will print out:

Hello World !

tStreamheader is a struct for the header information of our stream. It contains only one variable at this time(unsigned long numblocks) but it is easy to enhance it if you need more detailed information in the header like source, destination, time, totalsize,...

History

Version 1.0 released at 24.04.2003

1 May 2003 - v 1.1

  • more efficient (you can create the stream as often you need, not only one time)
  • easier to use (you dont need say that you want to "BEGIN" a stream - so the method "begin()" was removed)
  • there are no known bugs to be fixed, so no bugfix needed :-P

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior) Deep Silver FISHLABS
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Generalrubbish Pin
mfreund11-May-06 10:13
mfreund11-May-06 10:13 
GeneralRe: rubbish Pin
Sendel14-May-06 15:40
Sendel14-May-06 15:40 
GeneralNew Update will come in some days Pin
Sendel30-Apr-03 20:08
Sendel30-Apr-03 20:08 
GeneralRe: New Update will come in some days Pin
yuyunqiang13-May-04 17:58
yuyunqiang13-May-04 17:58 
GeneralRe: New Update will come in some days Pin
Sendel14-May-04 0:40
Sendel14-May-04 0:40 
This class is only to create a stream, it doesn't do any network action at this moment. If you wan't to use one stream for several threads, you have to look that only one thread write or read at time. So to answer your question: it is not multithread compliant, but with little workaround you can make it multithread able. If you use Microsoft Windows (instead of Linux) you can use "Mutex" to make sure that only one thread has proteced access to your stream. I used that for my network class and it works quite proparly. If you want to be shure and dont want to use mutex, you can use a stream class for each thread if you want.

how to create a network class with this stream class:

1. choose a network protocol (Tcp/ip or UDP)
2. create a simple network connection class which is able to send and receive some bytes.
3. create an own network layer protocol with a header and data (look down for details)

now the difficult part begins:
you may receive some packets from one client and then some other from another client just in a random order (because if you want to send 1MB data for example, you have to split this big thing into small peaces, 16KByte peaces for example). Therefore you have to have some usefull information in each packet-header:

1. unique packet id (ip-adress + unique generated nr. for example)
2. destination ID (the destination to deliver the packet)
3. total packets count (how many packtets will be sent and therefor needed to be received?)
4. packetnr (which packet is this?)
5. packetsize (how big is this thing? 16Kbyte?)
6. total size (not really needed, but a good value to check if packet is received completely)
7. data (data to be sent over network)

When receiving in a random order you can sort the packets by creating a stream for each unique packet id. When all packets of one Unique-Packet-ID are received you can sent it to the destination and delete the stream.

ok, but where to make the thread? (multithread?):
if you receive the packets you'll extremly need a thread(otherwise your system will hang the most of the time). So, the best way to use the "mutex" is when writing to the receive-buffer or writing to the send-buffer. If you want to make a thread for each client connection you will have to setup some more mutex for each send- or receivebuffer. If you want to make the "destination-class" threadable, you have to setup "mutex" in this class for each instance again. I am sure that you'll find a good mutex or network class somewhere at codeproject.

I hope that was useful and understandable. If you have any questions, don't hasitate !
cheers,
Sendel

The only place for millions of bugs is the Rainforest

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.