|
||
|
GP Mailing List
ATXGPSIG List
|
Net2: ExamplesDownload
Source in .tar.gz Part1:
Introduction I don't know about you, but I can usually learn more about how to do something from reading through a few examples than I can from reading documentation. Documentation tells you what the document writer thinks you need to know. It often leaves out all the stuff that the writer assumes you already know. Not to mention that it tells you what the writer thinks is true, which as we all know is not always the truth. On the other hand a code example has to actually compile and run. That means that everything you need to make the code work is there, even if it isn't documented. And, code does not lie. To get started I'm going to show you a few simple examples. These examples try to be the absolute minimum code needed to send and receive information over the network. UDP ExamplesThe following is a pair of programs that use the UDP protocol to send and receive messages. The first program, us.cpp, opens a port and waits for incoming messages. The second program, uc.cpp, sends a bunch of messages for the other one to receive. Receive UDP MessagesThe following code shows how to set up to accept incoming UDP/IP messages. The important things to notice are that the accept call is not inside of any loop and that all the messages are received as events. Also note that after getting the receive event it checks to see if there is more than one message waiting. NET2 only sends receive events when the input queue for a socket is empty. Which means that there may be dozens of messages queued up by the time you get around to handling the receive event. To play with these program start us in one command shell and start uc in another command shell and watch the output. If you want them to run on different machines you will have to edit tc to change the name of the computer it connects to. #include <stdlib.h>
// The following libraries all have to be included to get all of SDL
// plus the net2 and fastevents libraries. I include my SDLUtils
// library because I have used my initialization and quit functions to
// simplify the code.
#include "SDL.h"
#include "net2.h"
#include "fastevents.h"
#include "SDLUtils.h"
int main(int argc, char **argv)
{
SDL_Event ev; // storage for an SDL event
UDPpacket *p = NULL; // used to get messages
int count = 0;
mySDLInitOrQuit(SDL_INIT_EVENTTHREAD | // initialize SDL. We need
SDL_INIT_VIDEO | // events and it doesn't work
SDL_INIT_NOPARACHUTE); // without video.
// The following tells NET2 to start accepting messages on port
// 5555. It also tells NET2 that messages are no larger than 128 bytes
// long. That is all you have to do to start accepting UDP messages.
NET2_UDPAcceptOn(5555, 128);
// This is the normal SDL event loop. But, since we are using NET2
// we have to also use the fastevents library. Everything else
// should look normal. We just get an event and process it.
while (FE_WaitEvent(&ev))
{
//printSDLEvent(&ev);
switch (ev.type)
{
case SDL_QUIT: // this event tells us to stop
printf("count = %d\n", count); // how many messages were received
mySDL_Quit(); // use my utility to shut down
exit(0); // good bye
break;
// This part of the code handles user events. All NET2 events are user
// events. Not all user events are NET2 events.
case SDL_USEREVENT:
switch(NET2_GetEventType(&ev)) // get the event type
{
case NET2_UDPRECEIVEEVENT:
// This event tells us that there is at least 1 message waiting to be
// processed. There could be more than one. Notice that when we do a
// read we use the socket from the event.
printf("udp recieve\n");
//printNET2Event(&ev);
p = NET2_UDPRead(NET2_GetSocket(&ev)); // get a message
while (NULL != p) // if we get NULL we are done
{
count += p->len;
printf("%08x(%d)%s\n",p->address.host, p->address.port, p->data);
NET2_UDPFreePacket(p); // free the packet
p = NET2_UDPRead(NET2_GetSocket(&ev)); // get the next message
}
break;
// For this example I just print any errors I get. Normally you would
// want to check to see if you received a valid socket and take action
// to clean things up. But, for this demo I just print the error and
// continue as it nothing has happened.
case NET2_ERROREVENT:
printf("Error: %s(%d)\n", NET2_GetEventError(&ev), NET2_GetSocket(&ev));
//printNET2Event(&ev);
break;
}
break;
}
}
mySDL_Quit(); // Can we ever get here? if we do clean up and quit,
// we are done.
}Send UDP MessagesThe following code shows how to send a UDP/IP message to a computer. You can have some fun and learn a bit about UDP/IP using these two UDP examples. The most interesting thing to me is to see the number of dropped messages when the messages come from the same machine they are being sent to. My desktop machine machine starts losing messages early and then just drops everything after the first 500 or so messages. UDP really isn't a reliable way to send a message. But, if the message gets there are all, it gets there quickly. #include <string.h>
#include <stdlib.h>
// The following libraries all have to be included to get all of SDL
// plus the net2 and fastevents libraries. I include my SDLUtils
// library because I have used my initialization and quit functions to
// simplify the code.
#include "SDL.h"
#include "net2.h"
#include "SDLUtils.h"
int main(int argc, char **argv)
{
IPaddress ip; // where to send messages
char buf[100]; // will store messages
int i;
int limit = 1000;
int count = 0;
mySDLInitOrQuit(SDL_INIT_EVENTTHREAD | // initialize SDL. we need
SDL_INIT_VIDEO | // events and it doesn't work
SDL_INIT_NOPARACHUTE); // without video.
// The call to NET2_ResolveHost fills in the IPaddress with the IP
// address and port we are going to send messages to. You can put in
// any symbolic name and it will be resolved or you will get an
// error. I don't check for an error here because this is a sample,
// not production code, and if this fails, you have worse problems...
NET2_ResolveHost(&ip, "localhost", 5555); // talk to my self on 5555
for (i = 0; i < limit; i++) // send a BUNCH of messages
{
memset(buf, 0, sizeof(buf)); // clear the message buffer
sprintf(buf, "UDP message #%08d", i); // create a message
// The next line sends a UDP/IP message to the port and address stored
// in ip.
NET2_UDPSend(&ip, buf, sizeof(buf)); // send the message
count += sizeof(buf);
//printf("%d\n", i);
//SDL_Delay(1); // play with this to see
// how it effects the
// number of messages
// that get through
}
printf("count=%d\n", count); // print how many were sent
mySDL_Quit(); // clean up and quit
}TCP ExamplesThese two examples, tc.cpp and ts.cpp, demonstrate how to set up and use a TCP/IP connection using NET2. TCP/IP is a reliable way to send information back and forth between computers, but it will slow down to match the load on the network. So, it might be slower than you expect. To play with these programs first start ts, the server, in one command shell, and then start tc in another on the same machine, and watch them run. If you want them to run on different machines you will have to edit tc to change the name of the computer it connects to. TCP ClientFor some reason people call a program that makes a TCP/IP connection to a computer a “client.” This doesn't always make sense but usually, just like when someone calls you on the phone, the person or computer making that call wants something. So, they might as well be called clients. To following code shows how to make a TCP/IP connection to a computer using NET2. #include <string.h>
#include <stdlib.h>
// The following libraries all have to be included to get all of SDL
// plus the net2 and fastevents libraries. I include my SDLUtils
// library because I have used my initialization and quit functions to
// simplify the code.
#include "SDL.h"
#include "net2.h"
#include "SDLUtils.h"
int main(int argc, char **argv)
{
char buf[100]; // storage for a message
int i; // a counter
int s = -1; // the socket, just an int
int count = 0; // how many messages to send
int limit = 1000;
mySDLInitOrQuit(SDL_INIT_EVENTTHREAD | // initialize SDL. We need
SDL_INIT_VIDEO | // events and it doesn't
SDL_INIT_NOPARACHUTE); // work without video.
// Here we ask for a connection to the computer. In this case we are
// just trying to connect to the computer we are on at port 6666. We
// check to make sure we have a valid connection before going on with
// the rest of the program. Note that the socket id winds up in s.
if (-1 == (s = NET2_TCPConnectTo("localhost", 6666)))
{
printf("ConnectTo failed\n");
exit(0);
}
// All we do here is create a message and send it. The message is just
// the words "TCP message" followed by a message number.
for (i = 0; i < limit; i++)
{
memset(buf, 0, sizeof(buf));
sprintf(buf, "TCP message #%08d\n", i); // create the message to send
NET2_TCPSend(s, buf, sizeof(buf)); // send it and count it.
count += sizeof(buf);
//printf("%d\n", i);
//SDL_Delay(1);
}
printf("count=%d\n", count); // tell how many were sent
mySDL_Quit(); // clean up.
}TCP ServerThis example shows how to accept connections from a computer using the NET2 library. #include <stdlib.h>
// The following libraries all have to be included to get all of SDL
// plus the net2 and fastevents libraries. I include my SDLUtils
// library because I have used my initialization and quit functions to
// simplify the code.
#include "SDL.h"
#include "fastevents.h"
#include "net2.h"
#include "SDLUtils.h"
int main(int argc, char **argv)
{
SDL_Event ev; // an SDL event
char buf[1024]; // a message buffer
int len = 0; // some counters
int count = 0;
int socks = 0; // the number of
// connected sockets,
// which is also the
// number of connected
// clients.
mySDLInitOrQuit(SDL_INIT_EVENTTHREAD | // initialize SDL. We need
SDL_INIT_VIDEO | // events and it doesn't
SDL_INIT_NOPARACHUTE); // work without video
// This is where we tell NET2 to start accepting TCP/IP connections on
// port 6666. This call does not wait for a connection to come in. It
// tells NET2 to do the waiting and it returns immediately. After this
// call returns your program will get an event any time a computer
// trys to connect to the port given in this call.
NET2_TCPAcceptOn(6666);
while (FE_WaitEvent(&ev)) // wait for events
{
//printSDLEvent(&ev);
switch (ev.type)
{
// all NE2 events are SDL_USEREVENTs but not all user events are NET2
// events. If you use user events in your code you need to be careful
// to make sure you are not using the same event codes that NET2 uses.
case SDL_USEREVENT:
switch(NET2_GetEventType(&ev))
{
// This next piece of code handles an accept event. This event tells
// us that an connection has been accepted. Here, all we do is count
// it. You would normally take some other action.
case NET2_TCPACCEPTEVENT:
printf("accept(%d)\n", NET2_GetSocket(&ev));
printNET2Event(&ev);
socks++;
break;
// This next piece of code is for handling receive
// events. This kind of event tells us we have input waiting
// on a socket. You need to grab all of it. No that we get the
// socket from the event. You can use the socket to tell you
// which user sent the information to you.
case NET2_TCPRECEIVEEVENT:
while (0 != (len = NET2_TCPRead(NET2_GetSocket(&ev), buf, sizeof(buf))))
{
count += len;
}
break;
// If an error occurs on a socket or the other computer closes
// the connection you will get a close event. When you get a
// close event you must close the socket. Use the socket in
// the event to tell you which connection went away.
case NET2_TCPCLOSEEVENT:
printf("close(%d)\n", NET2_GetSocket(&ev));
printNET2Event(&ev);
NET2_TCPClose(NET2_GetSocket(&ev)); // close the socket
printf("count=%d\n", count); fflush(NULL);
socks--;
if (0 >= socks)
{
//exit(0);
}
//count = 0;
break;
// Sometimes you will get errors. It is best to keep track of
// them and try to figure out what is causing them.
case NET2_ERROREVENT:
printf("Error: %s(%d)\n", NET2_GetEventError(&ev), NET2_GetSocket(&ev));
printNET2Event(&ev);
break;
}
break;
case SDL_QUIT: // time to quit
mySDL_Quit(); // clean up and exit
exit(0);
break;
}
}
mySDL_Quit();
}
Part1:Introduction, Part2: Examples, Part3:Documentation, Part4:Sets Copyright © 2002 Robert C. Pendleton. All rights reserved.
|
|