http://GameProgrammer.Com

Programming

GP Mailing List
     Thread Index
     Date Index

ATXGPSIG List
     Thread Index
     Date Index

Google
>

Home

Wise2Food


Net2: Sets

Bob Pendleton


Download Source in .tar.gz
Download Source in .zip

Part1: Introduction
Part2: Examples
Part3: Documentation
Part4: Sets


Sets are very useful in network programming because you often need to keep track of a number of sockets and/or IP addresses using operations like those on a logical set. These routines allow you to add an item to a set, test to see if an item is a member of a set, remove an item from a set, and to iterate over the contents of a set. I've also included code to send a message to each item in the set.

Most high level programming languages such as Java or C++ provide a set data type either as a built in part of the language or as part of a standard library. Net2 is written in C to make it as easy as possible to embedded it in other languages. C does not have a set data type so I decided to include code for handling sets in Net2. Then, I realized that many, if not most, Net2 users would not need them so I moved them into separate files (net2sets.c and net2sets.h) which you can use or ignore as you please. Most of the code for these functions is generated by a set of weird looking C macros in set.h. If you are new to C you might find the contents of set.h educational. It shows how we used to implement generic types before languages like C++ and Java came along. Or, at least this is how some of us did it when we couldn't use LISP.

This implementation of sets is efficient for sets with small numbers of items. But, it does set operations using iterative O(n/2) algorithms that may be too slow for handling very large sets.

Sample Code

The following code creates a SocketSet and initializes it. The example code then adds 1000 sockets to the set. After that it deletes all the even numbered sockets. Finally, it iterates over the set printing out all the sockets in no particular order. The complete program can be found in set.cpp.

int main(int argc, char **argv)
{
  int i;
  int j;

  SocketSet s;                       // declare the set
  initSocketSet(&s, 100);            // initialize it
  
  for (i = 0; i < 1000; i++)
  {
    addSocketSet(&s, &i);            // add members to the set
  }

  for (i = 0; i < 1000; i += 2)
  {
    delSocketSet(&s, &i);            // delete members from the set
  }

  for (j = firstSocketSet(&s, &i);   // get first member
       j != -1;                      // check for end of set
       j = nextSocketSet(&s, &i))    // get the next member 
  {
    printf("item = %d\n", i);        // print out the members
  }

  finitSocketSet(&s);                // free memory used by the set
}

Socket Sets

In Net2 a socket is represented as a small integer so the set operations take a pointer to a SocketSet structure and integers as parameters. To create a SocketSet declare a variable of type SocketSet or malloc() a structure of that type and then initialize it. The actual structure looks like:

typedef struct
{
  int itr;
  int last;
  int size;
  int *set;
} SocketSet;

int initSocketSet(SocketSet *s, int size);

Initializes a SocketSet structure for use by your program. You can't use the set until you initialized it. The size parameter tells you the initial size of the set. The set functions will allocate more memory to store the set if they need to. But, while the set will automatically grow beyond the size specified, it will not automatically shrink.

s: Pointer to a SocketSet structure.

size: Initial capacity of the set. If the number of items you add to the set exceeds this amount then more storage is allocated for the set.

Returns: -1 if the action failed and 0 (zero) if it succeeded.

void finitSocketSet(SocketSet *s);

Frees all memory allocated to the set. Use this to make sure that memory is freed and to prevent memory leaks.

s: Pointer to a SocketSet structure.

int memberSocketSet(SocketSet *s, int *v);

Test to see if the socket v is already a member of the set. The value returned by this function can be used to find the element of and change it. Doing that is not a good idea when you are working with sockets. This ability is built in for use with more complex structures. Look at set set.h to see how to take advantage of this for your own sets.

s: Pointer to a SocketSet structure.

v: Pointer to an integer, a Net2 socket.

Returns: -1 if the socket is not a member of the set. Or, a value N >= 0 if it is a member of the set. The value N is the index of the item in the vector used to represent the set. The value of N is valid until after the next call to any set operation.

int addSocketSet(SocketSet *s, int *v);

Adds a socket to the set. No matter how many times you add an item to a set there will never be more than one copy of it in the set.

s: Pointer to a SocketSet structure.

v: Pointer to an integer, a Net2 socket.

Returns: -1 if the operation failed and 0 (zero) if it succeeded.

int delSocketSet(SocketSet *s, int *v);

Removes a socket from the set. If this call succeeds the socket will no longer be a member of the set.

s: Pointer to a SocketSet structure.

v: Pointer to an integer, a Net2 socket.

Returns: -1 if the operation failed and 0 (zero) if it succeeded.

int firstSocketSet(SocketSet *s, int *v);

This function is used with nextSocketSet() to iterate over the contents of a SocketSet. This function copies the first socket in the set to the value pointed to by *v replacing that value.

s: Pointer to a SocketSet structure.

v: Pointer to an integer, a Net2 socket.

Returns: -1 if the operation failed and 0 (zero) if it succeeded. That is, 0 if there is an item in the set and -1 if the set is empty.

int nextSocketSet(SocketSet *s, int *v);

This function is used with firstSocketSet() to iterate over the contents of a SocketSet. It either copies the next item in the set to the value pointed to by *v and returns 0 or it leaves that value alone and returns -1.

s: Pointer to a SocketSet structure.

v: Pointer to an integer, a Net2 socket.

Returns: -1 if the operation failed and 0 (zero) if it succeeded. That is, 0 if a value was returned and -1 if there are not more items in the set.

int NET2_TCPSendSet(SocketSet *s, char *buf, int len);

This function sends the same buffer of data to every socket in the set. This means that it will send a message to no one when the set is empty, or to hundreds or thousands of recipients if there are that many members of the set. One problem with using this function is the value returned by this function. The return value indicates an error if an error occurred sending a message to any member of the set. If more detailed error reporting is needed use the first/next functions to iterate over the set and send each message separately (which is what this function actually does) and check each for errors.

s: Pointer to a SocketSet structure.

buf: Data in the form of a character array to be sent to every member of the set.

len: The number of characters to send.

Returns: the number of bytes sent. If this value is less than len then an error occurred.

IP Address Sets

The IPSet type is essentially the same as SocketSet type. The only difference is that the IPSet type stores SDL_net IPaddress values while the SocketSet type stores sockets. Two IP addresses are considered to be equal if both the IP address and port number are the same. The IPSet structure is:

typedef struct
{
  int itr;
  int last;
  int size;
  IPaddress *set;
} IPSet;

int initIPSet(IPSet *s, int size);

Initializes a IPSet structure for use by your program. You can't use the set until you initialized it.

s: Pointer to an IPSet structure.

size: Initial capacity of the set. If the number of items you add to the set exceeds this amount then more storage will be allocated for the set.

Returns: -1 if the action failed and 0 (zero) if it succeeded.

void finitIPSet(IPSet *s);

Frees all memory allocated to the set. Use this to make sure that memory is freed and to prevent memory leaks.

s: Pointer to an IPSet structure.

int memberIPSet(IPSet *s, IPaddress *v);

Test to see if the IPaddress v is already a member of the set.

s: Pointer to a IPSet structure.

v: Pointer to an IPaddress as defined by SDL_net.

Returns: -1 if the IPaddress is not a member of the set. Or, a value N >= 0 if it is a member of the set. The value N is the index of the item in the vector used to represent the set. The value of N is valid until after the next call to any set operation.

int addIPSet(IPSet *s, IPaddress *v);

Adds an IPaddress to the set. No matter how many times you add an item to a set there will never be more than one copy of it in the set.

s: Pointer to a IPSet structure.

v: Pointer to an IPaddress as defined by SDL_net.

Returns: -1 if the operation failed and 0 (zero) if it succeeded.

int delIPSet(IPSet *s, IPaddress *v);

Removes an IPaddress from the set. If this call succeeds the IPaddress will no longer be a member of the set.

s: Pointer to a IPSet structure.

v: Pointer to an IPaddress as defined by SDL_net.

Returns: -1 if the operation failed and 0 (zero) if it succeeded.

int firstIPSet(IPSet *s, IPaddress *v);

This function is used with nextIPSet() to iterate over the contents of a IPSet. This function copies the first IPaddress in the set to the value pointed to by *v replacing that value.

s: Pointer to a IPSet structure.

v: Pointer to an IPaddress as defined by SDL_net.

Returns: -1 if the operation failed and 0 (zero) if it succeeded. That is, 0 if there is an item in the set and -1 if the set is empty.

int nextIPSet(IPSet *s, IPaddress *v);

This function is used with firstIPSet() to iterate over the contents of an IPSet. It either copies the next item in the set to the value pointed to by *v and returns 0 or it leaves that value alone and returns -1.

s: Pointer to a IPSet structure.

v: Pointer to an IPaddress as defined by SDL_net.

Returns: -1 if the operation failed and 0 (zero) if it succeeded. That is, 0 if a value was returned and -1 if there are not more items in the set.

int NET2_UDPSendSet(IPSet *s, char *buf, int len);

This function sends the same buffer to every IPaddress in the set. This means that it will send a message to no one when the set is empty, or to hundreds or thousands of recipients if there are that many members of the set. One problem area is in the value returned by this function. The return value indicates an error if an error occurred sending a message to any member of the set. If more detailed error reporting is needed use the first/next functions to iterate over the set and send each message separately (which is what this function actually does) and check each for errors.

s: Pointer to a IPSet structure.

buf: Data in the form of a character array to be sent to every member of the set.

len: The number of characters to send.

Returns: Zero (0) if any send failed and 1 if a message was sent to each IPaddress in the set.


Part1:IntroductionPart2: ExamplesPart3:DocumentationPart4:Sets


Copyright © 2002 Robert C. Pendleton. All rights reserved.