|
||
|
GP Mailing List
ATXGPSIG List
|
Net2: DocumentationDownload
Source in .tar.gz Part1:introduction Init and Quit RoutinesLike every other library in the world NET2 requires you to call an initialization routine before you start using it and recommends that you call a finalization (or quit) routine when you are done with it. The trouble is that before you can initialize NET2 you have to have already initialized SDL, SDL_net, and FE. Like any good programmer I'm too lazy to write all that code every time I want to use NET2 so I wrote a some utility routines that do the job for me. You can find them in my SDLUtils.h and SDLUtils.c files that are included with the NET2 source or you can just copy them initialization and quit functions from here. char *mySDL_Init(Uint32 flags)
{
if (-1 == SDL_Init(flags))
{
return SDL_GetError();
}
if (-1 == SDLNet_Init())
{
return SDLNet_GetError();
}
if (-1 == FE_Init())
{
return FE_GetError();
}
if (-1 == NET2_Init())
{
return NET2_GetError();
}
return NULL;
}mySDL_Init() simply tries to initialize each library in turn, and if the initialization fails, it returns a pointer to an error message. Otherwise, it returns NULL. Since it take the same arguments as SDL_Init() you can use it anywhere you normally call SDL_Init(). It is also pretty easy to modify this routine, and my other utility routines, to initialize other libraries as well as the ones it already handles. void mySDLInitOrQuit(Uint32 flags)
{
char *message = NULL;
if (NULL != (message = mySDL_Init(flags)))
{
printf("Failed to initialize SDL error=%s\n", message);
exit(1);
}
atexit(mySDL_Quit);
}mySDLInitOrQuit() is handy when you are developing and testing. It takes the same arguments as the standard SDL_Init() routine so you can just use it in place of SDL_Init(). It tries to start everything up, but if an error occurred starting any of the libraries it just prints the error message and quits. If everything goes as it should, it sets up a handy cleanup routine using atexit() and exits. void mySDL_Quit()
{
NET2_Quit();
FE_Quit();
SDLNet_Quit();
SDL_Quit();
}mySDL_Quit() shuts down all the layers in the proper order. Use it at the end of the program to clean up everything. int NET2_Init();Initialize the NET2 library. It allocates all resources used by the library, and starts the input thread. This function must be called before any other NET2 functions can be called. No NET2 events will be generated until this function is called. Returns: -1 on failure and 0 (zero) on success. void NET2_Quit();Kills the input thread and releases all resources used by the NET2 library. This function should be called to clean up at the end of a program. It must be called if you are going to restart the NET2 library. NET2 SocketsIn NET2 a socket is just an integer index used by the library to keep track of a connection. You can count on the fact that a socket number is never negative. You can also count on old socket numbers to be reused. The library has a fixed number of sockets available and reuses them. The default NET2 configuration allows for 1024 sockets. You can reconfigure it to make any number of sockets available. But, since TCP/IP only allows 65536 connections there isn't much point in configuring NET2 to handle more than that. There are a few rules you should follow. Never use a socket index after it has been closed. Never do arithmetic on socket indexes. Never count on sockets being allocated in a specific order. You can get socket 1 and then get socket 37 and after that you might get 23. Socket indexes can be safely used as indexes into arrays of information about that connection. That is why they are simple integers. To make programming easy. Supported ProtocolsNET2 supports the TCP/IP (Transmission Control Protocol/Internet Protocol) and UDP/IP (User Datagram Protocol) protocols. I'm not going to try to give a tutorial on those protocols here, but it is important to briefly discuss these protocols. TCP/IPTCP/IP is a connection oriented protocol. What that means is that it acts rather like a phone call. When you make a phone call you make a connection, talk over that connection, and then hang up. To make calls you have to know the telephone number of the people you want to call. To accept calls you have to have a phone number. A TCP/IP connection is logically that same, though the underlying details are completely different. And, like a phone, a TCP/IP connection is a reliable connection. You can be sure that if you send data over a TCP/IP connection it will get there or you will get an error telling you it failed. To use TCP/IP you have to have an IP address and you have to know the IP address of the computer you are going to call. If you computer is connected to the net it has an IP address, and DNS (Domain Name System) lets you look up another computers address based on its name the same way your browser connected to Gameprogrammer.com given only its name. When your program makes a TCP/IP connection it asks to connect to a given IP address on a specific port. (You can think of a port as being like the extension number you use when calling into an office.) If the connection is granted then you can send and receive data over the connection. Either end of the connection can close the connection (hang up the phone) any time they want to. To accept incoming connections you have to register a port to accept connections on. You can accept connections on many different ports at the same time. When a connection comes in you answer it, send and receive information, and then close the connection. UDP/IPUDP/IP is a message oriented protocol. And, it is not reliable. It is rather like writing a message on a paper airplane and sending it gliding towards the person you want to get the message. It might get there, and it might not. UDP/IP is more reliable than that, but there are no guarantees that a UDP message will get where you are sending it. People use UDP because when it works it generally works very quickly. To send a UDP message you just need the IP address and the port to send it to. To accept UDP messages you just register a port for them to come in on. When a message comes in, process it as you wish. NET2 EventsNET2 is based on and driven by events. Many of the NET2 functions don't do much by themselves, they set things up so that you can get events that tell you what has happened. All NET2 events are packaged inside of SDL_Event structures. Each SDL_Event has a type field that tells you what kind of event you are getting. Each NET2 events has a type of SDL_USEREVENT. Each SDL_USEREVENT has a code field that is used to tell one kind of user event from another. In NET2 the codes are specified using the following enumeration: NET2 Event Typesenum
{
NET2_ERROREVENT,
NET2_TCPACCEPTEVENT,
NET2_TCPRECEIVEEVENT,
NET2_TCPCLOSEEVENT,
NET2_UDPRECEIVEEVENT,
};If your program also makes use of user events you will have to make sure that your code and the NET2 code do not use the same codes. The rest of the fields in a user event are used in different ways depending of the event code. NET2 includes a number of helper functions whose only purpose it to get the right data out of the right fields in an event. The following gives more information about each NET2 event type. NET2_ERROREVENTAn error event contains a pointer to an error message string, and either a socket index or -1. A -1 is passed as the socket index when the error does not relate to a specific socket. Use the NET2_GetSocket() and NET2_GetEventError() functions to retrieve those values. NET2_TCPACCEPTEVENTWhen a TCP/IP connection comes in on a specific port your program will get an NET2_TCPACCEPTEVENT. This event tells you that your computer has accepted a connection from another computer. This event contains the socket index to use to talk to the other computer and the port that the connection came in on. You need the port because your program may be accepting connections on more that one port. Use NET2_GetSocket() to get the socket index and NET2_GetEventData() to get the port number from the event. NET2_TCPRECEIVEEVENTThis event is sent to your program when data is received from a remote computer over a TCP/IP connection. After getting this event you need to read and process all the data that has been received. Your program will not get another event of this type until you have read all the data pending on the socket. This event includes the socket index for the connection. Use NET2_GetSocket() to get the socket index from the event. NET2_TCPCLOSEEVENTThis event tells you that either the connection has been closed from the other end or an error has occurred. When your program gets this event you should just use NET2_TCPClose() to close the socket and ignore the returned status. Use NET2_GetSocket() to get the socket index from the event. NET2_UDPRECEIVEEVENTThis event tells your program that a UDP/IP message has be received. After getting this event you need to read and process all the messages that are pending on the socket. Your program will not get another event of this type until you have read all the messages queued on this socket. This event contains a socket index that you can use to get the message that was received. Use NET2_GetSocket() to get the socket index from the event. Event Helper FunctionsThe following functions are used to get NET2 data from SDL events. int NET2_GetEventType(SDL_Event *event);A helper function that gets the code field from an SDL_Event. If the event came from NET2 then it will be a member of the enumeration listed above. If not, then it could be almost any value. event: A pointer to an SDL_Event. Returns: An integer. int NET2_GetSocket(SDL_Event *event);A helper function that returns the socket index from a NET2 event. If the event was not generated by NET2 then this could be anything. event: A pointer to an SDL_Event. Returns: -1 if no socket index is available or an integer greater than or equal to 0 (zero). int NET2_GetEventData(SDL_Event *event);This helper function returns other data associated with a NET2 event. Currently this function is only useful for getting the port number from an NET2_TCPACCEPTEVENT. event: A pointer to an SDL_Event. Returns: An integer. When used correctly the integer is a port number for a TCP/IP connection. Error Handling RoutinesIn NET2 an error can occur immediately when a function is called or it can occur asynchronously as events are handled in the IO thread. For that reason NET2 has a function that fetches a description of immediate errors and a helper routine for getting descriptions of asynchronous errors that are reported using an error event. char *NET2_GetError();Get the a string that describes the last immediate error that occurred. Returns: If an error has occurred than a pointer to an error message is returned. Otherwise NULL is returned. Immediate Error MessagesA lot of these errors are reported from internal consistency checks that test for conditions that are supposed to be impossible. But, one bad pointer can ruin you whole day and turn the impossible into the possible by letting you write all over everything. So, I test for the impossible to help find memory corruption errors and bugs in the library.
char *NET2_GetEventError(SDL_Event *event);This is a helper function used to process error events. See the NET2_ERROREVENT description for more information about how it works. event: A pointer to an SDL_Event. Returns: When applied to a NET2_ERROREVENT it returns a pointer to an error message that describes the error. If misused it will return most any kind of garbage. Asynchronous Error MessagesMost of these message are internal consistency checks for conditions that aren't supposed to be possible. Why check for the impossible? Because a bad pointer in your code can mess up everything by letting you write arbitrary values all over your program. Any way, you want to detect and report all errors, and you especially want to report the impossible errors!
Resolve Hostint NET2_ResolveHost(IPaddress *ip, char *name, int port);Fills in an SDL_net IPaddress structure based on a domain name or a string representation of an IP address and a port number. IPaddress structures are used to create connections to other computers and to set up to accept TCP/IP connections and UDP/IP messages. Ip: A pointer to an IPaddress structure to fill in. name: Domain name of a computer or an IP address in character form. Examples: “localhost,”, “gameprogrammer.com”, or “192.168.1.5”. port: An IP port number in the range 0 to 65535. Returns: -1 if the operation failed and 0 (zero) on success. This function will fail if no address can be found for the named system. TCP RoutinesThe following routines are used with TCP/IP connections. They allow you to accept incoming connections, create outgoing connections, and to send and receive data over a connection. int NET2_TCPAcceptOn(int port);This function tells NET2 to start waiting for incoming TCP/IP connections on a specific port. Unlike other TCP/IP "accept" function this function returns immediately, it does not wait for a connection. NET2 does the waiting while your program continues to run. When a connection comes in NET2 will send you an event telling you about the connection. You can use this function to accept connections on several ports at the same time. This function returns a socket. To stop accepting connections on a port just close the socket returned by this function. port: The port number to accept connections on. Only connections coming in on this port number will reach your program. The port is opened for the default IP address of the machine you are running on. Returns: -1 if the operation failed and a socket index greater than or equal to 0 (zero) on success. The most likely reasons for this function to fail are that you are trying to use a port that another program is already using or you are trying to use a port in the range 0-1023 and the program is not running with root privileges. int NET2_TCPAcceptOnIP(IPaddress *ip);This function is essentially the same as NET2_TCPAcceptOn() except that its parameter is an IPaddress structure (possibly filled in by NET2_ResolveHost()), instead of just a port number. This function is for use on computers with multiple interfaces and multiple IP addresses. The use of an IPaddress structure allows you to specify the both the IP address and the port to open for connections. ip: A pointer to a properly filled in IPaddress structure. Returns: -1 if the operation failed and a socket index greater than or equal to 0 (zero) on success. The most likely reasons for this function to fail are that the IPaddress structure was not properly filled in, you are trying to use a port that another program is already using, or you are trying to use a port in the range 0-1023 and the program is not running with root privileges. int NET2_TCPConnectTo(char *name, int port);This function creates a TCP/IP connection to a specific port on a named computer. You give it the symbolic name of the computer and the port to connect to and it gives you a socket that you use to send and receive TCP/IP messages to and from the named computer. name: Domain name of a computer or an IP address in character form. Examples: “localhost”, “gameprogrammer.com”, or “192.168.1.5”. port: An IP port number in the range 0 to 65535. Returns: -1 if the operation failed and a socket index greater than or equal to 0 (zero) on success. int NET2_TCPConnectToIP(IPaddress *ip);This function is essentially the same as NET2_TCPConnectTo() except that its parameter is an IPaddress structure containing both an IP address and a port number, instead of a name and a port number. ip: A pointer to a properly filled in IPaddress structure. Returns: -1 if the operation failed and a socket index greater than or equal to 0 (zero) on success. void NET2_TCPClose(int socket);This function closes a TCP/IP socket. You may have gotten the socket by calling any of the TCP/IP accept or connect functions. This function makes the integer that stands for the socket available for reuse, so the next socket you get may have the same number as the one you just closed. After closing the socket it is an error to try to do anything with it. socket: An integer that represents a TCP/IP socket. int NET2_TCPSend(int socket, char *buf, int len);NET2_TCPSend() is used to send data to the computer at the other end of a TCP/IP connection represented by the socket. If this function encounters an error it sends an event telling you to close the socket. After the error you can still read from the socket, but you can no longer send to the socket. socket: An integer that represents a TCP/IP socket. buf: A pointer to a block of data you want to send to the other computer. Must not be NULL. len: The number of bytes of data to send. Must be greater than 0 (zero). Returns: -1 if an error occurred or the len, the number of bytes you asked to send. int NET2_TCPRead(int socket, char *buf, int len);After getting a NET2_TCPRECEIVEEVENT you must use this function to read the data that has been received by the socket. This function reads at most len bytes of data. It returns the actual number of bytes that were read. socket: An integer that represents a TCP/IP socket. buf: A pointer to the location you want data read into. Must not be NULL. len: The maximum number of bytes that you want to read. Len must be less than or equal to the size of the input buffer (buf). Returns: The number of bytes copied into buf. This could be any value from 0 to len. IPaddress *NET2_TCPGetPeerAddress(int socket);Returns the IP address of the computer on the other end of the connection. It is useful if you want to track incoming connections by their IP addresses. For example: to prevent multiple connections from the same player. It will return NULL if the operation is not valid for the socket. You must not free the IPaddress structure that is returned and you must not modify its contents. socket: An integer that represents a TCP/IP socket. Returns: Either a pointer to an IPaddress structure, or NULL. UDP RoutinesThese routines are for sending and receiving messages using the UDP/IP protocol. To avoid security problems that can result from buffer overruns these functions only allow messages of a fixed length. int NET2_UDPAcceptOn(int port, int size);Before you can get mail you have to have a mail box. This function declares a port on your computer that can accept incoming UDP messages. You can have multiple ports that all accept UDP messages of different sizes. The returned value is a socket that you use to tell which port a message came in on and to close the port when you are done with it. port: An IP port number in the range 0 to 65535. size: The size of messages that will be received on this port. Returns: -1 if the operation failed and a socket index greater than or equal to 0 (zero) on success. void NET2_UDPClose(int socket);When you no longer want to accept UDP/messages on a port or an error has occurred you must close the socket using this function. socket: An integer that represents a UDP/IP socket. int NET2_UDPSend(IPaddress *ip, char *buf, int len);Use this function to send a UDP/IP message to a computer. The IPaddress structure contains the IP address and the port number to send the message to. ip: A pointer to a properly filled in IPaddress structure. buf: A pointer to a block of data to be sent. len: The number of bytes to send. Returns: -1 if the operation failed and 0 (zero) if the message was sent. Note: because this is sending a UDP/IP message the fact that the message was sent does not mean that it was received. UDP/IP messages can be dropped by the network and by the receiving computer. UDPpacket *NET2_UDPRead(int socket);After receiving a NET2_UDPRECEIVEEVENT event you must retrieve queued message using NET2_UDPRead(). The socket to read from is provided in the event and can be used to tell which port the message came in on. The UDPpacket must be freed using NET2_UPDFreePacket() when you are done with it or you will have a memory leak. socket: An integer that represents a UDP/IP socket. Returns: A pointer to a UDPpacket structure or NULL if there are no more messages in the queue. void NET2_UDPFreePacket(UDPpacket *packet)A UDPpacket returned by NET2_UDPRead() must be freed by calling this function. These packets are dynamically allocated and must be freed so that the memory can be reused. Failure to free them properly will cause a memory leak in your program. packet: a pointer to a UDPpacket returned by NET2_UDPRead().
Part1:Introduction, Part2: Examples, Part3:Documentation, Part4:Sets Copyright © 2002 Robert C. Pendleton. All rights reserved.
|
|