Thread: sending a file across sockets.

  1. #1
    Registered User
    Join Date
    Jan 2008
    Posts
    79

    sending a file across sockets.

    i'm struggling with this.

    Firstly, is it best to open the file in rb and send it across in binary?

    Secondly, what way would i work it do i loop and read chunks for the file at a time and then send them to the remote client

    if i do that how do i make sure i dont just read the same part of the file over and over, i.e how do i make sure the second read call reads the next block of info.

    also how do i test if the file has been completely read?

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    So, do you know how file I/O works? Because all of those questions would be answered by looking up how fread and friends operate.

  3. #3
    Registered User jeffcobb's Avatar
    Join Date
    Dec 2009
    Location
    Henderson, NV
    Posts
    875
    Tabstop is right about the file IO parts but in general you need to construct two parts, one to be the sender (tx) and one to be the receiver (rx). For each:

    Tx: Sender needs to stat the file to be sent, get the full path, exact number of bytes in the file and preferably do a CRC on the file for later confirming what got sent to the Rx box was indeed correct and intact. A short header message can then be sent to the Rx box essentially saying "file XXXXX.YYY is coming, expect NNN bytes of data and the CRC is ZZZZ".

    Rx: Rx gets this message, usually spins off a thread to handle the job, opens the file and then goes into a loop that essentially says "while total bytes received is less than what we have so far, keep accepting packets" and then sends a message to the Tx box saying "I am ready".

    Tx then creates a buffer of say 1024 bytes and goes into a loop using fread to scoop the next 1024 bytes of file and pushes it out of the socket to Rx until done. When done it then would go into a wait-state waiting for the Rx box to send a final "I got it all" message, at which point the Tx box tears down the connection, releases any resources and goes onto the next task.

    Rx meanwhile continues to get packets from the Tx box and writing them to the file until the last bytes are received and stored. A CRC is then done the the new file and if it matches what the Tx sent in the beginning, it sends a message to Tx saying "thanks, got it" and tears down its side of the connection. If there is a CRC mismatch, the msg to Tx looks more like "CRC mismatch, send again" which would start the whole process over again.

    This in general is a simplistic way of sending a file over a network to another machine with error-checking. An exercise left to the reader would be to allow for auto-resume if the connection is lost part-way through the file, possibly individual packet CRCs so if something is damaged in transit, only the bad packets are resent, not the whole file.
    C/C++ Environment: GNU CC/Emacs
    Make system: CMake
    Debuggers: Valgrind/GDB

  4. #4
    Registered User
    Join Date
    Jan 2008
    Posts
    79
    i had a go using what i thought was a good way of doing it, obviously im a noob and im crap - needless to say this isnt working, ive put comments down at the bottom of the code where it seems to be going wrong. a basic list of problems.

    Firstly this code is both client and server you can run it and specify one side to send a file on connection and you can run it again on a different terminal window and tell it to connect and download the file.

    Well thats what i was trying anyway. Here are the problems.

    1) the makeaddress function works when creating the socket for the server. However it does not work for creating the socket for the client and when i call the connect command it throws and error trying to perfom a socket action on non-socket

    The actual reading of the file and writing it too the socket - because i cant get the client option to work im connection with telnet and it seems to print out alot of rubbish basically as im dumping what its reading from the file to the screen.

    Anyway ive included the code. Again it compiles with no errors or warnings.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h> 
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <sys/wait.h>
    #include <errno.h>
    
    
    void bail (char *msg){
    	fputs(strerror(errno),stderr);
    	fputs(": ",stderr);
    	fputs(msg,stderr);
    	fputc('\n',stderr);
    	exit(1);
    
    }
    
    char *resolve (const char *hostname){
    
    	struct hostent *hp;
    	hp = gethostbyname(hostname);
    
    	if(!hp){
    
    		bail("Error Resolving host");
    
    	}
    	char rstr = sprintf("%s",hp->h_addr_list[0]); 
    	return hp->h_addr_list[0];
    
    
    
    }
    
    
    int makeaddr(void * addr, int len, int *s, char *type, char *ip, int port){
    
    	//takes &addr,sizeof(addr), &sock,"TCP",ipaddr, port number
    	int Default_port = 3099;
    	int yes = 1;
    	struct sockaddr_in *ad = (struct sockaddr_in *)addr; 	
    
    	memset(ad,0,len);
    
    	ad->sin_family = AF_INET;
    
    	if(!ip){
    	
    		ad->sin_addr.s_addr = INADDR_ANY;
    
    	}
    
    	else{
    		ad->sin_addr.s_addr = inet_addr(ip);
    
    	}
    
    	if(port == 0){
    		printf("\n Port = 0\nDefault port = %d\n",Default_port);
    		ad->sin_port = htons(Default_port);
    	
    
    	}
    	else{
    		Default_port = port;
    		ad->sin_port = htons(port);
    
    	}
    
    	
    	
    	//we have created the address structure. Now create the socket
    
    	if(strcmp(type,"TCP")==0){
    
    		if((*s = socket(AF_INET,SOCK_STREAM,0))== -1)
    			bail("TCP Sock Error");
    
    		if(setsockopt(*s, SOL_SOCKET,SO_REUSEADDR, &yes, sizeof(int))==-1)
    			bail("Unable to set socket options");
    
    		if(bind(*s,(struct sockaddr*)ad,len)== -1){
    
    			bail("TCP Bind Error");
    
    		}
    
    		printf("TCP Socket Successfully created: On Port %d \n",Default_port);
    
    	}
    
    	else if(strcmp(type,"PASS")==0){
    		//nothing.
    	}
    
    	else{
    
    
    		if((*s = socket(AF_INET,SOCK_DGRAM,0))== -1)
    			bail("UDP Sock Error");
    
    		if(setsockopt(*s, SOL_SOCKET,SO_REUSEADDR, &yes, sizeof(int))== -1)
    			bail("Unable to set socket options");
    		if(bind(*s,(struct sockaddr*)ad,len)== -1){
    
    			bail("UDP Bind Error");
    
    		}
    		printf("UDP Socket Successfully created: On Port %d \n",Default_port);
    
    	}
    	
    	
    
    
    
    
    
    
    }
    
    int main(int argc, char *argv[]){
    
    	int sock;
    	int clisock;
    	struct sockaddr_in addr, cli_addr;
    
    	//takes &addr,sizeof(addr), &sock,"TCP",ipaddr, port number
    	//makeaddr(&addr,sizeof(addr),&sock,"UDP",NULL,0);
    
    	int flag_listen = 0;
    	int flag_listen_port = 0;
    	int flag_sendFile = 0;
    	int flag_filename = 0;
    	int i = 1;
    	int cli_len;
    	int flag_getfile = 0;
    	int flag_getfilePort = 0;
    
    	for(i = 0; i < argc; i++){
    
    		if(strcmp(argv[i],"-l")==0){
    	
    			flag_listen = i;
    			flag_listen_port = i + 1;
    			if(argc <= flag_listen_port)
    				bail("No Port Number Set\n");
    
    		}
    
    
    		if(strcmp(argv[i],"-sF")==0){
    			
    			if(flag_listen == 0)
    				bail("You need to specify a -l [portnumber] to use this function.\n");
    			flag_sendFile = i;
    			flag_filename = i + 1;
    			if(argc <= flag_filename)
    				bail("No Filename Set\n");
    
    			
    
    		}
    
    		
    		if(strcmp(argv[i],"-gF")==0){
    
    			flag_getfile = i;
    			flag_getfilePort = i + 1;
    			if(argc <= flag_getfilePort)
    				bail("Specify Port Number To connect too\n");
    
    		}
    
    
    	
    
    	}
    
    
    
    	//we got here we might have a logical command.
    
    	if(flag_getfile > 0 && flag_getfilePort > 1){
    
    		makeaddr(&addr,sizeof(addr),&sock,"PASS","127.0.0.1",flag_getfilePort);
    		if(sock = socket(AF_INET,SOCK_STREAM,0) == -1) /*The reason ive got this here was because i passed it with TCP instead of pass  it tried to bind and errored*/
    				bail("Socket Error"); 
    
    		if(connect(sock,(struct sockaddr *)&addr,sizeof(addr)) < 0)
    				bail("Error On Connection."); //errors here socket operation on non socket. 
    		int bytes;
    		char buff[256];
    		int pkt = 1;
    		
    		for(;;){
    
    			bytes = recv(sock,buff,sizeof(buff),0);
    			printf("Packet Recieved %d\n",pkt);
    			printf("Total Bytes: %d\n",bytes);
    			printf("Dump:\n%s",buff);
    
    			if(strcmp(buff,"END")==0)
    				break;
    	
    		}
    
    		printf("loop Exit.");
    		close(sock);
    			
    	
    	
    
    	}
    	if(flag_listen > 0 && flag_sendFile > 0){
    		
    		char sndBuf[256];
    		FILE *p;
    		//program didnt bail out so must have logical port command
    		 p = fopen(argv[flag_filename],"r");
    			//bail(argv[flag_filename]);
    
    		//make socket address
    		makeaddr(&addr,sizeof(addr),&sock,"TCP",NULL,atoi(argv[flag_listen_port]));
    		//we should now have a bind socket.
    		printf("Listening on port %d - Waiting for connection...\nReady to send file: %s\n",atoi(argv[flag_listen_port]),argv[flag_filename]);
    		listen(sock,5);
    		
    		cli_len = sizeof(cli_addr);
    		if(clisock = accept(sock,(struct sockaddr *) &cli_addr, &cli_len)== -1)
    			bail("Error Accepting Remote connection\n");
    		
    		printf("Connection Established. Sending File: %s\n\n",argv[flag_filename]);
    		
    		//read and write.
    		int bytes_sent;
    		int jj = 1;
    		//sndBuf
    		
    		while(fgets(sndBuf,256,p)!= NULL){
    			
    			//write the file to the client.
    			bytes_sent = send(clisock,sndBuf,sizeof(sndBuf),0);
    			printf("Sent packet %d\n",jj);
    			jj++;
    			printf("Total Bytes Sent: %d\n",bytes_sent); //this always remains at -1 error??
    			printf("Dump:\n%s\n\n",sndBuf);
    			//sleep(2); //wont sleep keeps sending packets of data very fast
    
    		}
    		int k = strlen("END");
    		send(clisock,"END",k,0);
    	}
    
    
    	else{printf("Usage: ./ma [-sF send file] [-gF get File]\n");}
    
    	close(sock);
    	return 0;
    }

  5. #5
    Registered User jeffcobb's Avatar
    Join Date
    Dec 2009
    Location
    Henderson, NV
    Posts
    875
    While I am not going to compile all of that I noticed you are using UDP which if you are at all concerned with stuff getting from A to B, UDP is the WRONG answer unless you add a ton more control/data management logic to it. Unlike TCP, UDP packets can arrive in any order and are not even guaranteed to arrive at all. It is called Unreliable Datagram Protocol for a reason mate! While you will probably get lucky going from term A to B, going from machine A to B will produce some problems and going over the Internet will make you nuts. I am not saying UDP has no uses on the net but this sure isn't it.

    Realistically looking at your code it seems like you are just opening a socket and throwing data at it. While this might work in some circumstances you really need to do more to manage the transfer and not just open a port and start reading data or opening a port and slamming data into it. If you are still having issues tomorrow I can probably whip something up (I do a lot of this stuff) to illustrate what I mean...going at it this way looks like an invitation to pain...

    Also on the receive side, I see where you are reading packet after packet but not storing the data anywhere...did that get dropped from the code?
    Last edited by jeffcobb; 04-17-2010 at 05:27 PM.
    C/C++ Environment: GNU CC/Emacs
    Make system: CMake
    Debuggers: Valgrind/GDB

  6. #6
    Registered User
    Join Date
    Jan 2008
    Posts
    79
    the makeaddress function has an option to make a udp socket, but it doesnt. As you can see i pass the string TCP to the makeaddress function to specify that i want to create a tcp socket which is what happens.

    perhaps the code is too big, to be honest im getting sick of c programming it seems to constantly throw up stupid errors and problems that i cant detect.

    Plus its nearly impossible to find good info on the things i want

    i.e how to send a file across sockets properly in binary mode
    and how to implement a select server which can read and write.

    i have a huge book linux socket programming and he goes into detail on everything and explains it well but when it comes to the select statement he throws it in as part of 500 line source code using a rpn calculator making it impossible for a noob like me to understand.

    Even then he only explains how to read from multiple sockets (badly) he just says "writing on top of this is even more complex"

    wow thanks.

  7. #7
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You say this compiles cleanly, and yet:
    Code:
    $ gcc -Wall -Wextra -o mushy mushy.c
    mushy.c: In function ‘resolve’:
    mushy.c:33: warning: format not a string literal and no format arguments
    mushy.c:33: warning: unused variable ‘rstr’
    mushy.c: In function ‘makeaddr’:
    mushy.c:125: warning: control reaches end of non-void function
    mushy.c: In function ‘main’:
    mushy.c:192: warning: suggest parentheses around assignment used as truth value
    mushy.c:235: warning: pointer targets in passing argument 3 of ‘accept’ differ in signedness
    mushy.c:235: warning: suggest parentheses around assignment used as truth value
    There are several warnings about your parenthesizing error again. That line 33 is definitely an error as you've forgotten the string to print to!

  8. #8
    Registered User
    Join Date
    Aug 2007
    Location
    MD, USA
    Posts
    71
    Yes it is a big topic.
    I feel your pain , but I'd definitely eliminate those warnings. Heck, that's the easy part!
    Try: Beej's Guide to Network Programming
    Last edited by HowardL; 04-18-2010 at 09:50 AM.

  9. #9
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by mushy View Post
    i have a huge book linux socket programming and he goes into detail on everything and explains it well but when it comes to the select statement he throws it in as part of 500 line source code using a rpn calculator making it impossible for a noob like me to understand.
    Programming documentation & literature is an infinite regress, it seems.

    I have a few different little utility servers I've written that I use everyday, some online, some on a LAN. They are into the hundreds and thousands of lines too, but are simple enough to describe. To be honest, I don't use select much because I prefer to avoid persistent connections. In other words, a client connects, you deal with the client's request, then you disconnect the client. If the client wants to make another request, it can call again. This is how an http web server works.

    I do have some specific methods for file transfer that work.

    Usually my approach to the server is like this:

    -> I have an infinite -- "while(1)" -- main loop. It doesn't have to be infinite, but it might as well be. Use "break" within the loop to end the session. Obviously the socket has to be set up, listen() called, etc, before this main loop.

    -> The first thing in the loop is a blocking (or a non-block time limited) accept(). I have used select here as well, that makes the next step a nested loop (to deal with all the ready descriptors). Using the "no persistent connection" model, all you need is accept, and so the next step applies to a single incoming descriptor.

    -> If you need to deal with authentication, you do that first; if you have a list of ip's, you can use that, and or a "handshake" method where the client sends some password as the first part of the transmission. Authentication is optional, probably you can skip this for now.

    -> Next you read one byte (a char) from the incoming descriptor. This indicates the type of request from the client, eg "G" could mean a get file request, "M" could mean an incoming text message, etc. You have a case/switch statement in the main loop (or in a separate function to which you send that char):
    Code:
    switch (byte) {
         case ('G'):  getfile(client);
                            break;
         case ('M'):  takemessage(client);
                           break;
         case ('P'):   putfile(client);
    Here byte is that first "byte" and "client" is the int socket descriptor of the client returned by accept(). getfile(), putfile() and takemessage() are discrete functions. Depending on context, these can fork() -- it is not necessary.

    -> putfile() works like this: you continue reading from the client upto a '\0' (or '\n'*). That's the filename. Now read 4 more bytes from the client, an int (you have to make sure the client and server both are using the same endianness and type size if they are on different machines). This is the length of the data. Then you have a read loop like this:
    Code:
    int len;  // this is the length just read in!
    int r = 0, total = 0;
    unsigned char *data = malloc(len), *p = data;
    while(total < len) {
        r = recv(client, p, len-total, 0);
        p += r;
        total += r;
    }
    You now have the file in "data". You can write that out to a file using binary mode with fopen() & fwrite() or open() and write(). Any and all kinds of files can be transferred this way.

    * networking may seems to work more smoothly if you use newlines with messages in some circumstances
    Last edited by MK27; 04-18-2010 at 10:19 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  10. #10
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    You'ave got too many things goin' on at once - simplify.
    Start off by creating a simple tcp server side socket.
    As it is the code is too hard, so fix your indentation.
    Also I don't see any bind() or listen() calls in the code.
    Code goes from socket() straight to connect(), as in
    Code:
    if (sock = socket(AF_INET,SOCK_STREAM,0) == -1)
        bail("Socket Error"); 
    
    /* where's the bind() and listen() ?? */
    
    if (connect(sock,(struct sockaddr *)&addr,sizeof(addr)) < 0)
        bail("Error On Connection."); //errors here socket operation on non socket.

  11. #11
    Registered User jeffcobb's Avatar
    Join Date
    Dec 2009
    Location
    Henderson, NV
    Posts
    875
    The thing with select() is that it is meant to be used in situations where you are planning on having many multiple connections happening concurrently and those connections need to be serviced for more than a single transaction. If none of the above is true, what MK said is correct. If you plan on having more than a few connections to your server (in your example no) and/or these connections are going to take time (hint: transferring a file takes time) then you need to use select or you will miss client connections. Now select() in and of itself isn't that hard to use; for a simple example check out the Beej link someone posted a few replies back.

    In general C programming is not trivial once you get out the "hello world" phase of learning but it is one of the more widely-used languages so if you want to be a programmer, suck it up and learn.

    So one question before we go on (and someone moves this thread to the Networking forum) is: do you intend for this to be a single-shot thing (simple client A shooting a file to client B) or do you plan on this thing being a full-time server? How you answer this will determine what is the most correct and simplest way to accomplish what you want...
    C/C++ Environment: GNU CC/Emacs
    Make system: CMake
    Debuggers: Valgrind/GDB

  12. #12
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by itCbitC View Post
    Code goes from socket() straight to connect(), as in
    Code:
    /* where's the bind() and listen() ?? */
    if (connect(sock,(struct sockaddr *)&addr,sizeof(addr)) < 0)
        bail("Error On Connection."); //errors here socket operation on non socket.
    Servers bind and listen.

    Clients connect. So it is either one or the other, not both -- bind, listen, then connect would be silly.

    However, the way mushy is doing it is wrong, since it looks like an attempt to connect to one's self.

    Quote Originally Posted by jeffcobb View Post
    these connections are going to take time (hint: transferring a file takes time)
    Select will not really solve this problem easily -- if you want to really on a select based solution, you would need to break the file into small packets, keep track, at each iteration send the next packet. It would be easier (and in fact better in many ways) to use fork() to deal with this, in which case you still do not need select().

    But depending on the context, you may not need to bother with either one. If the files transferred are small enough to be done with in <10 seconds (that's a lot on broadband and even more on a LAN, etc), you can just let incoming requests wait. Connect doesn't time out -- I think you can leave a client blocked by a pending connect for hours (altho I haven't tried).
    Last edited by MK27; 04-18-2010 at 01:39 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  13. #13
    Registered User jeffcobb's Avatar
    Join Date
    Dec 2009
    Location
    Henderson, NV
    Posts
    875
    Quote Originally Posted by MK27 View Post
    Select will not really solve this problem easily -- if you want to really on a select based solution, you would need to break the file into small packets, keep track, at each iteration send the next packet. It would be easier (and in fact better in many ways) to use fork() to deal with this, in which case you still do not need select().

    Connect doesn't time out -- I think you can leave a client blocked by a pending connect for hours (altho I haven't tried).
    MK: First, Connect doesn't time out but most clients will; this is dictated at a higher level than a single function call but is part of good design. IOW unless you own and monitor both ends of the process, you don't know that the client should wait for hours to connect when in fact the server itself is down. However even if that were the proper behavior I have seen where a non-answering (due to blocking) server will result in the connect attempt from more than say 5 waiting connections will fail immediately.

    As for the fork() suggestion, you may want to read about why Apache moved from that model to a thread-based model. It is here that the select() call has power and is irreplaceable. One call that kind of lived inbetween select() and what you prefer is poll(); simpler to use for a single descriptor with many of the same benefits of select(). Also it seems most the argument for/against select() are scoped into the read/write descriptors but being able to react quickly to an error state on a connection is very useful...

    At the end of the day its all about if you want to service more than one connection concurrently and if you want to keep your server responsive.

    I am envious of your broadband connection though; most files take < 10 seconds to move? Wow. Most of mine are in the 700mb range and take an hour or more to move up or down...
    C/C++ Environment: GNU CC/Emacs
    Make system: CMake
    Debuggers: Valgrind/GDB

  14. #14
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by jeffcobb View Post
    MK: First, Connect doesn't time out but most clients will; this is dictated at a higher level than a single function call but is part of good design. IOW unless you own and monitor both ends of the process, you don't know that the client should wait for hours to connect when in fact the server itself is down.
    That was sort of an extreme example. It really depends on specifically what this software is for.

    However even if that were the proper behavior I have seen where a non-answering (due to blocking) server will result in the connect attempt from more than say 5 waiting connections will fail immediately.
    Yes, that is a parameter you set with listen (the second argument is the max number of pending connections to wait on, anything over this fails with ECONNREFUSED). Sometimes you may even want to set that to 0, but anyway it's indicative of the fact that you do not have to accept() a connect() request immediately, it can wait in a queue (of determinate length, but for an indeterminate time).

    As for the fork() suggestion, you may want to read about why Apache moved from that model to a thread-based model. It is here that the select() call has power and is irreplaceable.
    Haven't written a threaded server but no doubt this is true, you could just put mutex's on the descriptor queue and have multiple threads consuming that. But apache has to answer a bunch of simultaneous request from a single client (the page source, the images, the scripts, etc, these are all separate requests).

    Anyway, dollars to donuts most servers are still running forked not threaded because the php module is not thread safe. I tried to tell everyone perl/mason is a better choice, they won't listen

    I am envious of your broadband connection though; most files take < 10 seconds to move? Wow. Most of mine are in the 700mb range and take an hour or more to move up or down...
    Fiber optic is the tish. I can upload 700mb in 10 minutes (download in <90 secs). I would not treat that as a standard for anyone, the point is context rules. You might as well write a 1000 line program that does a specific thing in a specific setting properly as rely on a 20000 line program someone else wrote to do any number of completely different things for just about anybody.
    Last edited by MK27; 04-18-2010 at 02:13 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  15. #15
    Registered User jeffcobb's Avatar
    Join Date
    Dec 2009
    Location
    Henderson, NV
    Posts
    875
    Oh man you have FIBER???

    <dies>

    <rassafrassin DSL rassafrassin Las Vegas providers..>

    Curious: what does that cost in your area for a static IP?
    C/C++ Environment: GNU CC/Emacs
    Make system: CMake
    Debuggers: Valgrind/GDB

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. sequential file program
    By needhelpbad in forum C Programming
    Replies: 80
    Last Post: 06-08-2008, 01:04 PM
  2. Game Pointer Trouble?
    By Drahcir in forum C Programming
    Replies: 8
    Last Post: 02-04-2006, 02:53 AM
  3. Post...
    By maxorator in forum C++ Programming
    Replies: 12
    Last Post: 10-11-2005, 08:39 AM
  4. System
    By drdroid in forum C++ Programming
    Replies: 3
    Last Post: 06-28-2002, 10:12 PM
  5. Need a suggestion on a school project..
    By Screwz Luse in forum C Programming
    Replies: 5
    Last Post: 11-27-2001, 02:58 AM