Ralph
Ralph

Reputation: 473

Socket consistently disconnecting C++

I have a client and server set up to talk to each other. But every time I try to echo back to the client the socket seems to have disconnected. Much of the code is adapted from a sockets tutorial over at yolinux. Also, I'm running this remotely over ssh.

Client:

#include <cerrno>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/select.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <iostream>
#include <cstdlib>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <string>
#include <sstream>

using namespace std;

main(int argc, char *argv[])
{

    if (argc != 3) {
        cout << "exiting\n";
        exit(EXIT_FAILURE);
    }

    struct sockaddr_in remoteSocketInfo;
    struct hostent *hPtr;
    int socketHandle;
    char *remoteHost = argv[1];
    int portNumber = atoi(argv[2]);

    cout << "Welcome!\n";

    // create socket

    if ((socketHandle = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0)
    {
            cout << "Socket creation failed.\n";
            close(socketHandle);
            exit(EXIT_FAILURE);
    }
    cout << "Socket created!\n";

    bzero(&remoteSocketInfo, sizeof(sockaddr_in)); // Clear structure memory

    if ((hPtr = gethostbyname(remoteHost)) == NULL)
    {
        cerr << "System DN name resolution not configured properly.\n";
        cerr << "Error number: " << ECONNREFUSED << endl;
        exit(EXIT_FAILURE);
    }

    // Load system information for remote socket server into socket data structures

    memcpy((char*)&remoteSocketInfo.sin_addr, hPtr->h_addr, hPtr->h_length);
    remoteSocketInfo.sin_family = AF_INET;
    remoteSocketInfo.sin_port = htons((u_short)portNumber); // set port number

    if (connect(socketHandle, (struct sockaddr *)&remoteSocketInfo, sizeof(sockaddr_in)) < 0) {
        cout << "connection failed\n";
        close(socketHandle);
        exit(EXIT_FAILURE);
    }

    cout << "Connected!\n";

    string input;
    int message;
    while (1) {
        cout << "Please indicate rotation amount:";
        cin >> input;
        if (input == "exit") {
            close(socketHandle);
            break;
        }

        char buf[input.length()+1];
        const char *conv_input = input.c_str();
        strcpy(buf, conv_input);
        int bytes_sent = 0;
        if ( (bytes_sent = send(socketHandle, buf, strlen(buf)+1, 0)) < 0) {
            char buffer[256];
            char * errorMessage = strerror_r( errno, buffer, 256);
            cout << errorMessage << endl;
            close(socketHandle);
            exit(EXIT_FAILURE);
        }
        cout << "bytes sent: " << bytes_sent << endl;

        int rc;
        char buf2[input.length()+1];
        rc = recv(socketHandle, buf2, strlen(buf)+1, 0);
        buf[rc] = (char)NULL; // Null terminate string


        cout << "received: " << buf2 << endl;
        cout << "bytes received: " << rc << endl;

        }

    close(socketHandle);

    }

Server:

#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <strings.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <cstring>
#define MAXHOSTNAME 256

using namespace std;

main(int argc, char *argv[])
{
    if (argc != 2) {
        cout << "not enough arguments, ex: ./CaesarCipherServer 9876\n";
        exit(EXIT_FAILURE);
    }

    struct sockaddr_in socketInfo;
    char sysHost[MAXHOSTNAME+1]; // Hostname of this computer we're running on
    struct hostent *hPtr;
    int portNumber = atoi(argv[1]);
    int sock;

    bzero(&socketInfo, sizeof(sockaddr_in)); // Clear structure memory

    // Get system information
    gethostname(sysHost, MAXHOSTNAME); // Get this computer's hostname

    if ((hPtr = gethostbyname(sysHost)) == NULL)
    {
        cerr << "System hostname misconfigured." << endl;
        exit(EXIT_FAILURE);
    }

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        close(sock);
        exit(EXIT_FAILURE);
    }

    // Load system info into socket data structures

    socketInfo.sin_family = AF_INET;
    socketInfo.sin_addr.s_addr = htonl(INADDR_ANY); // Use any addr available
    socketInfo.sin_port = htons(portNumber); // Set port number

    // Bind the socket to a local socket address

     if (bind(sock, (struct sockaddr *) &socketInfo, sizeof(socketInfo)) < 0)
     {
         close(sock);
         perror("bind");
         exit(EXIT_FAILURE);
     }

     cout << "listening for initial connection \n";
     listen(sock, 1);

     int sockConn;
     if ((sockConn = accept(sock, NULL, NULL)) < 0)
     {
         exit(EXIT_FAILURE);
     }  else {
         cout << "connection accepted!\n";
     }

     int rc = 0;
     char buf[512];

     cout << "about to receive message... \n";
     // rc is number of chars returned
     rc = recv(sockConn, buf, 512, 0);
     buf[rc] = (char)NULL; // Null terminate string

     cout << "received: " << buf << endl;
     cout << "rc: " << rc << endl;


     int bytes_sent;
     if ((bytes_sent = send(sock, buf, rc, MSG_NOSIGNAL)) < 0) {
         cout << "error sending\n";
         close(sock);
         exit(EXIT_FAILURE);
     }

     cout << "bytes sent: " << bytes_sent << endl;

     close(sock);
}

Client Output:

./CaesarCipherClient cs-ssh 9876
Welcome!
Socket created!
socket handle : 3
Connected!
Please indicate rotation amount:5
bytes sent: 2
received: 
bytes received: 0
Please indicate rotation amount:

Server Output:

./CaesarCipherServer 9876
listening for initial connection 
connection accepted!
about to receive message... 
received: 5
rc: 2
error sending

If the MSG_NOSIGNAL flag isn't specified, the server crashes at send(), which means the socket has disconnected at the other end. Why would the socket consistently disconnect after a send()/recv() pair?

I apologize for any poor readability/style/pure stupidity in my submission.

Thank you for your help!

Upvotes: 3

Views: 391

Answers (1)

Sergiy Shvets
Sergiy Shvets

Reputation: 180

In your server, you are using:

 if ((bytes_sent = send(sock, buf, rc, MSG_NOSIGNAL)) < 0) {
         cout << "error sending\n";
         close(sock);
         exit(EXIT_FAILURE);
     }

Here, sock is the listening socket, not the accepted client socket. You need to replace sock with sockCon instead (which you are using in your recv() function call, and that is working).

Upvotes: 6

Related Questions