├── LICENSE.TXT ├── Makefile ├── bufferclient.c ├── bufferserver.c ├── chat.c ├── chat.h ├── chatserver.c ├── docs ├── changelog.txt ├── images │ ├── important.png │ ├── no.png │ └── yes.png ├── manual.html └── style.css ├── echoserver.c ├── netBuffer.c ├── netBuffer.h ├── netSocket.c ├── netSocket.h ├── readme.md ├── testclient.c ├── testserver.c └── webserver.c /LICENSE.TXT: -------------------------------------------------------------------------------- 1 | netLib Network Communication Library 2 | v0.4 - 2007.08.30 3 | Coded by Ian Seyler (iseyler@gmail.com) 4 | http://bubbai.ath.cx/projects/netlib/ 5 | 6 | Copyright (c) 2007 Ian Seyler 7 | 8 | Permission is hereby granted, free of charge, to any person 9 | obtaining a copy of this software and associated documentation 10 | files (the "Software"), to deal in the Software without 11 | restriction, including without limitation the rights to use, 12 | copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the 14 | Software is furnished to do so, subject to the following 15 | conditions: 16 | 17 | The above copyright notice and this permission notice shall be 18 | included in all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 22 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 24 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 25 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 | OTHER DEALINGS IN THE SOFTWARE. 28 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | gcc webserver.c netSocket.c -o webserver -DUNIX 3 | clean: 4 | rm -f webserver 5 | -------------------------------------------------------------------------------- /bufferclient.c: -------------------------------------------------------------------------------- 1 | /* 2 | bufferclient.c - Module file for Test Buffer Client demo using netLib 3 | v0.4 - 2007.08.30 4 | Coded by Ian Seyler (iseyler@gmail.com) 5 | http://bubbai.ath.cx/projects/netlib/ 6 | Copyright (c) 2007 Ian Seyler. All Rights Reserved. 7 | Distributed under the terms of the MIT License. 8 | */ 9 | 10 | 11 | #include "netSocket.h" 12 | #include "netBuffer.h" 13 | 14 | int main(int argc, char *argv[]) 15 | { 16 | int tint, tint2, tint3; 17 | unsigned int tval; 18 | unsigned short tval2; 19 | int buffervalint; 20 | short buffervalshort; 21 | char buffervalstring[128]; 22 | netSocket *tempsocket; // YOU MUST INITIALIZE ALL SOCKETS BEFORE USING THEM!! (netInitSocket) 23 | netBuffer *tempbuffer; // YOU MUST INITIALIZE ALL BUFFERS BEFORE USING THEM!! (netInitBuffer) 24 | 25 | printf("Buffer Client demo for netLib v0.4\n"); 26 | 27 | if (argc < 2) // make sure we got a destination as an arguement 28 | { 29 | printf("Usage : bufferclient hostname (ex: testclient bubbai.ath.cx)\n"); 30 | exit(1); 31 | } 32 | 33 | netInit(); // Start the netLib library 34 | 35 | tempsocket = netInitSocket(); // initiate the socket 36 | tempbuffer = netInitBuffer(128); // initiate a 128 byte buffer 37 | 38 | if (netConnect(tempsocket, argv[1], 8192) == netOK) // if the connection looks good, keep going 39 | { 40 | printf("\n"); 41 | for (tint=0; tint<3; tint++) //loop of doing a netRecvBuffer 3 times 42 | { 43 | netBufferClear(tempbuffer); 44 | tint2 = netRecvBuffer(tempsocket, tempbuffer); 45 | 46 | if(tint2 > 0) // make sure we got some data 47 | { 48 | printf("\nBUFF: "); 49 | for (tint3=0; tint3datalength; tint3++) 50 | printf("%02X", tempbuffer->dataptr[tint3]); 51 | printf("\n"); 52 | tval = netBufferRemoveInt32(tempbuffer); 53 | printf("int32: %d\n", tval); 54 | netBufferRemoveString(buffervalstring, tempbuffer); 55 | printf("string: %s\n", buffervalstring); 56 | tval = netBufferRemoveInt32(tempbuffer); 57 | printf("int32: %d\n", tval); 58 | tval2 = netBufferRemoveInt16(tempbuffer); 59 | printf("int16: %d\n", tval2); 60 | printf("int32: %d\n", netBufferRemoveInt32(tempbuffer)); 61 | } 62 | else 63 | { 64 | printf("\nNo data?"); 65 | // break; // if the netRecvBuffer failed then break out to the netDisconnect 66 | } 67 | } 68 | netDisconnect(tempsocket); // Issue here. We disconnect twice if the server dies early as netRecvBuffer does cleanup on broken connections. 69 | } 70 | 71 | netStop(); // Stop the netLib library 72 | 73 | printf("\n"); 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /bufferserver.c: -------------------------------------------------------------------------------- 1 | /* 2 | bufferserver.c - Module file for Test Buffer Server demo using netLib 3 | v0.4 - 2007.08.30 4 | Coded by Ian Seyler (iseyler@gmail.com) 5 | http://bubbai.ath.cx/projects/netlib/ 6 | Copyright (c) 2007 Ian Seyler. All Rights Reserved. 7 | Distributed under the terms of the MIT License. 8 | */ 9 | 10 | 11 | #include "netSocket.h" 12 | #include "netBuffer.h" 13 | 14 | #define MAXCONCURRENTCLIENTS 3 15 | 16 | int main() 17 | { 18 | int tint, tint3, step = 60, freeclient = -1; 19 | netSocket *clientsocket[MAXCONCURRENTCLIENTS]; 20 | netSocket *tempsocket; // YOU MUST INITIALIZE ALL SOCKETS BEFORE USING THEM!! 21 | netSocket *listensocket; 22 | netBuffer *tempbuffer; // YOU MUST INITIALIZE ALL BUFFERS BEFORE USING THEM!! 23 | char *netBuff; 24 | char netBuffData[128]; 25 | unsigned char rawdata[4] = {0xBA, 0xBE, 0x0D, 0xAD}; 26 | char message[]="Sample test string."; 27 | netBuff = netBuffData; 28 | 29 | printf("Buffer Server demo for netLib v0.4\n"); 30 | 31 | netInit(); // Start the netLib library 32 | 33 | for(tint=0; tintdata[0] = step++; // increment the message 48 | 49 | // listen for new connections and accept them if there is room 50 | if (netIsDataPending(listensocket) == 1) 51 | { 52 | for(tint=0; tintinuse == 0) 55 | { 56 | freeclient = tint; 57 | break; // get out of the for loop... we have the freeclient token 58 | } 59 | } 60 | 61 | if (freeclient != -1) // There is a valid free connection.. use it! 62 | { 63 | netAccept(listensocket, clientsocket[freeclient]); 64 | printf(" --> Client is %d", tint+1); 65 | freeclient = -1; // clear the token 66 | } 67 | else // No more connection.. kick them off 68 | { 69 | printf("\nNo more free connections."); 70 | netAccept(listensocket, tempsocket); // accept and disconnect the socket 71 | // Do something here??? 72 | netDisconnect(tempsocket); 73 | } 74 | } // we are done listening here 75 | 76 | // Update current clients 77 | for(tint=0; tintinuse == 1) 80 | { 81 | netBufferClear(tempbuffer); 82 | netBufferAppendInt32(tempbuffer, 16909060); 83 | netBufferAppendString(tempbuffer, message); 84 | netBufferAppendInt32(tempbuffer, 2147483647); 85 | netBufferAppendInt16(tempbuffer, 32768); 86 | netBufferAppendInt32(tempbuffer, 87654321); 87 | netBufferAppendData(tempbuffer, rawdata, 4); 88 | netSendBuffer(clientsocket[tint], tempbuffer); // NetSendBuffer will do the cleaning if there is an error. 89 | printf("\nBUFF: "); 90 | for (tint3=0; tint3datalength; tint3++) 91 | printf("%02X", tempbuffer->dataptr[tint3]); 92 | } 93 | } 94 | // done updating the current clients 95 | 96 | } 97 | 98 | netDisconnect(listensocket); 99 | 100 | netStop(); // Stop the netLib library 101 | 102 | printf("\n"); 103 | return 0; 104 | } 105 | -------------------------------------------------------------------------------- /chat.c: -------------------------------------------------------------------------------- 1 | /* 2 | chat.c - Module file for Chat Client using netLib 3 | v0.2 - 2007.08.30 4 | Coded by Ian Seyler (iseyler@gmail.com) 5 | http://bubbai.ath.cx/ 6 | Copyright (c) 2007 Ian Seyler. All Rights Reserved. 7 | Distributed under the terms of the MIT License. 8 | */ 9 | 10 | 11 | #include "netSocket.h" 12 | #include "netBuffer.h" 13 | #include "chat.h" 14 | 15 | void printhelp(); 16 | 17 | int main(int argc, char *argv[]) 18 | { 19 | int tint, chatmode, returnval; 20 | char tempstring[100]; 21 | char tempmessage[2048]; 22 | char nickname[9]; // 8 chars plus a null 23 | char message[MessageSize]; 24 | netSocket *serverSocket; 25 | netBuffer *chatBuffer; 26 | printf("Chat v0.2 (A demo using netLib)\n"); 27 | printf("Designed and coded by Ian Seyler\n"); 28 | 29 | if (argc <= 2) 30 | { 31 | printhelp(); 32 | exit(1); 33 | } 34 | else if (argc > 3) 35 | { 36 | printf("\nToo many args"); 37 | exit(1); 38 | } 39 | 40 | if (argv[2][1] == 'l' || argv[2][1] == 'L') // Listen 41 | { 42 | chatmode = 0; 43 | } 44 | else if (argv[2][1] == 's' || argv[2][1] == 'S') // Speak 45 | { 46 | chatmode = 1; 47 | } 48 | else 49 | { 50 | printf("\nInvalid Arguement\n"); 51 | exit(1); 52 | } 53 | 54 | netInit(); 55 | serverSocket = netInitSocket(); 56 | chatBuffer = netInitBuffer(MessageSize); 57 | 58 | if (chatmode == 0) // Listen mode 59 | { 60 | printf("\n\nListen mode"); 61 | printf("\n\nConnecting to chat server..."); 62 | if (netConnect(serverSocket, argv[1], ChatPort) == netOK) 63 | { 64 | printf(" OK!\n\n"); 65 | netSend(serverSocket, "0", 1); // tell the server we want listen mode 66 | while(1) 67 | { 68 | netBufferClear (chatBuffer); 69 | returnval = netRecvBuffer(serverSocket, chatBuffer); 70 | if (returnval > 0 && chatBuffer->complete == 1) 71 | { 72 | printf("%s\n", chatBuffer->dataptr); 73 | // for (tint=0; tintdatalength+1; tint++) 74 | // printf("%d ", chatBuffer->data[tint]); 75 | } 76 | else if (returnval < 0) 77 | { 78 | printf("\nDisconnected from chat server.\n"); 79 | netStop(); 80 | exit(1); // error 81 | } 82 | } 83 | } 84 | else 85 | { 86 | printf("\nCould not connect to server.\n"); 87 | netStop(); 88 | exit(1); 89 | } 90 | } 91 | else if (chatmode == 1) // Speak mode 92 | { 93 | printf("\n\nSpeak mode"); 94 | printf("\n\nEnter your nickname (Max 8 chars): "); 95 | fgets(tempstring, 80, stdin); // only read in 80 chars at a time 96 | fflush(stdin); // flush the rest of the keystrokes that are waiting in stdin 97 | tempstring[strlen(tempstring)-1] = '\0'; // get rid of the new line character 98 | strncpy(nickname, tempstring, 8); 99 | nickname[8] = '\0'; 100 | printf("Your nickname is '%s'", nickname); 101 | 102 | printf("\n\nConnecting to chat server..."); 103 | if (netConnect(serverSocket, argv[1], ChatPort) == netOK) 104 | { 105 | returnval = netSend(serverSocket, "1", 1); // tell the server we want speak mode 106 | returnval = netSend(serverSocket, nickname, 9); 107 | printf(" OK!\n\n"); 108 | } 109 | else 110 | { 111 | printf("\nCould not connect to server.\n"); 112 | netStop(); 113 | exit(1); 114 | } 115 | 116 | while(1) 117 | { 118 | printf("Say: "); 119 | fgets(tempstring, 80, stdin); // only read in 80 chars at a time 120 | fflush(stdin); // flush the rest of the keystrokes that are waiting in stdin 121 | tempstring[strlen(tempstring)-1] = '\0'; // get rid of the new line character 122 | if (tempstring[0] == '/' && (tempstring[1] == 'q' || tempstring[1] == 'Q')) // exit the loop 123 | break; 124 | 125 | netBufferClear (chatBuffer); 126 | memset(tempmessage, '\0', sizeof(tempmessage)); 127 | 128 | strncpy(tempmessage, nickname, strlen(nickname)); 129 | memset(tempmessage+strlen(nickname), ' ', 8-strlen(nickname)); // pad the nick with spaces 130 | strncat(tempmessage, ": ", 2); 131 | strncat(tempmessage, tempstring, (MessageSize - 10)); // 128 - 10 for nickname 132 | 133 | netBufferAppendString (chatBuffer, tempmessage); 134 | 135 | if(netSendBuffer(serverSocket, chatBuffer) <= 0) 136 | { 137 | printf("\nDisconnected from chat server.\n"); 138 | netStop(); 139 | exit(1); 140 | } 141 | } 142 | } 143 | else // No mode was chosen 144 | { 145 | printf("\nProgram error. Mode not set.\n"); 146 | netStop(); 147 | exit(1); 148 | } 149 | 150 | printf("\nDisconnected from chat server.\n"); 151 | 152 | netDisconnect(serverSocket); 153 | 154 | netStop(); 155 | 156 | return 0; 157 | } 158 | 159 | void printhelp() 160 | { 161 | printf("\nUsage: chat hostname [-listen or -speak]\n"); 162 | } 163 | -------------------------------------------------------------------------------- /chat.h: -------------------------------------------------------------------------------- 1 | /* 2 | chat.h - Global header file for Chat and Chatserver 3 | v0.2 - 2007.08.30 4 | Coded by Ian Seyler (iseyler@gmail.com) 5 | http://bubbai.ath.cx/ 6 | Copyright (c) 2007 Ian Seyler. All Rights Reserved. 7 | Distributed under the terms of the MIT License. 8 | */ 9 | 10 | 11 | #include // printf 12 | #include // malloc 13 | #include // memset 14 | 15 | #define ChatPort 8192 16 | #define MessageSize 128 17 | #define MaxConcurrentClients 10 18 | -------------------------------------------------------------------------------- /chatserver.c: -------------------------------------------------------------------------------- 1 | /* 2 | chatserver.c - Module file for Chatserver using netLib 3 | v0.2 - 2007.08.30 4 | Coded by Ian Seyler (iseyler@gmail.com) 5 | http://bubbai.ath.cx/ 6 | Copyright (c) 2007 Ian Seyler. All Rights Reserved. 7 | Distributed under the terms of the MIT License. 8 | */ 9 | 10 | 11 | #include "netSocket.h" 12 | #include "netBuffer.h" 13 | #include "chat.h" 14 | 15 | int main() 16 | { 17 | int tint, tint2, freeclient = -1, returnval, loopcounter = 0, tval; 18 | netSocket *clientsocket[MaxConcurrentClients]; 19 | netBuffer *clientbuffer[MaxConcurrentClients]; 20 | int clientsockettype[MaxConcurrentClients]; 21 | char clientnick[MaxConcurrentClients][9]; 22 | netSocket *tempsocket; // YOU MUST INITIALIZE ALL SOCKETS BEFORE USING THEM!! 23 | netSocket *listensocket; 24 | netBuffer *tempbuffer; // YOU MUST INITIALIZE ALL BUFFERS BEFORE USING THEM!! 25 | char *netBuff; 26 | char netBuffData[MessageSize]; 27 | char tempmessage[2048]; 28 | netBuff = netBuffData; 29 | 30 | printf("Chat Server v0.2 (A demo using netLib)\n"); 31 | printf("Designed and coded by Ian Seyler\n"); 32 | 33 | netInit(); // Start the netLib library 34 | 35 | for(tint=0; tintinuse = 0; 40 | clientsockettype[tint] = -1; 41 | } 42 | tempsocket = netInitSocket(); // initiate the socket 43 | listensocket = netInitSocket(); // initiate the socket 44 | tempbuffer = netInitBuffer(MessageSize); // create a buffer 45 | 46 | netListen(listensocket, ChatPort); // Set the server to listen 47 | 48 | printf("\n"); 49 | 50 | // Main program loop 51 | for (;;) 52 | { 53 | // Listen for new connections and accept them if there is room 54 | if (netIsDataPending(listensocket) == 1) 55 | { 56 | printf("\nGot a connection."); 57 | for(tint=0; tintinuse == 0) 60 | { 61 | freeclient = tint; 62 | break; // get out of the for loop... we have the freeclient token 63 | } 64 | } 65 | 66 | if (freeclient != -1) // There is a valid free connection.. use it! 67 | { 68 | netAccept(listensocket, clientsocket[freeclient]); 69 | printf(" Client is %d", tint+1); 70 | netRecv(clientsocket[freeclient], netBuff, 1); 71 | if (netBuff[0] == '0') 72 | { 73 | printf(" --> Listen mode"); 74 | clientsockettype[freeclient] = 0; 75 | } 76 | else if (netBuff[0] == '1') 77 | { 78 | printf(" --> Speak mode"); 79 | memset(netBuff, '\0', sizeof(netBuff)); 80 | for (tint=0; tint<3; tint++) // loop here three times in case of a slow client connection 81 | { 82 | returnval = netRecv(clientsocket[freeclient], clientnick[freeclient], 9); // get the name 83 | if (returnval == 9) 84 | tint = 1000000; // one meeeellion 85 | } 86 | if (returnval != 9) // the client is corrupt 87 | { 88 | printf(" --> Corrupt client"); 89 | netDisconnect(clientsocket[freeclient]); 90 | } 91 | else // we have a good client 92 | { 93 | clientsockettype[freeclient] = 1; 94 | printf(" : %s.", clientnick[freeclient]); 95 | memset(tempmessage, '\0', sizeof(tempmessage)); 96 | strcpy(tempmessage, "CHANSERV: "); 97 | strcat(tempmessage, clientnick[freeclient]); 98 | strcat(tempmessage, " has joined the chat."); 99 | netBufferClear (tempbuffer); 100 | netBufferAppendString (tempbuffer, tempmessage); 101 | 102 | printf(" Sending global message."); 103 | for(tint=0; tintinuse == 1 && clientsockettype[tint] == 0) 106 | if (netSendBuffer(clientsocket[tint], tempbuffer) <= 0) 107 | clientsockettype[tint] = -1; 108 | } 109 | } 110 | } 111 | else // The other end is not a chat client. 112 | { 113 | printf(" --> Corrupt client"); 114 | netDisconnect(clientsocket[freeclient]); 115 | } 116 | freeclient = -1; // clear the token 117 | } 118 | else // No more connection.. kick them off 119 | { 120 | printf(" No more free connections."); 121 | netAccept(listensocket, tempsocket); // accept and disconnect the socket 122 | netSend(tempsocket, "Server message: No free connections. Please try again later.\0", MessageSize); // send an error message 123 | netDisconnect(tempsocket); 124 | } 125 | } 126 | // we are done listening here 127 | 128 | // Update current clients 129 | for(tint=0; tintcomplete == 1) 132 | { 133 | printf(" Sending message to clients."); 134 | for(tint2=0; tint2inuse == 1 && clientsockettype[tint2] == 0) 137 | { 138 | if (netSendBuffer(clientsocket[tint2], clientbuffer[tint]) <= 0) 139 | clientsockettype[tint2] = -1; 140 | } 141 | } 142 | clientbuffer[tint]->complete = 0; 143 | } 144 | } 145 | // done updating the current clients 146 | 147 | netBufferClear (tempbuffer); 148 | 149 | // Check the speaking clients 150 | for(tint=0; tintinuse == 1 && clientsockettype[tint] == 1) 153 | { 154 | returnval = netRecvBuffer(clientsocket[tint], clientbuffer[tint]); 155 | if (returnval < 0) // the client has disconnected 156 | { 157 | memset(tempmessage, '\0', sizeof(tempmessage)); 158 | strcpy(tempmessage, "CHANSERV: "); 159 | strcat(tempmessage, clientnick[tint]); 160 | strcat(tempmessage, " has left the chat."); 161 | netBufferClear (clientbuffer[tint]); 162 | netBufferAppendString (clientbuffer[tint], tempmessage); 163 | clientbuffer[tint]->complete = 1; 164 | printf("\nMessage received from client %d.", tint+1); 165 | } 166 | else if (returnval > 0) // the client is sending a message 167 | { 168 | if (clientbuffer[tint]->complete == 1) // we have a whole message 169 | printf("\nMessage received from client %d.", tint+1); 170 | } 171 | } 172 | } 173 | // done updating the current clients 174 | } 175 | 176 | netDisconnect(listensocket); 177 | 178 | netStop(); // Stop the netLib library 179 | 180 | printf("\n"); 181 | return 0; 182 | } 183 | -------------------------------------------------------------------------------- /docs/changelog.txt: -------------------------------------------------------------------------------- 1 | Change Log for netLib Network Communication Library 2 | --------------------------------------------------- 3 | 4 | v0.4 - 20070830 5 | -major rework of how netBuffers are used. netBuffers can now store binary information that can be sent between different computer platforms (Endian issues) 6 | -added netBufferAppendInt8, netBufferAppendInt16, netBufferAppendInt32, netBufferAppendString, netBufferAppendData, netBufferRemoveInt8, netBufferRemoveInt16, netBufferRemoveInt32, netBufferRemoveString, netBufferRemoveData, and netBufferClear functions. 7 | -separate source files for netSockets (basic functions like connect, listen, accept, send, receive, etc.) and netBuffers (sendbuffer, recvbuffer, appends, removes) 8 | -Thanks to Brad Fewster for offering tips on a few parts of netLib. "if" statements were altered as well as variable passing to some functions based on his advice 9 | -added netSetOption function 10 | -found the command line option to allow for correct functionality in BeOS BONE 11 | -miscellaneous cleanup of code 12 | 13 | v0.3 - 20070626 14 | -fixed bug in netConnect on Unix. setsockint was not declared as a variable 15 | -disable the Nagle algorithm by default in netConnect and netAccept 16 | -changed all library messages to print to stderr instead of stdout 17 | -added a return value to the netSocket structure. netSock->retval will contain the return value of the last netLib fuction that was called on it 18 | -added a complete value to the netBuffer structure. netBuff->complete will contain 1 if the whole buffer has been sent/received 19 | -change to netRecvBuffer so we can not get stuck waiting for more data 20 | -fixed an issue with netIsSocketWaiting as it was not interpreting the return value propery 21 | -renamed netIsSocketWaiting to netIsDataPending. The function name is a bit clearer now 22 | -removed netSelect function. Should be using netIsDataPending instead 23 | -added a chat demo 24 | -miscellaneous cleanup of code 25 | 26 | v0.2 - 20070424 27 | -use errno values from operating system 28 | -added timeout value to netSocket structure 29 | -added netIsSocketWaiting function, quick version of netSelect 30 | -added netSetTimeout function to set timeout on a netSocket 31 | -change: netRecv, netRecvBuffer, and netAccept use netIsSocketWaiting 32 | -added global verbose option for library 33 | -bug fix in netListen. Internal call to setsockopt was not working correctly in Windows 34 | -fixed a small bug in netSendBuffer and netRecvBuffer. At was not being reset in the case of a failed transfer 35 | -fixed an issue on linux when doing a send(). In v0.1 SIGPIPE was still being tripped. Tested with Ubuntu 7.04 36 | -added SIGPIPE protection in netConnect for Mac OS X 37 | -miscellaneous cleanup of code 38 | 39 | v0.1 - 20070227 40 | -Initial public release 41 | -------------------------------------------------------------------------------- /docs/images/important.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IanSeyler/netLib/e2b1801e29a14c46a35a5caa6d900d79a09c2c31/docs/images/important.png -------------------------------------------------------------------------------- /docs/images/no.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IanSeyler/netLib/e2b1801e29a14c46a35a5caa6d900d79a09c2c31/docs/images/no.png -------------------------------------------------------------------------------- /docs/images/yes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IanSeyler/netLib/e2b1801e29a14c46a35a5caa6d900d79a09c2c31/docs/images/yes.png -------------------------------------------------------------------------------- /docs/manual.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IanSeyler/netLib/e2b1801e29a14c46a35a5caa6d900d79a09c2c31/docs/manual.html -------------------------------------------------------------------------------- /docs/style.css: -------------------------------------------------------------------------------- 1 | /* Default Stylesheet for bubbai.ath.cx */ /* >>> ELEMENTS <<< */ * { margin: 0; padding: 0; } body { color: #222; background-color: #f5f5f5; font-family: Verdana, "Arial", "Tahoma", "MS Sans Serif", sans-serif; text-align: center; } h1 { font-size: 200%; } h2 { font-size: 180%; } h3 { font-size: 160%; } h4 { font-size: 140%; } h5 { font-size: 120%; } h6 { font-size: 80%; } h2 { color: #225588; } h3 { color: #336699; } h4 { color: #4477AA; } color: #222; /* >>> CONTAINERS <<< */ div#print { display: none; } div#container { margin: 10px; text-align: left; } div#header-wrap { margin: 8px 0; } div#header-in { padding: 10px; color: inherit; background-color: #fff; border: solid #eee; border-width: 0 2px 2px 0; } div#content-wrap { } div#center { color: inherit; background-color: #fff; border: solid #eee; border-width: 0 2px 2px 0; } div#center-in { padding: 20px; } div#footer-wrap { clear: both; } div#footer-in { } /* >>> SUB CONTAINERS <<< */ * { } /* >>> LISTS <<< */ ul#nav-center { margin: 0 0 10px 0; padding: 0 0 10px 0; list-style: none; border-bottom: 1px solid #ddd; font-size: 80%; } ul#nav-center li { display: inline; } ul#nav-center li a { margin: 0 6px; padding: 0px 1px; color: #444; background-color: #F0F0F0; text-decoration: none; border: 1px solid #E0E0E0; } ul#nav-center li a:hover { background-color: #E0E0E0; border: 1px solid #D0D0D0; } ul#nav-center li-selected a { margin: 0 6px; padding: 0px 1px; color: #333; background-color: #D0D0D0; text-decoration: none; border: 1px solid #B0B0B0; } ul#nav-center li-selected a:hover { background-color: #E0E0E0; border: 1px solid #C0C0C0; } ul#nav-center-lower { margin: 0 0 10px 0; padding: 0 0 10px 0; list-style: none; border-bottom: 1px solid #eee; font-size: 80%; } ul#nav-center-lower li { display: inline; } ul#nav-center-lower li a { margin: 0 6px; padding: 0px 1px; color: #444; background-color: #F0F0F0; text-decoration: none; border: 1px solid #E0E0E0; } ul#nav-center-lower li a:hover { background-color: #E0E0E0; border: 1px solid #D0D0D0; } ul#nav-center-lower li-selected a { margin: 0 6px; padding: 0px 1px; color: #333; background-color: #D0D0D0; text-decoration: none; border: 1px solid #B0B0B0; } ul#nav-center-lower li-selected a:hover { background-color: #E0E0E0; border: 1px solid #C0C0C0; } /* Settings for the top navigation panel */ ul#nav-top { float: right; padding: 1px 0; list-style: none; font-size: 80%; } ul#nav-top li { display: inline; } ul#nav-top li a { margin: 0 4px; padding: 0px 1px; color: #444; background-color: #F0F0F0; text-decoration: none; border: 1px solid #E0E0E0; } ul#nav-top li a:hover { background-color: #E0E0E0; border: 1px solid #D0D0D0; } ul#nav-top li-selected a { margin: 0 4px; padding: 0px 1px; color: #333; background-color: #D0D0D0; text-decoration: none; border: 1px solid #B0B0B0; } ul#nav-top li-selected a:hover { background-color: #E0E0E0; border: 1px solid #C0C0C0; } /* Settings for footer */ ul#nav-footer { padding: 0 2px; color: #aaa; background-color: inherit; font-size: 80%; list-style: none; text-align: left; } ul.list { margin: 0px 24px; line-height: 24px; color: #222; } .code { color: #222; background-color: #E3EEFF; border: 1px solid #C3D9FF; padding: 1px; } .codeheader { color: #444; background-color: #E3FFEE; border: 1px solid #C0F0D0; padding: 1px; } .console { color: #333; background-color: #DDD; border: 1px solid #BBB; padding: 1px; } /* >>> TYPOGRAPHY <<< */ *.x { display: none; } div#header-wrap h1 { padding: 10px; font-size: 200%; } div#center p { margin: 5px 0 5px 0; color: #444; background-color: inherit; font-size: 90%; line-height: 20px; } p a, ul.list a { color: #3F4C6B; background-color: inherit; text-decoration: none; border-bottom: 1px solid #F1F7FF; } p a:hover, ul.list a:hover { color: #333; background-color: #EEEEFF; border-bottom: 1px solid #eee; } /* >>> FORMS <<< */ * { } /* >>> TABLES <<< */ table a, table a:link, table a:visited { border:none; } table { width:80%; border-top:1px solid #e5eff8; border-right:1px solid #e5eff8; margin:1em auto; border-collapse:collapse; } tr.odd td { background:#f7fbff } tr.odd .column1 { background:#f4f9fe; } .column1 { background:#f9fcfe; } td { color:#678197; border-bottom:1px solid #e5eff8; border-left:1px solid #e5eff8; padding:.3em 1em; text-align:center; } th { color: #678197; text-align:left; border-bottom: 1px solid #e5eff8; border-left:1px solid #e5eff8; padding:.3em 1em; } thead th { background:#f4f9fe; text-align:center; color:#66a3d3 } /* >>> END <<< */ -------------------------------------------------------------------------------- /echoserver.c: -------------------------------------------------------------------------------- 1 | /* 2 | echoserver.c - Module file for Echo Server demo using netLib 3 | v0.4 - 2007.08.30 4 | Coded by Ian Seyler (iseyler@gmail.com) 5 | http://bubbai.ath.cx/projects/netlib/ 6 | Copyright (c) 2007 Ian Seyler. All Rights Reserved. 7 | Distributed under the terms of the MIT License. 8 | */ 9 | 10 | 11 | #include "netSocket.h" 12 | 13 | int main() 14 | { 15 | int tint; 16 | netSocket *clientsocket, *listensocket; 17 | char tempbuffer[1]; 18 | 19 | printf("Echo Server demo for netLib v0.4\n"); 20 | 21 | netInit(); // Start the netLib library 22 | 23 | clientsocket = netInitSocket(); // Initiate the socket 24 | listensocket = netInitSocket(); 25 | 26 | netListen(listensocket, 8192); // Set the server to listen on port 8192 27 | 28 | printf("\n\n"); 29 | 30 | // Main program loop 31 | for (;;) 32 | { 33 | if (netAccept(listensocket, clientsocket) > 0) // A client has connected! 34 | { 35 | for (;;) 36 | { 37 | tint = netRecv(clientsocket, tempbuffer, 1); // Get a byte from the client 38 | if (tint > 0) 39 | { 40 | printf("\nGot %c", tempbuffer[0]); // Print the char we got 41 | netSend(clientsocket, tempbuffer, 1); // Send it back to the client 42 | } 43 | else if (tint == -1) 44 | { 45 | printf("\n"); 46 | break; 47 | } 48 | } 49 | } 50 | else 51 | { 52 | printf("."); // Prints this while waiting for a client 53 | } 54 | } 55 | 56 | netDisconnect(listensocket); 57 | 58 | netStop(); // Stop the netLib library 59 | 60 | printf("\n"); 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /netBuffer.c: -------------------------------------------------------------------------------- 1 | /* 2 | netBuffer.c - Module file for netLib Network Communication Library (Buffers) 3 | v0.4 - 2007.08.30 4 | Coded by Ian Seyler (iseyler@gmail.com) 5 | http://bubbai.ath.cx/projects/netlib/ 6 | Copyright (c) 2007 Ian Seyler. All Rights Reserved. 7 | Distributed under the terms of the MIT License. 8 | */ 9 | 10 | 11 | #include "netBuffer.h" 12 | 13 | 14 | /*========================================================* 15 | * Function : netInitBuffer() 16 | * Purpose : Initiate a new netBuffer. 17 | * Entry : int size = The size in bytes of the buffer 18 | * Returns : a pointer to a netBuffer, NULL on error 19 | *========================================================*/ 20 | 21 | netBuffer* netInitBuffer (int size) 22 | { 23 | netBuffer *netBuff; 24 | 25 | #if nlVerbose >= 1 26 | fprintf(stderr, "\nnetLib: InitBuffer"); 27 | #endif 28 | 29 | if (size > netMaxBufferSize) 30 | { 31 | #if nlVerbose >= 1 32 | fprintf(stderr, ", Error! (Buffer over set size limit)"); 33 | #endif 34 | return NULL; 35 | } 36 | 37 | netBuff = malloc(sizeof(netBuffer)); 38 | if (NULL == netBuff) 39 | { 40 | #if nlVerbose >= 1 41 | fprintf(stderr, ", Error! (Allocating Pointer Buffer)"); 42 | #endif 43 | return NULL; 44 | } 45 | else 46 | { 47 | memset(netBuff, '\0', sizeof(netBuffer)); // zero the entire structure 48 | netBuff->data = malloc(size+2); // add two since datalength is at begining of buffer 49 | if (NULL == netBuff->data) 50 | { 51 | #if nlVerbose >= 1 52 | fprintf(stderr, ", Error! (Allocating Data Buffer)"); 53 | #endif 54 | free(netBuff); // We couln't get enough memory for the data buffer so free what we have used so far. 55 | return NULL; 56 | } 57 | else 58 | { 59 | netBuff->size = size; // set the size for buffer data 60 | memset(netBuff->data, '\0', size+2); // zero the data structure 61 | netBuff->lenptr = netBuff->data; 62 | netBuff->dataptr = netBuff->data + 2; 63 | return netBuff; 64 | } 65 | } 66 | } 67 | 68 | 69 | /*========================================================* 70 | * Function : netSendBuffer() 71 | * Purpose : Send data from a netBuffer to a netSocket. 72 | * Entry : netSocket *netSock = The socket to send to 73 | * netBuffer *netBuff = The buffer to be sent out 74 | * Returns : number of bytes that were sent, -1 on error 75 | *========================================================*/ 76 | 77 | int netSendBuffer (netSocket *netSock, netBuffer *netBuff) 78 | { 79 | int byte_count = 0; 80 | int bytes_sent = 0; // keep track of how many bytes have been sent in this run 81 | int bytes_left = (netBuff->datalength+2) - netBuff->readAt; 82 | short temp = htons(netBuff->datalength); 83 | #if nlVerbose >= 2 84 | int verbosetint; 85 | #endif 86 | 87 | #if nlVerbose >= 1 88 | fprintf(stderr, "\nnetLib: Send Buffer"); 89 | #endif 90 | 91 | #if nlVerbose >= 2 92 | fprintf(stderr, "\nSENDBUFF: "); 93 | for (verbosetint=0; verbosetintdatalength; verbosetint++) 94 | fprintf(stderr, "%02X", netBuff->dataptr[verbosetint]); 95 | #endif 96 | 97 | memcpy(&netBuff->data[0], (char*)&temp, 2); 98 | 99 | while(bytes_sent < netBuff->datalength+2) // keep going until the buffer has been sent 100 | { 101 | #ifdef MSG_NOSIGNAL // Stop SIGPIPE errors in Linux 102 | byte_count = send(netSock->number, netBuff->data+bytes_sent, bytes_left, MSG_NOSIGNAL); 103 | #else 104 | byte_count = send(netSock->number, netBuff->data+bytes_sent, bytes_left, 0); 105 | #endif 106 | 107 | #if nlVerbose >= 1 108 | fprintf(stderr, ", transfered %d bytes", byte_count); 109 | #endif 110 | 111 | if (0 >= byte_count) 112 | { 113 | #if nlVerbose >= 1 114 | printf (", Connection closed"); 115 | #if nlVerbose >= 2 116 | #ifdef MS_WINDOWS 117 | fprintf(stderr, ", ERRNO = %d", WSAGetLastError()); 118 | #else 119 | fprintf(stderr, ", ERRNO = %d (%s)", errno, strerror(errno)); 120 | #endif 121 | #endif 122 | #endif 123 | netDisconnect(netSock); // Since the connection has closed we can disconnect it 124 | netBuff->readAt = 0; // Transfer has failed. Reset at for next call of netSendBuffer 125 | netBuff->complete = 0; 126 | netSock->retval = -1; 127 | return -1; 128 | } 129 | else 130 | { 131 | bytes_sent += byte_count; 132 | netBuff->readAt += byte_count; // keep track of where we are in the buffer 133 | bytes_left -= byte_count; 134 | #if nlVerbose >= 1 135 | if (bytes_sent < netBuff->datalength+2) 136 | fprintf(stderr, ", waiting to send %d bytes", bytes_left); 137 | #endif 138 | } 139 | } 140 | 141 | if (netBuff->readAt == netBuff->datalength+2) // We sent everything we need.. reset at and set complete 142 | { 143 | #if nlVerbose >= 1 144 | fprintf(stderr, ", complete!"); 145 | #endif 146 | netBuff->readAt = 0; 147 | netBuff->complete = 1; 148 | } 149 | 150 | netSock->retval = bytes_sent; 151 | return bytes_sent; 152 | } 153 | 154 | 155 | /*========================================================* 156 | * Function : netRecvBuffer() 157 | * Purpose : Receive data from a netSocket to a netBuffer. 158 | * Entry : netSocket *netSock = The socket to receive from 159 | * netBuffer *netBuff = The buffer where the incoming data will be stored 160 | * Returns : number of bytes that were received, -1 on error 161 | *========================================================*/ 162 | 163 | int netRecvBuffer (netSocket *netSock, netBuffer *netBuff) 164 | { 165 | int byte_count = 0; 166 | int size = 0; 167 | short length = 0; 168 | int bytes_recv = 0; // keep track of how many bytes have been received in this run 169 | int bytes_left = netBuff->datalength - netBuff->readAt; 170 | short temp = 0; 171 | #if nlVerbose >= 2 172 | int verbosetint; 173 | #endif 174 | 175 | #if nlVerbose >= 1 176 | fprintf(stderr, "\nnetLib: Receive Buffer"); 177 | #endif 178 | 179 | #if nlVerbose >= 2 180 | fprintf(stderr, "\nRECVBUFF: "); 181 | for (verbosetint=0; verbosetintdatalength; verbosetint++) 182 | fprintf(stderr, "%02X", netBuff->dataptr[verbosetint]); 183 | #endif 184 | 185 | if(1 < netIsDataPending(netSock)) 186 | { 187 | #if nlVerbose >= 1 188 | fprintf(stderr, ", nothing is pending"); 189 | #endif 190 | netSock->retval = 0; 191 | return 0; 192 | } 193 | 194 | if (0 == netBuff->readAt) 195 | { 196 | netBuff->complete = 0; 197 | 198 | byte_count = recv(netSock->number, (void *)&temp, 2, 0); 199 | if (0 >= byte_count) 200 | { 201 | #if nlVerbose >= 1 202 | printf (", Connection closed"); 203 | #if nlVerbose >= 2 204 | #ifdef MS_WINDOWS 205 | fprintf(stderr, ", ERRNO = %d", WSAGetLastError()); 206 | #else 207 | fprintf(stderr, ", ERRNO = %d (%s)", errno, strerror(errno)); 208 | #endif 209 | #endif 210 | #endif 211 | netDisconnect(netSock); // Since the connection has closed we can disconnect it 212 | netBuff->readAt = 0; // Transfer has failed. Reset at for next call of netRecvBuffer 213 | netBuff->complete = 0; 214 | netSock->retval = -1; 215 | return -1; 216 | } 217 | 218 | length = ntohs(temp); 219 | if (length > netBuff->size) 220 | { 221 | return -1; // MAJOR ERROR.. we got a packet larger then we can hold. 222 | printf("MAJOR ERROR!\n"); 223 | } 224 | 225 | netBuff->datalength = length; 226 | } 227 | 228 | bytes_left = length - netBuff->readAt; 229 | 230 | while(0 != bytes_left) // keep going until the buffer is full 231 | { 232 | byte_count = recv(netSock->number, netBuff->dataptr+netBuff->readAt, bytes_left, 0); 233 | 234 | #if nlVerbose >= 1 235 | fprintf(stderr, ", transfered %d bytes", byte_count); 236 | #endif 237 | 238 | if (0 >= byte_count) 239 | { 240 | #if nlVerbose >= 1 241 | printf (", Connection closed"); 242 | #if nlVerbose >= 2 243 | #ifdef MS_WINDOWS 244 | fprintf(stderr, ", ERRNO = %d", WSAGetLastError()); 245 | #else 246 | fprintf(stderr, ", ERRNO = %d (%s)", errno, strerror(errno)); 247 | #endif 248 | #endif 249 | #endif 250 | netDisconnect(netSock); // Since the connection has closed we can disconnect it 251 | netBuff->readAt = 0; // Transfer has failed. Reset at for next call of netRecvBuffer 252 | netBuff->complete = 0; 253 | netSock->retval = -1; 254 | return -1; 255 | } 256 | else 257 | { 258 | bytes_recv += byte_count; 259 | netBuff->readAt += byte_count; // keep track of where we are in the buffer 260 | bytes_left -= byte_count; 261 | #if nlVerbose >= 1 262 | if (bytes_recv < netBuff->datalength) 263 | fprintf(stderr, ", waiting to receive %d bytes", bytes_left); 264 | #endif 265 | 266 | if (1 > netIsDataPending(netSock)) 267 | { 268 | if (netBuff->readAt == netBuff->datalength) // We got everything we need.. reset at and set complete 269 | { 270 | netBuff->readAt = 0; 271 | netBuff->complete = 1; 272 | netSock->retval = bytes_recv; 273 | #if nlVerbose >= 1 274 | fprintf(stderr, ", complete!"); 275 | #endif 276 | return bytes_recv; 277 | } 278 | #if nlVerbose >= 1 279 | fprintf(stderr, ", nothing more is pending"); 280 | #endif 281 | netSock->retval = bytes_recv; 282 | return bytes_recv; 283 | } 284 | } 285 | } 286 | 287 | if (netBuff->readAt == netBuff->datalength) // We got everything we need.. reset at and set complete 288 | { 289 | #if nlVerbose >= 1 290 | fprintf(stderr, ", complete!"); 291 | #endif 292 | netBuff->readAt = 0; 293 | netBuff->complete = 1; 294 | } 295 | 296 | netSock->retval = bytes_recv; 297 | return bytes_recv; 298 | } 299 | 300 | 301 | /*========================================================* 302 | * Function : netBufferAppendInt8() 303 | * Purpose : Pack an 8-bit integer into a netBuffer. 304 | * Entry : netBuffer *netBuff = The buffer where the integer data will be stored 305 | * char data = The integer to store 306 | * Returns : 0 on success, -1 on error 307 | *========================================================*/ 308 | 309 | int netBufferAppendInt8 (netBuffer *netBuff, char data) 310 | { 311 | if (netBuff->writeAt >= netBuff->size) 312 | { 313 | return -1; 314 | } 315 | 316 | netBuff->dataptr[netBuff->writeAt] = (char)data; 317 | netBuff->writeAt++; 318 | netBuff->datalength++; 319 | return 0; 320 | } 321 | 322 | 323 | /*========================================================* 324 | * Function : netBufferAppendInt16() 325 | * Purpose : Pack a 16-bit integer into a netBuffer. 326 | * Entry : netBuffer *netBuff = The buffer where the integer data will be stored 327 | * short data = The integer to store 328 | * Returns : 0 on success, -1 on error 329 | *========================================================*/ 330 | 331 | int netBufferAppendInt16 (netBuffer *netBuff, short data) 332 | { 333 | short tshort = htons(data); 334 | char *ptr = (char*)&tshort; 335 | 336 | if (netBuff->writeAt >= netBuff->size) 337 | { 338 | return -1; 339 | } 340 | 341 | memcpy(&netBuff->dataptr[netBuff->writeAt], ptr, 2); 342 | netBuff->writeAt += 2; 343 | netBuff->datalength += 2; 344 | return 0; 345 | } 346 | 347 | 348 | /*========================================================* 349 | * Function : netBufferAppendInt32() 350 | * Purpose : Pack a 32-bit integer into a netBuffer. 351 | * Entry : netBuffer *netBuff = The buffer where the integer data will be stored 352 | * int data = The integer to store 353 | * Returns : 0 on success, -1 on error 354 | *========================================================*/ 355 | 356 | int netBufferAppendInt32 (netBuffer *netBuff, int data) 357 | { 358 | int tint = htonl(data); 359 | char *ptr = (char*)∭ 360 | 361 | if (netBuff->writeAt >= netBuff->size) 362 | { 363 | return -1; 364 | } 365 | 366 | memcpy(&netBuff->dataptr[netBuff->writeAt], ptr, 4); 367 | netBuff->writeAt += 4; 368 | netBuff->datalength += 4; 369 | return 0; 370 | } 371 | 372 | 373 | /*========================================================* 374 | * Function : netBufferAppendString() 375 | * Purpose : Pack a string into a netBuffer. 376 | * Entry : netBuffer *netBuff = The buffer where the string will be stored 377 | * const char *data = The string to store 378 | * Returns : 0 on success, -1 on error 379 | *========================================================*/ 380 | 381 | int netBufferAppendString (netBuffer *netBuff, const char *data) 382 | { 383 | int len; 384 | len = strlen(data); 385 | 386 | if (len > (netBuff->size - netBuff->writeAt)) 387 | { 388 | return -1; 389 | } 390 | strcpy((unsigned char*)netBuff->dataptr+netBuff->writeAt, (unsigned char*)data); 391 | netBuff->writeAt += len+1; 392 | netBuff->datalength += len+1; 393 | 394 | return 0; 395 | } 396 | 397 | 398 | /*========================================================* 399 | * Function : netBufferAppendData() 400 | * Purpose : Pack raw data into a netBuffer. 401 | * Entry : netBuffer *netBuff = The buffer where the data will be stored 402 | * const char *data = The data to store 403 | * int bytes = The number of bytes to store 404 | * Returns : 0 on success, -1 on error 405 | *========================================================*/ 406 | 407 | int netBufferAppendData (netBuffer *netBuff, const char *data, int bytes) 408 | { 409 | if (bytes > (netBuff->size - netBuff->writeAt)) 410 | { 411 | return -1; 412 | } 413 | memcpy(&netBuff->dataptr[netBuff->writeAt], data, bytes); 414 | netBuff->writeAt += bytes; 415 | netBuff->datalength += bytes; 416 | 417 | return 0; 418 | } 419 | 420 | 421 | /*========================================================* 422 | * Function : netBufferRemoveInt8() 423 | * Purpose : Unpack an 8-bit integer from a netBuffer. 424 | * Entry : netBuffer *netBuff = The buffer where the integer is stored 425 | * Returns : the 8-bit integer, -1 on error (not a reliable error number) 426 | *========================================================*/ 427 | 428 | char netBufferRemoveInt8 (netBuffer *netBuff) 429 | { 430 | char tchar; 431 | 432 | if (netBuff->readAt >= netBuff->size) 433 | { 434 | return -1; 435 | } 436 | tchar = netBuff->dataptr[netBuff->readAt]; 437 | netBuff->readAt++; 438 | 439 | return tchar; 440 | } 441 | 442 | 443 | /*========================================================* 444 | * Function : netBufferRemoveInt16() 445 | * Purpose : Unpack a 16-bit integer from a netBuffer. 446 | * Entry : netBuffer *netBuff = The buffer where the integer is stored 447 | * Returns : the 16-bit integer, -1 on error (not a reliable error number) 448 | *========================================================*/ 449 | 450 | short netBufferRemoveInt16 (netBuffer *netBuff) 451 | { 452 | short tshort; 453 | 454 | if (netBuff->readAt >= netBuff->size) 455 | { 456 | return -1; 457 | } 458 | 459 | memcpy(&tshort, &netBuff->dataptr[netBuff->readAt], 2); 460 | netBuff->readAt += 2; 461 | return ntohs(tshort); 462 | } 463 | 464 | 465 | /*========================================================* 466 | * Function : netBufferRemoveInt32() 467 | * Purpose : Unpack a 32-bit integer from a netBuffer. 468 | * Entry : netBuffer *netBuff = The buffer where the integer is stored 469 | * Returns : the 32-bit integer, -1 on error (not a reliable error number) 470 | *========================================================*/ 471 | 472 | int netBufferRemoveInt32 (netBuffer *netBuff) 473 | { 474 | int tint; 475 | 476 | if (netBuff->readAt >= netBuff->size) 477 | { 478 | return -1; 479 | } 480 | 481 | memcpy(&tint, &netBuff->dataptr[netBuff->readAt], 4); 482 | netBuff->readAt += 4; 483 | 484 | return ntohl(tint); 485 | } 486 | 487 | 488 | /*========================================================* 489 | * Function : netBufferRemoveString() 490 | * Purpose : Unpack a string from a netBuffer. 491 | * Entry : char *data = Where the string will be unpacked to 492 | * netBuffer *netBuff = The buffer where the string is stored 493 | * Returns : 0 on success, -1 on error 494 | *========================================================*/ 495 | 496 | int netBufferRemoveString (char *data, netBuffer *netBuff) 497 | { 498 | int tint, strlen = 0; 499 | tint = netBuff->readAt; 500 | 501 | while (netBuff->data[tint] != 0x00) 502 | { 503 | tint++; 504 | strlen++; 505 | } 506 | 507 | strcpy((unsigned char*)data, (unsigned char*)netBuff->dataptr+netBuff->readAt); 508 | netBuff->readAt += strlen-1; 509 | 510 | return 0; 511 | } 512 | 513 | 514 | /*========================================================* 515 | * Function : netBufferRemoveData() 516 | * Purpose : Unpack raw data from a netBuffer. 517 | * Entry : char *data = Where the data will be unpacked to 518 | * netBuffer *netBuff = The buffer where the data is stored 519 | * int bytes = The number of bytes to copy 520 | * Returns : 0 on success, -1 on error 521 | *========================================================*/ 522 | 523 | int netBufferRemoveData (char *data, netBuffer *netBuff, int bytes) 524 | { 525 | memcpy(data, &netBuff->dataptr[netBuff->writeAt], bytes); 526 | 527 | netBuff->readAt += bytes; 528 | 529 | return 0; 530 | } 531 | 532 | 533 | /*========================================================* 534 | * Function : netBufferClear() 535 | * Purpose : Clear a netBuffer. 536 | * Entry : netBuffer *netBuff = The buffer to be cleared 537 | * Returns : 0 on success 538 | *========================================================*/ 539 | 540 | int netBufferClear(netBuffer *netBuff) 541 | { 542 | netBuff->datalength = 0; 543 | netBuff->writeAt = 0; 544 | netBuff->readAt = 0; 545 | memset(netBuff->data, '\0', netBuff->size+2); // zero the data structure 546 | 547 | return 0; 548 | } 549 | -------------------------------------------------------------------------------- /netBuffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | netBuffer.h - Header file for netLib Network Communication Library (Buffers) 3 | v0.4 - 2007.08.30 4 | Coded by Ian Seyler (iseyler@gmail.com) 5 | http://bubbai.ath.cx/projects/netlib/ 6 | Copyright (c) 2007 Ian Seyler. All Rights Reserved. 7 | Distributed under the terms of the MIT License. 8 | */ 9 | 10 | 11 | #include "netSocket.h" 12 | 13 | /* Structure of a netBuffer */ 14 | struct netBufferStruct { 15 | int size; // allocated size in bytes of the buffer 16 | int readAt; // location in buffer where we are currently reading 17 | int writeAt; // location in buffer where we are currently writing 18 | char complete; // set to 1 when we have completed the buffer 19 | short datalength; // the length of the data in the buffer 20 | unsigned char *data; // pointer to the data 21 | unsigned char *lenptr; // pointer to datalength (same as *data) 22 | unsigned char *dataptr; // pointer to the start of the actual data (*data + 2) 23 | }; 24 | 25 | typedef struct netBufferStruct netBuffer; 26 | 27 | #define netMaxBufferSize 4096 28 | 29 | netBuffer* netInitBuffer (int size); //initialize a new netBuffer of a specified size in bytes 30 | 31 | int netSendBuffer (netSocket *netSock, netBuffer *netBuff); // send data to a netSocket (in buffer form) 32 | int netRecvBuffer (netSocket *netSock, netBuffer *netBuff); // receive data from a netSocket (in buffer form) 33 | 34 | int netBufferAppendInt8 (netBuffer *netBuff, char data); // append an 8-bit int to a netBuffer 35 | int netBufferAppendInt16 (netBuffer *netBuff, short data); // append an 16-bit int to a netBuffer 36 | int netBufferAppendInt32 (netBuffer *netBuff, int data); // append an 32-bit int to a netBuffer 37 | int netBufferAppendString (netBuffer *netBuff, const char *data); // append a string to a netBuffer 38 | int netBufferAppendData (netBuffer *netBuff, const char *data, int bytes); // append raw data to a netBuffer 39 | 40 | char netBufferRemoveInt8 (netBuffer *netBuff); // remove an 8-bit int from a netBuffer 41 | short netBufferRemoveInt16 (netBuffer *netBuff); // remove an 16-bit int from a netBuffer 42 | int netBufferRemoveInt32 (netBuffer *netBuff); // remove an 32-bit int from a netBuffer 43 | int netBufferRemoveString (char *data, netBuffer *netBuff); // remove a string from a netBuffer 44 | int netBufferRemoveData (char *data, netBuffer *netBuff, int bytes); // append raw data to a netBuffer 45 | 46 | int netBufferClear (netBuffer *netBuff); // clear a netBuffer 47 | -------------------------------------------------------------------------------- /netSocket.c: -------------------------------------------------------------------------------- 1 | /* 2 | netSocket.c - Module file for netLib Network Communication Library (Main) 3 | v0.4 - 2007.08.30 4 | Coded by Ian Seyler (iseyler@gmail.com) 5 | http://bubbai.ath.cx/projects/netlib/ 6 | Copyright (c) 2007 Ian Seyler. All Rights Reserved. 7 | Distributed under the terms of the MIT License. 8 | */ 9 | 10 | 11 | #include "netSocket.h" 12 | 13 | 14 | /* 15 | Used for setting the verbose mode of the library. 16 | 0 = Silent, 1 = Verbose, 2 = Verbose + Debug 17 | */ 18 | #ifndef nlVerbose 19 | #define nlVerbose 0 20 | #endif 21 | 22 | int nlEndian; // Global variable for the host endian 23 | 24 | 25 | /*========================================================* 26 | * Function : netInit() 27 | * Purpose : Initiate the netLib library. 28 | * Entry : nothing 29 | * Returns : 0 on success, -1 on failure 30 | *========================================================*/ 31 | 32 | int netInit () 33 | { 34 | int endiantest = 1; 35 | 36 | #ifdef MS_WINDOWS 37 | { 38 | fprintf(stderr, "\nnetLib: Start Windows networking"); 39 | WSADATA wsaData; // If WSADATA doesn't work then try WSAData instead. 40 | if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) // Init the WinSock library. 41 | { 42 | fprintf(stderr, ", WSAStartup Error!\n"); 43 | return -1; 44 | } 45 | } 46 | #endif 47 | #ifdef UNIX 48 | fprintf(stderr, "\nnetLib: Start Unix networking"); 49 | #ifdef SIGPIPE 50 | signal(SIGPIPE, SIG_IGN); // This removes "Broken Pipe" errors in BSD 51 | #endif 52 | #endif 53 | #ifdef BEOS 54 | fprintf(stderr, "\nnetLib: Start BeOS networking"); 55 | #endif 56 | fprintf(stderr, " (v0.4)"); // The version of netLib 57 | #if nlVerbose == 1 58 | fprintf(stderr, " - Verbose mode"); 59 | #endif 60 | #if nlVerbose == 2 61 | fprintf(stderr, " - Verbose + Debug mode"); 62 | #endif 63 | 64 | if(1 == *(char *)&endiantest) 65 | nlEndian = 0; // Little endian - Intel 66 | else 67 | nlEndian = 1; // Big endian - PPC 68 | 69 | if (sizeof(int) != 4 && sizeof(short) != 2 && sizeof(char) != 1) 70 | fprintf(stderr, " - Possible buffer errors!"); 71 | 72 | return 0; 73 | } 74 | 75 | 76 | /*========================================================* 77 | * Function : netStop() 78 | * Purpose : Stop the netLib library. 79 | * Entry : nothing 80 | * Returns : 0 on success, -1 on failure 81 | *========================================================*/ 82 | 83 | int netStop () 84 | { 85 | #if nlVerbose >= 1 86 | fprintf(stderr, "\nnetLib: Stop"); 87 | #endif 88 | 89 | #ifdef MS_WINDOWS 90 | { 91 | WSACleanup(); // We are done using the WinSock library. 92 | } 93 | #endif 94 | return 0; 95 | } 96 | 97 | 98 | /*========================================================* 99 | * Function : netInitSocket() 100 | * Purpose : Initiate a new netSocket. 101 | * Entry : nothing 102 | * Returns : a pointer to a netSocket, NULL on error 103 | *========================================================*/ 104 | 105 | netSocket* netInitSocket () 106 | { 107 | netSocket *netSock; 108 | 109 | #if nlVerbose >= 1 110 | fprintf(stderr, "\nnetLib: InitSocket"); 111 | #endif 112 | 113 | netSock = malloc(sizeof(netSocket)); 114 | if (NULL == netSock) 115 | { 116 | #if nlVerbose >= 1 117 | fprintf(stderr, ", Error!"); 118 | #endif 119 | return NULL; 120 | } 121 | else 122 | { 123 | memset(netSock, '\0', sizeof(netSocket)); // zero the entire structure 124 | netSetTimeout(netSock, 0.1); 125 | return netSock; 126 | } 127 | } 128 | 129 | 130 | /*========================================================* 131 | * Function : netConnect() 132 | * Purpose : Connect a netSocket to the specified destination. 133 | * Entry : netSocket *netSock = Socket to connect 134 | * const char *address = Character string of the destination (eg: "bubbai.ath.cx" or "192.168.0.1") 135 | * unsigned short port = The port on the destination to connect to 136 | * Returns : 0 on success, -1 on failure 137 | *========================================================*/ 138 | 139 | int netConnect (netSocket *netSock, const char *address, unsigned short port) 140 | { 141 | int tint = 0, socketargs = 0, setsockint = 1; 142 | struct hostent *h; 143 | 144 | #if nlVerbose >= 1 145 | fprintf(stderr, "\nnetLib: Connect"); 146 | fprintf(stderr, " %s:%d", address, port); 147 | #endif 148 | 149 | memset(&netSock->addr, '\0', sizeof(netSock->addr)); 150 | 151 | h = gethostbyname(address); // convert host name to IP and hold it in hostent structure 152 | if (NULL == h) 153 | { 154 | #if nlVerbose >= 1 155 | fprintf(stderr, ", name lookup failed"); 156 | #endif 157 | netSock->retval = -1; 158 | return -1; // DNS has failed.. bail out. 159 | } 160 | 161 | #if nlVerbose >= 1 162 | printf(" (Official name is: %s, IP address: %s)", h->h_name, inet_ntoa(*(struct in_addr*)h->h_addr)); 163 | #endif 164 | 165 | netSock->addr.sin_family = AF_INET; 166 | netSock->addr.sin_port = htons(port); // setup the port we will be connecting to. 167 | netSock->addr.sin_addr.s_addr = *((unsigned long *) h->h_addr); // Translate the IP address string to a usable address. 168 | netSock->number = socket(PF_INET, SOCK_STREAM, socketargs); 169 | if (-1 == netSock->number) 170 | { 171 | #if nlVerbose >= 1 172 | fprintf(stderr, ", socket ERROR"); 173 | #endif 174 | netSock->retval = -1; 175 | return -1; 176 | } 177 | 178 | tint = connect(netSock->number, (struct sockaddr*)&netSock->addr, sizeof(netSock->addr)); // connect the socket 179 | 180 | if (0 != tint) 181 | { 182 | #if nlVerbose >= 1 183 | fprintf(stderr, ", FAILED"); 184 | #endif 185 | netDisconnect (netSock); // properly close the socket 186 | netSock->retval = -1; 187 | return -1; 188 | } 189 | else 190 | { 191 | #ifdef TCP_NODELAY // Disable the Nagle algorithm 192 | { 193 | #ifdef MS_WINDOWS 194 | BOOL optval = TRUE; 195 | int optlen = sizeof(BOOL); 196 | if (-1 == setsockopt(netSock->number, IPPROTO_TCP, TCP_NODELAY, (char*)&optval, optlen)) 197 | { 198 | #if nlVerbose >= 1 199 | fprintf(stderr, ", setsockopt (Nagle) Warning"); 200 | #if nlVerbose >= 2 201 | fprintf(stderr, ", ERRNO = %d", WSAGetLastError()); 202 | #endif 203 | #endif 204 | } 205 | #else 206 | if (-1 == setsockopt(netSock->number, IPPROTO_TCP, TCP_NODELAY, &setsockint, sizeof(int))) 207 | { 208 | #if nlVerbose >= 1 209 | fprintf(stderr, ", setsockopt (Nagle) Warning"); 210 | #if nlVerbose >= 2 211 | fprintf(stderr, ", ERRNO = %d (%s)", errno, strerror(errno)); 212 | #endif 213 | #endif 214 | } 215 | #endif 216 | } 217 | #endif 218 | #ifdef SO_NOSIGPIPE // Stops "Broken pipe" errors in Mac OS X and some Unix distributions. SIGPIPE will stop the program from running. 219 | { 220 | if (-1 == setsockopt(netSock->number, SOL_SOCKET, SO_NOSIGPIPE, &setsockint, sizeof(int))) 221 | { 222 | #if nlVerbose >= 1 223 | fprintf(stderr, ", setsockopt (Sigpipe) Error"); 224 | #if nlVerbose >= 2 225 | fprintf(stderr, ", ERRNO = %d (%s)", errno, strerror(errno)); 226 | #endif 227 | #endif 228 | netDisconnect(netSock); 229 | return -1; 230 | } 231 | } 232 | #endif 233 | netSock->inuse = 1; // mark this socket as being in use since it was successful 234 | netSock->retval = 0; 235 | 236 | return 0; 237 | } 238 | } 239 | 240 | 241 | /*========================================================* 242 | * Function : netDisconnect() 243 | * Purpose : Disconnect a netSocket. 244 | * Entry : netSocket *netSock = The socket to disconnect 245 | * Returns : 0 on success, -1 on failure 246 | *========================================================*/ 247 | 248 | int netDisconnect (netSocket *netSock) 249 | { 250 | #if nlVerbose >= 1 251 | fprintf(stderr, "\nnetLib: Disconnect"); 252 | #endif 253 | 254 | shutdown(netSock->number, 2); // Stop reads and writes 255 | 256 | #ifdef UNIX // Unix uses close(), Windows and BeOS use closesocket(). 257 | { 258 | close(netSock->number); 259 | } 260 | #else 261 | { 262 | closesocket(netSock->number); 263 | } 264 | #endif 265 | 266 | memset(&netSock->addr, '\0', sizeof(netSock->addr)); 267 | netSock->inuse = 0; 268 | netSock->number = 0; 269 | netSock->retval = 0; 270 | 271 | return 0; 272 | } 273 | 274 | 275 | /*========================================================* 276 | * Function : netListen() 277 | * Purpose : Listen on a specified netSocket. 278 | * Entry : netSocket *netSock = Socket to listen on 279 | * unsigned short port = Port number to listen on 280 | * Returns : 0 on success, -1 on failure 281 | *========================================================*/ 282 | 283 | int netListen (netSocket *netSock, unsigned short port) 284 | { 285 | int tint = 0, socketargs = 0; 286 | 287 | #ifndef MS_WINDOWS 288 | int setsockint = 1; 289 | #endif 290 | 291 | #if nlVerbose >= 1 292 | fprintf(stderr, "\nnetLib: Listen"); 293 | #endif 294 | 295 | memset(&netSock->addr, '\0', sizeof(netSock->addr)); 296 | 297 | netSock->addr.sin_family = AF_INET; 298 | netSock->addr.sin_port = htons(port); // The clients will connect to this port 299 | netSock->addr.sin_addr.s_addr = INADDR_ANY; // autoselect IP address 300 | netSock->number = socket(PF_INET, SOCK_STREAM, socketargs); 301 | if (-1 == netSock->number) 302 | { 303 | #if nlVerbose >= 1 304 | fprintf(stderr, ", socket ERROR"); 305 | #endif 306 | return -1; 307 | } 308 | 309 | #ifdef MS_WINDOWS 310 | BOOL optval = TRUE; 311 | int optlen = sizeof(BOOL); 312 | if (-1 == setsockopt(netSock->number, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, optlen)) 313 | { 314 | #if nlVerbose >= 1 315 | fprintf(stderr, ", setsockopt (Reuse) Warning"); 316 | #if nlVerbose >= 2 317 | fprintf(stderr, ", ERRNO = %d", WSAGetLastError()); 318 | #endif 319 | #endif 320 | } 321 | #else 322 | if (-1 == setsockopt(netSock->number, SOL_SOCKET, SO_REUSEADDR, &setsockint, sizeof(int))) 323 | { 324 | #if nlVerbose >= 1 325 | fprintf(stderr, ", setsockopt (Reuse) Warning"); 326 | #if nlVerbose >= 2 327 | fprintf(stderr, ", ERRNO = %d (%s)", errno, strerror(errno)); 328 | #endif 329 | #endif 330 | } 331 | #endif 332 | 333 | tint = bind(netSock->number, (struct sockaddr*)&netSock->addr, sizeof(struct sockaddr)); 334 | if (0 != tint) 335 | { 336 | #if nlVerbose >= 1 337 | fprintf(stderr, ", Bind Failure"); 338 | #if nlVerbose >= 2 339 | #ifdef MS_WINDOWS 340 | fprintf(stderr, ", ERRNO = %d", WSAGetLastError()); 341 | #else 342 | fprintf(stderr, ", ERRNO = %d (%s)", errno, strerror(errno)); 343 | #endif 344 | #endif 345 | #endif 346 | netDisconnect(netSock); 347 | netSock->retval = -1; 348 | return -1; 349 | } 350 | 351 | tint = listen(netSock->number, 10); // set up to be a server (listening) socket, 2nd argument is backlog 352 | if (0 != tint) 353 | { 354 | #if nlVerbose >= 1 355 | fprintf(stderr, ", Listen Failure"); 356 | #if nlVerbose >= 2 357 | #ifdef MS_WINDOWS 358 | fprintf(stderr, ", ERRNO = %d", WSAGetLastError()); 359 | #else 360 | fprintf(stderr, ", ERRNO = %d (%s)", errno, strerror(errno)); 361 | #endif 362 | #endif 363 | #endif 364 | netDisconnect(netSock); 365 | netSock->retval = -1; 366 | return -1; 367 | } 368 | 369 | netSock->retval = 0; 370 | return 0; 371 | } 372 | 373 | 374 | /*========================================================* 375 | * Function : netAccept() 376 | * Purpose : Accept a connection from a listening port. 377 | * Entry : netSocket *listenSock = The listening socket 378 | * netSocket *netSock = The netSocket that has just connected 379 | * Returns : 1 on an accepted connection, 0 on nothing to accept, -1 on error 380 | *========================================================*/ 381 | 382 | int netAccept (netSocket *listenSock, netSocket *netSock) 383 | { 384 | socklen_t addrlen = sizeof(netSock->addr); // set to a value since windows needs it 385 | int setsockint = 1; 386 | 387 | #if nlVerbose >= 1 388 | fprintf(stderr, "\nnetLib: Accept"); 389 | #endif 390 | 391 | if(1 > netIsDataPending(listenSock)) 392 | { 393 | #if nlVerbose >= 1 394 | fprintf(stderr, ", no pending connection"); 395 | #endif 396 | netSock->retval = 0; 397 | return 0; 398 | } 399 | 400 | memset(&netSock->addr, '\0', sizeof(netSock->addr)); 401 | 402 | netSock->number = accept(listenSock->number, (struct sockaddr*)&netSock->addr, &addrlen); 403 | 404 | if (-1 == netSock->number) 405 | { 406 | #if nlVerbose >= 1 407 | fprintf(stderr, ", Error"); 408 | #endif 409 | #if nlVerbose >= 2 410 | #ifdef MS_WINDOWS 411 | fprintf(stderr, ", ERRNO = %d", WSAGetLastError()); 412 | #else 413 | fprintf(stderr, ", ERRNO = %d (%s)", errno, strerror(errno)); 414 | #endif 415 | #endif 416 | netSock->retval = -1; 417 | return -1; 418 | } 419 | else 420 | { 421 | #if nlVerbose >= 1 422 | fprintf(stderr, ", received connection from %s", inet_ntoa(netSock->addr.sin_addr)); 423 | #endif 424 | #ifdef TCP_NODELAY // Disable the Nagle algorithm 425 | { 426 | #ifdef MS_WINDOWS 427 | BOOL optval = TRUE; 428 | int optlen = sizeof(BOOL); 429 | if (-1 == setsockopt(netSock->number, IPPROTO_TCP, TCP_NODELAY, (char*)&optval, optlen)) 430 | { 431 | #if nlVerbose >= 1 432 | fprintf(stderr, ", setsockopt (Nagle) Warning"); 433 | #if nlVerbose >= 2 434 | fprintf(stderr, ", ERRNO = %d", WSAGetLastError()); 435 | #endif 436 | #endif 437 | } 438 | #else 439 | if (-1 == setsockopt(netSock->number, IPPROTO_TCP, TCP_NODELAY, &setsockint, sizeof(int))) 440 | { 441 | #if nlVerbose >= 1 442 | fprintf(stderr, ", setsockopt (Nagle) Warning"); 443 | #if nlVerbose >= 2 444 | fprintf(stderr, ", ERRNO = %d (%s)", errno, strerror(errno)); 445 | #endif 446 | #endif 447 | } 448 | #endif 449 | } 450 | #endif 451 | #ifdef SO_NOSIGPIPE // Stops "Broken pipe" errors in Mac OS X and some Unix distributions. SIGPIPE will stop the program from running. 452 | { 453 | if (-1 == setsockopt(netSock->number, SOL_SOCKET, SO_NOSIGPIPE, &setsockint, sizeof(int))) 454 | { 455 | #if nlVerbose >= 1 456 | fprintf(stderr, ", setsockopt (Sigpipe) Error"); 457 | #if nlVerbose >= 2 458 | fprintf(stderr, ", ERRNO = %d (%s)", errno, strerror(errno)); 459 | #endif 460 | #endif 461 | netDisconnect(netSock); // Since the connection has closed we can disconnect it 462 | netSock->retval = -1; 463 | return -1; 464 | } 465 | } 466 | #endif 467 | 468 | netSock->inuse = 1; // mark the socket as being in use 469 | netSock->retval = 1; 470 | return 1; 471 | } 472 | } 473 | 474 | 475 | /*========================================================* 476 | * Function : netIsDataPending() 477 | * Purpose : Checks if a netSocket is waiting for action. 478 | * Entry : netSocket *netSock = The socket to check 479 | * Returns : 1 if data is pending, 0 if no data is pending 480 | *========================================================*/ 481 | 482 | int netIsDataPending (netSocket *netSock) 483 | { 484 | fd_set selectlist; 485 | struct timeval tv; 486 | 487 | #if nlVerbose >= 2 // This message will show up a lot on debug level 2 488 | fprintf(stderr, "\nnetLib: IsDataPending"); 489 | #endif 490 | 491 | FD_ZERO(&selectlist); 492 | FD_SET(netSock->number, &selectlist); 493 | 494 | tv.tv_sec = netSock->timeout.tv_sec; // Set the timeout delay from the netSocket 495 | tv.tv_usec = netSock->timeout.tv_usec; 496 | 497 | select(netSock->number+1, &selectlist, NULL, NULL, &tv); 498 | 499 | if (0 != FD_ISSET(netSock->number, &selectlist)) 500 | netSock->retval = 1; 501 | else 502 | netSock->retval = 0; 503 | 504 | return netSock->retval; 505 | } 506 | 507 | 508 | /*========================================================* 509 | * Function : netSend() 510 | * Purpose : Send a number of bytes to a netSocket. 511 | * Entry : netSocket *netSock = Socket to send data to 512 | * const char *data = Pointer to a character string, this is the data that will be transfered 513 | * int bytes = the number of bytes to send starting at *data 514 | * Returns : number of bytes that were sent, -1 on error 515 | *========================================================*/ 516 | 517 | int netSend (netSocket *netSock, const char *data, int bytes) // const void* data 518 | { 519 | int byte_count = 0; 520 | 521 | #if nlVerbose >= 1 522 | fprintf(stderr, "\nnetLib: Send"); 523 | #endif 524 | 525 | #ifdef MSG_NOSIGNAL // Stop SIGPIPE errors in Linux 526 | byte_count = send(netSock->number, data, bytes, MSG_NOSIGNAL); 527 | #else 528 | byte_count = send(netSock->number, data, bytes, 0); 529 | #endif 530 | 531 | #if nlVerbose >= 1 532 | fprintf(stderr, ", transfered %d bytes", byte_count); 533 | #endif 534 | 535 | if (0 >= byte_count) 536 | { 537 | #if nlVerbose >= 1 538 | printf (", Connection closed"); 539 | #if nlVerbose >= 2 540 | #ifdef MS_WINDOWS 541 | fprintf(stderr, ", ERRNO = %d", WSAGetLastError()); 542 | #else 543 | fprintf(stderr, ", ERRNO = %d (%s)", errno, strerror(errno)); 544 | #endif 545 | #endif 546 | #endif 547 | netDisconnect(netSock); // Since the connection has closed we can disconnect it 548 | netSock->retval = -1; 549 | return -1; 550 | } 551 | 552 | netSock->retval = byte_count; 553 | return byte_count; 554 | } 555 | 556 | 557 | /*========================================================* 558 | * Function : netRecv() 559 | * Purpose : Recveive a number of bytes from a netSocket. 560 | * Entry : netSocket *netSock = Socket to receive data from 561 | * char *data = Pointer to a character string, this is where the data will be stored 562 | * int bytes = the number of bytes to receive 563 | * Returns : number of bytes that were received, -1 on error 564 | *========================================================*/ 565 | 566 | int netRecv (netSocket *netSock, char *data, int bytes) // const void* data 567 | { 568 | int byte_count = 0; 569 | 570 | #if nlVerbose >= 1 571 | fprintf(stderr, "\nnetLib: Receive"); 572 | #endif 573 | 574 | if(1 > netIsDataPending(netSock)) 575 | { 576 | #if nlVerbose >= 1 577 | fprintf(stderr, ", nothing is pending"); 578 | #endif 579 | netSock->retval = 0; 580 | return 0; 581 | } 582 | 583 | byte_count = recv(netSock->number, data, bytes, 0); 584 | 585 | #if nlVerbose >= 1 586 | fprintf(stderr, ", transfered %d bytes", byte_count); 587 | #endif 588 | 589 | if (0 >= byte_count) 590 | { 591 | #if nlVerbose >= 1 592 | printf (", Connection closed"); 593 | #if nlVerbose >= 2 594 | #ifdef MS_WINDOWS 595 | fprintf(stderr, ", ERRNO = %d", WSAGetLastError()); 596 | #else 597 | fprintf(stderr, ", ERRNO = %d (%s)", errno, strerror(errno)); 598 | #endif 599 | #endif 600 | #endif 601 | netDisconnect(netSock); // Since the connection has closed we can disconnect it 602 | netSock->retval = -1; 603 | return -1; 604 | } 605 | 606 | netSock->retval = byte_count; 607 | return byte_count; 608 | } 609 | 610 | 611 | /*========================================================* 612 | * Function : netSetTimeout() 613 | * Purpose : Set the timeout on a netSocket. 614 | * Entry : netSocket *netSock = The socket to set 615 | * float timeoutvalue = The new timeout value 616 | * Returns : 0 on success 617 | *========================================================*/ 618 | 619 | int netSetTimeout (netSocket *netSock, float timeoutvalue) 620 | { 621 | #if nlVerbose >= 1 622 | fprintf(stderr, "\nnetLib: SetTimeout"); 623 | #endif 624 | 625 | netSock->timeout.tv_sec = (int)timeoutvalue; 626 | netSock->timeout.tv_usec = (timeoutvalue - netSock->timeout.tv_sec) * 1000000; 627 | 628 | netSock->retval = 0; 629 | return 0; 630 | } 631 | 632 | 633 | /*========================================================* 634 | * Function : netSetOption() 635 | * Purpose : Set an option on a netSocket. 636 | * Entry : netSocket *netSock = The socket to set 637 | * int option = The option to set 638 | * int enable = 1 for enable, 0 for disable 639 | * Returns : 0 on success, -1 on failure 640 | *========================================================*/ 641 | 642 | int netSetOption (netSocket *netSock, int option, int enable) 643 | { 644 | int setsockint; 645 | 646 | #if nlVerbose >= 1 647 | fprintf(stderr, "\nnetLib: SetOption"); 648 | #endif 649 | 650 | #ifdef MS_WINDOWS 651 | BOOL optval; 652 | int optlen = sizeof(BOOL); 653 | if (1 == enable) 654 | { 655 | optval = FALSE; 656 | } 657 | else 658 | { 659 | optval = TRUE; 660 | } 661 | #else 662 | if (1 == enable) 663 | { 664 | setsockint = 0; 665 | } 666 | else 667 | { 668 | setsockint = 1; 669 | } 670 | #endif 671 | 672 | if (option == netDontRoute) 673 | { 674 | #ifdef SO_DONTROUTE 675 | #if nlVerbose >= 1 676 | fprintf(stderr, ", netDontRoute"); 677 | #endif 678 | #ifdef MS_WINDOWS 679 | if (-1 == setsockopt(netSock->number, SOL_SOCKET, SO_DONTROUTE, (char*)&optval, optlen)) 680 | { 681 | #if nlVerbose >= 1 682 | fprintf(stderr, ", setsockopt (Reuse) Warning"); 683 | #if nlVerbose >= 2 684 | fprintf(stderr, ", ERRNO = %d", WSAGetLastError()); 685 | #endif 686 | #endif 687 | } 688 | #else 689 | if (-1 == setsockopt(netSock->number, SOL_SOCKET, SO_DONTROUTE, &setsockint, sizeof(int))) 690 | { 691 | #if nlVerbose >= 1 692 | fprintf(stderr, ", setsockopt (Reuse) Warning"); 693 | #if nlVerbose >= 2 694 | fprintf(stderr, ", ERRNO = %d (%s)", errno, strerror(errno)); 695 | #endif 696 | #endif 697 | } 698 | #endif 699 | #endif 700 | } 701 | else if (option == netNagleAlgorithm) 702 | { 703 | #ifdef TCP_NODELAY 704 | #if nlVerbose >= 1 705 | fprintf(stderr, ", netNagleAlgorithm"); 706 | #endif 707 | #ifdef MS_WINDOWS 708 | if (-1 == setsockopt(netSock->number, IPPROTO_TCP, TCP_NODELAY, (char*)&optval, optlen)) 709 | { 710 | #if nlVerbose >= 1 711 | fprintf(stderr, ", setsockopt (Nagle) Warning"); 712 | #if nlVerbose >= 2 713 | fprintf(stderr, ", ERRNO = %d", WSAGetLastError()); 714 | #endif 715 | #endif 716 | } 717 | #else 718 | if (-1 == setsockopt(netSock->number, IPPROTO_TCP, TCP_NODELAY, &setsockint, sizeof(int))) 719 | { 720 | #if nlVerbose >= 1 721 | fprintf(stderr, ", setsockopt (Nagle) Warning"); 722 | #if nlVerbose >= 2 723 | fprintf(stderr, ", ERRNO = %d (%s)", errno, strerror(errno)); 724 | #endif 725 | #endif 726 | } 727 | #endif 728 | #endif 729 | } 730 | else if (option == netDebug) 731 | { 732 | #ifdef SO_DEBUG 733 | #if nlVerbose >= 1 734 | fprintf(stderr, ", netDebug"); 735 | #endif 736 | #ifdef MS_WINDOWS 737 | if (-1 == setsockopt(netSock->number, SOL_SOCKET, SO_DEBUG, (char*)&optval, optlen)) 738 | { 739 | #if nlVerbose >= 1 740 | fprintf(stderr, ", setsockopt (Debug) Warning"); 741 | #if nlVerbose >= 2 742 | fprintf(stderr, ", ERRNO = %d", WSAGetLastError()); 743 | #endif 744 | #endif 745 | } 746 | #else 747 | if (-1 == setsockopt(netSock->number, SOL_SOCKET, SO_DEBUG, &setsockint, sizeof(int))) 748 | { 749 | #if nlVerbose >= 1 750 | fprintf(stderr, ", setsockopt (Debug) Warning"); 751 | #if nlVerbose >= 2 752 | fprintf(stderr, ", ERRNO = %d (%s)", errno, strerror(errno)); 753 | #endif 754 | #endif 755 | } 756 | #endif 757 | #endif 758 | } 759 | else if (option == netNonBlocking) 760 | { 761 | #if nlVerbose >= 1 762 | fprintf(stderr, ", netNonBlocking"); 763 | #endif 764 | #ifdef MS_WINDOWS 765 | u_long val; 766 | if (1 == enable) 767 | val = 1; 768 | else 769 | val = 0; 770 | if (-1 == ioctlsocket(netSock->number, FIONBIO, &val)) 771 | { 772 | #if nlVerbose >= 1 773 | fprintf(stderr, ", ioctlsocket (NonBlocking) Warning"); 774 | #if nlVerbose >= 2 775 | fprintf(stderr, ", ERRNO = %d", WSAGetLastError()); 776 | #endif 777 | #endif 778 | } 779 | #else 780 | #ifdef O_NONBLOCK 781 | if (-1 == fcntl(netSock->number, F_SETFL, O_NONBLOCK)) 782 | { 783 | #if nlVerbose >= 1 784 | fprintf(stderr, ", fcntl (NonBlocking) Warning"); 785 | #if nlVerbose >= 2 786 | fprintf(stderr, ", ERRNO = %d (%s)", errno, strerror(errno)); 787 | #endif 788 | #endif 789 | } 790 | #endif 791 | #endif 792 | } 793 | 794 | return 0; 795 | } 796 | -------------------------------------------------------------------------------- /netSocket.h: -------------------------------------------------------------------------------- 1 | /* 2 | netSocket.h - Header file for netLib Network Communication Library (Main) 3 | v0.4 - 2007.08.30 4 | Coded by Ian Seyler (iseyler@gmail.com) 5 | http://bubbai.ath.cx/projects/netlib/ 6 | Copyright (c) 2007 Ian Seyler. All Rights Reserved. 7 | Distributed under the terms of the MIT License. 8 | */ 9 | 10 | 11 | #ifndef __NETSOCKET_H__ 12 | #define __NETSOCKET_H__ 13 | 14 | 15 | #include // fprintf 16 | #include // malloc 17 | #include // memset 18 | #ifdef MS_WINDOWS 19 | #include 20 | #include 21 | typedef int socklen_t; // Windows does not define this. 22 | #endif 23 | #ifdef UNIX 24 | #include 25 | #include // to look at error return values 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include // for dns lookup 31 | #include 32 | #endif 33 | #ifdef BEOS 34 | #include 35 | #include // to look at error return values 36 | #include 37 | #include 38 | #include 39 | #include // for dns lookup 40 | #include 41 | typedef int socklen_t; // BeOS does not define this. 42 | #define PF_INET AF_INET // Just using the value for AF_INET (Mac OS X does the same thing) 43 | #endif 44 | 45 | /* Structure of a netSocket */ 46 | struct netSocketStruct { 47 | int number; // the socket descriptor from the socket() call 48 | int inuse; // 1 for active, 0 for not active 49 | int retval; // all functions will update this variable with the function return value 50 | struct timeval timeout; // timeout value 51 | struct sockaddr_in addr; // connector's address information 52 | }; 53 | 54 | typedef struct netSocketStruct netSocket; 55 | 56 | #define netOK 0 // For use in comparisons. ie: if (netConnect(tempsock, "blah.com", 80) == netOK) 57 | #define netEnable 1 // For use with netSetOption 58 | #define netDisable 0 // For use with netSetOption 59 | #define netDontRoute 0 // For use with netSetOption 60 | #define netNagleAlgorithm 1 // For use with netSetOption 61 | #define netDebug 2 // For use with netSetOption 62 | #define netNonBlocking 3 // For use with netSetOption 63 | 64 | int netInit (); // initiate the library 65 | int netStop (); // stop the library 66 | 67 | netSocket* netInitSocket (); // initialize a new netSocket 68 | 69 | int netConnect (netSocket *netSock, const char *address, unsigned short port); // connect to a netSocket 70 | int netDisconnect (netSocket *netSock); // disconnect from a netSocket 71 | 72 | int netListen (netSocket *netSock, unsigned short port); // open a netSocket and listen on it 73 | int netAccept (netSocket *listenSock, netSocket *netSock); // accept a connection from a listening netSocket 74 | 75 | int netIsDataPending (netSocket *netSock); // check to see if a netSocket has data that is pending to be received 76 | 77 | int netSend (netSocket *netSock, const char *data, int bytes); // send data to a netSocket 78 | int netRecv (netSocket *netSock, char *data, int bytes); // receive data from a netSocket 79 | 80 | int netSetTimeout (netSocket *netSock, float timeoutvalue); // set the timeout value on a netsocket 81 | int netSetOption (netSocket *netSock, int option, int enable); // set an option on a netsocket 82 | 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # netLib Network Communication Library 2 | v0.4 - 2007.08.30 3 | 4 | Coded by Ian Seyler (iseyler@gmail.com) 5 | 6 | https://github.com/IanSeyler/netLib 7 | 8 | Copyright (c) 2007 Ian Seyler. All Rights Reserved. 9 | 10 | Distributed under the terms of the MIT License. 11 | 12 | 13 | 14 | ### What is netLib? 15 | 16 | The netLib Network Communication Library is a free, open-source C library for network communication over TCP/IP. It currently compiles on Windows, Unix (Linux, *BSD, Mac OS X) and BeOS. The netLib Network Communication Library was designed for simplicity, portability, and ease of use. 17 | 18 | 19 | ### License 20 | 21 | This software is distributed under the MIT License. Please see license.txt for more information. 22 | 23 | 24 | ### Files included in the distribution 25 | 26 | chat.c - A chat client. 27 | chat.h - Global header for chat and chatserver. 28 | chatserver.c - A multiple client chat server. 29 | echoserver.c - A simple server that you can connect to using a telnet client. It will echo back what you type. 30 | netSocket.c - The module file for the netLib library main functions. 31 | netSocket.h - The header file for the netLib library main functions. 32 | netBuffer.c - The module file for the netLib library buffer functions. 33 | netBuffer.h - The header file for the netLib library buffer fucntions. 34 | readme.md - This text file. 35 | LICENSE.txt - The license for netLib. 36 | testclient.c - A test client. 37 | testserver.c - A test server. 38 | docs/changelog.txt - A running log detailing the changes between the release versions. 39 | docs/manual.html - The current manual. 40 | docs/style.css - Style sheet for the manual. 41 | 42 | 43 | ### How to use netLib 44 | 45 | Consult the manual in the docs folder or check for the latest version online at http://bubbai.ath.cx/projects/netlib/manual.html 46 | The included testclient, testserver, bufferclient, bufferserver, and chat programs can be used as guides for your own programs. 47 | All included examples except for echoserver require netBuffer as well. 48 | The next section contains example on how to include netLib with your program (replace yournetapp.c with testserver.c or testclient.c). 49 | 50 | 51 | ### Compile Example 52 | 53 | This was verified to work with different versions of the GCC compiler. 54 | Tested OS's were Windows (2000, XP and Vista), Mac OS X (10.3 and 10.4), BeOS 5, and Linux (Fedora 7, Ubuntu 7.04, and Debian 4.0). 55 | 56 | Windows: 57 | 58 | gcc yournetapp.c netSocket.c netBuffer.c -o yournetapp -DMS_WINDOWS -L../lib/win32 -lwsock32 59 | 60 | Unix/Mac: 61 | 62 | gcc yournetapp.c netSocket.c netBuffer.c -o yournetapp -DUNIX 63 | 64 | BeOS: 65 | 66 | gcc yournetapp.c netSocket.c netBuffer.c -o yournetapp -DBEOS 67 | 68 | BeOS BONE: 69 | 70 | gcc yournetapp.c netSocket.c netBuffer.c -o yournetapp -DBEOS -lsocket 71 | 72 | BeOS note: netLib has not been testing with Haiku. 73 | 74 | To compile the buffer client on Windows you would use the command line: 75 | 76 | gcc bufferclient.c netSocket.c netBuffer.c -o bufferclient -DMS_WINDOWS -L../lib/win32 -lwsock32 77 | 78 | To compile the chat server on Unix you would use the command line: 79 | 80 | gcc chatserver.c netSocket.c netBuffer.c -o chatserver -DUNIX 81 | 82 | To compile the echo server on BeOS you would use the command line: 83 | 84 | gcc echoserver.c netSocket.c -o echoserver -DUNIX 85 | 86 | 87 | ### References 88 | 89 | The following guides, articles, and examples were used while writting netLib. 90 | 91 | Beej's Guide to Network Programming 92 | http://beej.us/guide/bgnet/ 93 | 94 | BeOS (Be Operating System) 95 | http://en.wikipedia.org/wiki/BeOS_R5 96 | 97 | BSD Sockets: A Quick And Dirty Primer 98 | http://www.mathematik.uni-ulm.de/help/sockets.html 99 | 100 | Winsock Programmer's FAQ: Articles: BSD Sockets Compatibility 101 | http://tangentsoft.net/wskfaq/articles/bsd-compatibility.html 102 | 103 | Winsock Programmer's FAQ 104 | http://tangentsoft.net/wskfaq/ 105 | 106 | Microsoft WinSock Reference 107 | http://msdn2.microsoft.com/en-us/library/ms741416.aspx 108 | 109 | socket(7) - Linux man page 110 | http://www.die.net/doc/linux/man/man7/socket.7.html 111 | 112 | 113 | ### Final Notes 114 | 115 | If you have any questions, comments, concerns, bug reports, patches, suggestions or feature requests please send me an email. 116 | -------------------------------------------------------------------------------- /testclient.c: -------------------------------------------------------------------------------- 1 | /* 2 | testclient.c - Module file for Test Client demo using netLib 3 | v0.4 - 2007.08.30 4 | Coded by Ian Seyler (iseyler@gmail.com) 5 | http://bubbai.ath.cx/projects/netlib/ 6 | Copyright (c) 2007 Ian Seyler. All Rights Reserved. 7 | Distributed under the terms of the MIT License. 8 | */ 9 | 10 | 11 | #include "netSocket.h" 12 | #include "netBuffer.h" 13 | 14 | int main(int argc, char *argv[]) 15 | { 16 | int tint; 17 | netSocket *tempsocket; // YOU MUST INITIALIZE ALL SOCKETS BEFORE USING THEM!! (netInitSocket) 18 | netBuffer *tempbuffer; // YOU MUST INITIALIZE ALL BUFFERS BEFORE USING THEM!! (netInitBuffer) 19 | 20 | printf("Test Client demo for netLib v0.4\n"); 21 | 22 | if (argc < 2) // make sure we got a destination as an arguement 23 | { 24 | printf("Usage : testclient hostname (ex: testclient bubbai.ath.cx)\n"); 25 | exit(1); 26 | } 27 | 28 | netInit(); // Start the netLib library 29 | 30 | tempsocket = netInitSocket(); // initiate the socket 31 | tempbuffer = netInitBuffer(128); // initiate a 128 byte buffer 32 | 33 | if (netConnect(tempsocket, argv[1], 8192) == netOK) // if the connection looks good, keep going 34 | { 35 | for (tint=0; tint<5; tint++) //loop of doing a netRecvBuffer 5 times 36 | { 37 | if(netRecvBuffer(tempsocket, tempbuffer) > 0) // make sure we got some data 38 | printf("\nGot '%s'", tempbuffer->data); 39 | else 40 | break; // if the netRecvBuffer failed then break out to the netDisconnect 41 | } 42 | netDisconnect(tempsocket); // Issue here. We disconnect twice if the server dies early as netRecvBuffer does cleanup on broken connections. 43 | } 44 | 45 | netStop(); // Stop the netLib library 46 | 47 | printf("\n"); 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /testserver.c: -------------------------------------------------------------------------------- 1 | /* 2 | testserver.c - Module file for Test Server demo using netLib 3 | v0.4 - 2007.08.30 4 | Coded by Ian Seyler (iseyler@gmail.com) 5 | http://bubbai.ath.cx/projects/netlib/ 6 | Copyright (c) 2007 Ian Seyler. All Rights Reserved. 7 | Distributed under the terms of the MIT License. 8 | */ 9 | 10 | 11 | #include "netSocket.h" 12 | #include "netBuffer.h" 13 | 14 | #define MAXCONCURRENTCLIENTS 5 15 | 16 | int main() 17 | { 18 | int tint, step = 60, freeclient = -1; 19 | netSocket *clientsocket[MAXCONCURRENTCLIENTS]; 20 | netSocket *tempsocket; // YOU MUST INITIALIZE ALL SOCKETS BEFORE USING THEM!! 21 | netSocket *listensocket; 22 | netBuffer *tempbuffer; // YOU MUST INITIALIZE ALL BUFFERS BEFORE USING THEM!! 23 | char *netBuff; 24 | char netBuffData[128]; 25 | netBuff = netBuffData; 26 | 27 | printf("Test Server demo for netLib v0.4\n"); 28 | 29 | netInit(); // Start the netLib library 30 | 31 | for(tint=0; tintdata[0] = step++; // increment the message 46 | 47 | // listen for new connections and accept them if there is room 48 | if (netIsDataPending(listensocket) == 1) 49 | { 50 | for(tint=0; tintinuse == 0) 53 | { 54 | freeclient = tint; 55 | break; // get out of the for loop... we have the freeclient token 56 | } 57 | } 58 | 59 | if (freeclient != -1) // There is a valid free connection.. use it! 60 | { 61 | netAccept(listensocket, clientsocket[freeclient]); 62 | printf(" --> Client is %d", tint+1); 63 | freeclient = -1; // clear the token 64 | } 65 | else // No more connection.. kick them off 66 | { 67 | printf("\nNo more free connections."); 68 | netAccept(listensocket, tempsocket); // accept and disconnect the socket 69 | netDisconnect(tempsocket); 70 | } 71 | } // we are done listening here 72 | 73 | // Update current clients 74 | for(tint=0; tintinuse == 1) 77 | netSendBuffer(clientsocket[tint], tempbuffer); // NetSendBuffer will do the cleaning if there is an error. 78 | } 79 | // done updating the current clients 80 | 81 | } 82 | 83 | netDisconnect(listensocket); 84 | 85 | netStop(); // Stop the netLib library 86 | 87 | printf("\n"); 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /webserver.c: -------------------------------------------------------------------------------- 1 | /* 2 | webserver.c - Super simple webserver demo using netLib 3 | v0.1 - 2014.11.13 4 | Coded by Ian Seyler (iseyler@gmail.com) 5 | https://github.com/IanSeyler/netLib/ 6 | Copyright (c) 2007 Ian Seyler. All Rights Reserved. 7 | Distributed under the terms of the MIT License. 8 | */ 9 | 10 | 11 | #include "netSocket.h" 12 | 13 | const int port = 8192; 14 | const int buffsize = 2000; 15 | 16 | /* Default HTTP page with HTTP headers */ 17 | char webpage[] = 18 | "HTTP/1.0 200 OK\n" 19 | "Server: BareMetal (http://www.returninfinity.com)\n" 20 | "Content-type: text/html\n" 21 | "\n" 22 | "\n" 23 | "\n" 24 | "\n" 25 | "Hello world\n" 26 | "\n" 27 | "\n" 28 | "Hello World!\n" 29 | "\n" 30 | "\n"; 31 | 32 | int main() 33 | { 34 | int tint; 35 | netSocket *clientsocket, *listensocket; 36 | char tempbuffer[buffsize]; 37 | 38 | printf("Web Server demo for netLib v0.4\nListening on port %d\n", port); 39 | 40 | // Start the netLib library 41 | netInit(); 42 | 43 | // Initiate the sockets 44 | clientsocket = netInitSocket(); 45 | listensocket = netInitSocket(); 46 | 47 | // Set the server to listen 48 | netListen(listensocket, port); 49 | 50 | printf("\n\n"); 51 | 52 | // Main program loop 53 | for (;;) 54 | { 55 | // Check for an incoming connection 56 | if (netAccept(listensocket, clientsocket) > 0) 57 | { 58 | // A client has connected! 59 | printf("\nHello."); 60 | 61 | // Clear the buffer 62 | memset(tempbuffer, 0, buffsize); 63 | 64 | // Check for data to receive and print if there was something 65 | tint = netRecv(clientsocket, tempbuffer, buffsize); 66 | if (tint > 0) 67 | { 68 | printf("\nReceived %d bytes.", tint); 69 | // printf("\n--------------------\n%s", tempbuffer); 70 | } 71 | 72 | // Send data to the client 73 | tint = netSend(clientsocket, webpage, strlen(webpage)); 74 | printf("\nSent %d bytes.", tint); 75 | 76 | // Disconnect the client 77 | netDisconnect(clientsocket); 78 | printf("\nGoodbye.\n\n"); 79 | } 80 | // Why isn't this done on its own... 81 | fflush(stdout); 82 | } 83 | 84 | netDisconnect(listensocket); 85 | 86 | // Stop the netLib library 87 | netStop(); 88 | 89 | printf("\n"); 90 | return 0; 91 | } 92 | --------------------------------------------------------------------------------