Listening via Linuxby Solthae
Greeting, I bring you some simple C code that, when compiled, sets up a simple server on your system listening on a port of your request. But first...
Why did I code this and send it away? Without getting too long-winded, I simply wanted to provide an appetizer to the world of Linux network programming I've been getting into over the last year or so. The texts I've read and the projects I've worked on have kept me reading and continuing them (not always common). I'm hoping to turn on new people interested who've not yet had any neat code to play with. I figured that the best way I could do that was by providing the most basic of code that would also be useful and entertaining. The result: my simple 'listener.cc'. Besides I love to see code in 2600.
What does listener do? Listener listens on whatever machine it is executed on (provided '&' to run in the background), waiting and listening (that'sthree) for connections to the specified port. For example:
solthae@mars$> ./listener 2600 &then:
solthae@mars$> telnet localhost 2600will connect you to the listener program.
What happens afterwards is up to you. How is that up to me? You modify listener to so something other than what I provided by editing the code at the bottom of the 'for' loop. You'll see:
while (fgets(buf, sizeof bug, rStream)) { ...This continues to receive requests (for Telnet, requests are whatever was typed before pressing 'Enter') and storing them in the 'char buf[]'. At that point you can process them at will. Hopefully at this point the opportunities are beginning to come to you (your own personal <blank> server, making your own honeypot to stick on the Telnet port, perhaps begin work on a MUD, a joke-of-the-day echo server, etc.).
Since that's basically the whole shebang I'll leave you here. I have faith in your intelligence and also didn't want to bore you with attempting to explain what the various strange calls are doing (socket(2), listen(2), bind(2), etc.).
Instead I left you with a program that doesn't support somethingas vital as multiple clients (see fork(2)). I also hard-coded the families used, the specified services, and other goodies (such as broadcasting and general UDP which are not "hard-coded" but "not-coded"). These are for you to learn on your own can come highly recommended as interesting subjects to take up study (especially as just a hobby).
This, I hope, will send you out of your dark room or (unfortunately) deeper into the Internet to find out socket programming information. Besides, it takes time to explain the whole concept (that's what books are for) as well as the specifics. So just read the comments and the verbose variable names to follow along. Either way I hope you enjoy the code (questions, comments, bitches, complaints to Dear 2600, I'll address them there).
Primary sources (not just the net):
TCP/IP Sockets in C by Donahoo & Calvert
Linux Socket Programming by Example by Warren W. Gay
Shout outs: The 2600tucson crew, Ashley, Noam Chomsky, Robitussin, Modest Mouse.
//***************************************************************************** // // listener.cc // // by solthae // Simple server code that allows for remote connections. // Can have various uses (honeypot, listener, mud server, etc.). // I've hardcoded it to run on localhost with no specific service being run, // in hopes that those wishing to mod it for multiple clients, specific // services, etc. will follow up and learn more on their own. // // Compile: g++ -o listener listener.cc // // Usage: ./listener 2600 & // // This will leave a process running as seen with 'ps,' listening for // connections on port 2600. //***************************************************************************** #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <netdb.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> // error() reports an error then exits program void error(const char *err) { perror(err); exit (1); } int main(int argc, char **argv) { int z; int x; struct sockaddr_in serverAddress; // AF_INET family struct sockaddr_in clientAddress; // AF_INET family unsigned short portNumber; FILE *rStream = NULL; // Read stream FILE *wStream = NULL; // Write stream int s; // Socket int c; // Client socket char buf[4096]; // IO buffer socklen_t addrlen; // For accept(2) when using g++ // Check for correct argument usage if (argc != 2) { fprintf(stderr, "Usage: %s <port number>\n", argv[0]); exit (1); } // Assign supplied argument as port number portNumber = atoi(argv[1]); // Create a TCP/IP socket to use if ((s = socket(PF_INET, SOCK_STREAM, 0)) == -1 ) error("socket(2)"); // Fill in local address structure, that'd be our server address memset(&serverAddress, 0, sizeof(serverAddress)); // Clear out struct serverAddress.sin_family = AF_INET; // Internet address family serverAddress.sin_addr.s_addr = htonl(INADDR_ANY); // Any incoming interface serverAddress.sin_port = htons(portNumber); // Local port to use // Bind to server address if ((z = bind(s, (struct sockaddr *) &serverAddress, sizeof(serverAddress))) == -1) error("bind(2)"); // Make it a listening socket if ((z = listen(s, 10)) == -1) error("listen(2)"); // The server loop for (;;) { // Wait for a connection addrlen = sizeof(clientAddress); if ((c = accept(s, (struct sockaddr *) &clientAddress, &addrlen)) == -1) error("accept(2)"); // The read stream is where the clients requests are going to be coming in // through (don't mix them up) // Create read stream if (!(rStream = fdopen(c, "r"))) { close(c); continue; } // The write stream in where you are going to print you message (like requests) // to the client (don't mix them up) // Create write stream if (!(wStream = fdopen(dup(c), "w"))) { fclose(rStream); continue; } // Set both streams to line buffered mode setlinebuf(rStream); setlinebuf(wStream); printf("-------------------------------------\n"); printf("- Put a telnet message here for fun -\n"); printf("-------------------------------------\n"); // *** NOTE TO READERS *** // This is the main workhorse of the code. // This takes requests from the client through the read stream rStream. // You then can process these 'requests' (i.e., send text, etc.) // as a 'char buf[]' (i.e., string). // // Below: // Process 1 echo's sent command. // Process 2 prints 'stringlen'. // Process 3 goes through 'buf' one-by-one printing the chars. // Enjoy making creative ways to process 'buf' from different clients. // // Process clients requests while (fgets(buf, sizeof buf, rStream)) { printf("\nEcho: %s", buf); // Process 1 printf("\nSize: %d", strlen(buf)); // Process 2 for (x = 0; x < strlen(buf); x++) printf("\n%c", buf[x]); } // Close client's connection fclose(wStream); shutdown(fileno(rStream), SHUT_RDWR); fclose(rStream); } // If control gets here there's a problem with time/space return 0; }Code: listener.cc