//***************************************************************************** // // 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 #include #include #include #include #include #include #include #include // 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 \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; }