1

I am trying to write a TCP Echo program that should open a TCP server socket, accept at least 1 connection, and echo back any data received. At minimum, this program should launch and run on a specified port (exe: port 4444". Ideally, it would ask for a port number (from command line, command line parameter, or config file), attempt to open on that port, and report if errors occurred.

The program is supposed to be tested using the telnet command from windows or Linux, or any terminal emulator in any OS. The use connects to the running program using Telnet or Hyperterminal. Anything that gets typed in should echo back immediately.

So far I have the following:

#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <errno.h>


#define MAXCONNECTING 1000    //Max connection requests
#define BUFFERSIZE 128       //limits data sent per loop
#define ECHOPORT 4444


//Error checking function
//Will be called multiple times to check for errors throughout the code

void ERR(char *ERROR) {
    perror(ERROR);
    exit(1);
}

/****************************************************************************
 * Handles the connection. Receive/Send data from/to client
 ****************************************************************************/
void ClientHandle(int sock) {
    char buffer[BUFFERSIZE];
    int received = -1;

    //receive the data
    if ((received = recv(sock, buffer, BUFFERSIZE, 0)) < 0) {
        ERR("Failed to receive message from client");
    }

    //send data and check for more incoming data
    while (received > 0) {
        if (send(sock, buffer, received, 0) != received) {
            ERR("Failed to send data to client");
        }
        if ((received = recv(sock, buffer, BUFFERSIZE, 0)) < 0) {
            ERR("Failed to receive additional data from client");
        }
    }
    close(sock);
}

int main(int argc, char *argv[]) {
    /****************************************************************************
     * Get port number from command line and set to default port
     ****************************************************************************/
    char *endptr;
    short int port;

    if (argc == 2) {
        port = strtol(argv[1], &endptr, 0);
        if (*endptr) {
            fprintf(stderr, "EchoServer: Invalid Port Number.\n");
            exit(EXIT_FAILURE);
        }
    } else if (argc < 2) {
        port = ECHOPORT; //port 4444
    } else {
        fprintf(stderr, "EchoServer: Invalid arguments.\n");
        exit(EXIT_FAILURE);
    }

    /****************************************************************************
     * Server Configuration. Creating the socket
     ****************************************************************************/

    int serversock, clientsock;
    struct sockaddr_in echoserver, echoclient;

    if (argc != 2) {
        fprintf(stderr, "USING: echoserver Port: 4444\n");
        exit(1);
    }
    //Creating the TCP socket
    if ((serversock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
        ERR("Failed to create socket");
    }
    //Constructing the server sockaddr_in structure
    memset(&echoserver, 0, sizeof(echoserver)); //clear struct
    echoserver.sin_family = AF_INET;             //internet ip
    echoserver.sin_addr.s_addr = htonl(INADDR_ANY); //listen to any ip address
    echoserver.sin_port = htons(atoi(argv[1])); //server port


    /*****************************************************************************
     * Bind and Listen
     *****************************************************************************/
    if (bind(serversock, (struct sockaddr *) &echoserver, sizeof (echoserver)) < 0) {
        ERR("Failed to bind the server socket");
    }
    if (listen(serversock, MAXCONNECTING) < 0) {
        ERR("Failed to listen on server socket");
    }

    /*****************************************************************************
     * Accepting the transmission
     *****************************************************************************/
    while (1) {
        unsigned int clientleng = sizeof (echoclient);

        if ((clientsock = accept(serversock, (struct sockaddr *) &echoclient, &clientleng)) < 0) {
            ERR("Failed to accept connection from client");
        }
        fprintf(stdout, "Client connected: %s\n", inet_ntoa(echoclient.sin_addr));
        ClientHandle(clientsock);
    }
    return (0);
}

/*****************************************************************************************/

Can anyone see where I have went wrong? I can find the program in terminal using the command: g++ EchoServer.cpp -0 EchoServer and then followed by: ./EchoServer

The ouput only gives me: USING: echoserver Port: 4444

I am trying to telnet to it, but I am very new at this stuff. Please help!!

Zonxwedop
  • 387
  • 1
  • 3
  • 12
  • As you've written this you're supposed to give it the listening port as an argument, i.e. you'd start it as `./EchoServer 4444` . What other specific problems do you have ? – nos Jul 18 '12 at 20:42
  • Sorry I dont understand what you mean. I am very new to this stuff as yesterday was the first time I have been introduced to sockets. can you show an example? – Zonxwedop Jul 18 '12 at 21:39
  • And to answer, I specifically want to get it to where I can write a line in command prompt and hit enter and the program echo back exactly what I wrote. – Zonxwedop Jul 18 '12 at 21:49
  • I just showd you. Run it like this: `./EchoServer 4444` , and not like you said you did by `./EchoServer` Then you connect to your program using telnet to port 4444. It's still quite unclear what specific problems you're having, and whether you're asking about any of the code in partiular, or whether you're having trouble actually using that code.... – nos Jul 18 '12 at 22:17
  • Ah ok I got it. Thank you. Unfortunately, for some reason the code does not work. I compile EchoServer.cpp and the build is successful (Using NetBeans IDE). When I go to run the program, after I type ./EchoServer 4444 and hit enter, nothing really happens. I can type freely, but there is no response. This is what I see: [zcwright@lxs-sm1 NASCENTSocketProgram]$ g++ EchoServer.cpp -o EchoServer [zcwright@lxs-sm1 NASCENTSocketProgram]$ ./EchoServer 4444 hello Echo back? I then get nothing back. I can see what I typed but nothing else. – Zonxwedop Jul 18 '12 at 22:46
  • Would you happen to know of any solution to the code? I have gone back and forth through the code looking for any kind of solution and I am stumped. Maybe you could try to run this code for yourself? – Zonxwedop Jul 18 '12 at 23:51

1 Answers1

0

Assuming that you have the contents of the textbox above in a file called EchoServer.cpp in the current directory, you can run the following code to demonstrate it working:

g++ EchoServer.cpp -o EchoServer

After it compiles, you will have an executable file called EchoServer in the same directory.

If you just call it, You will receive the cryptic message below, which means that to use the executable, you will have to tell it which port number to use.

USING: echoserver Port 4444

To demonstrate it working, we are going to put the process in the background. To do this, we use an ampersand (&) to turn it into a job.

EchoServer 4444 &

This should return a job number, and a process identifier (yours will be different), thus:

[1] 53912

You can see that it is running using the jobs command:

[1]+  Running                 ./EchoServer 4444 &

You can now telnet to this to see that it is working:

telnet localhost 4444

You should see:

Trying 127.0.0.1...
Client connected: 127.0.0.1
Connected to localhost.
Escape character is '^]'.

Anything you type after this will be sent back to you when you press enter or return. Try typing Hello and pressing return.

Once you are done, you can press and hold the control key and then the close square bracket key (you may have to press return afterwards). This will bring you out into a telnet prompt, and you should type quit to leave.

To close off the EchoServer executable, you can bring the job back to the foreground and stop it with a Control-C keypress. Assuming that your job was 1 (you can run jobs again to check the number), you can run the following command to bring it back to the foreground:

fg 1

You are now effectively in the EchoServer process, and pressing Control-C will end it.

That's it! You're done. You have successfully demonstrated the program working.

Jonathan
  • 25,873
  • 13
  • 66
  • 85