0

I am trying to implement a simple chat using socket programming where the 'enter' key sends the response to the from the client to the server or vice versa. The code below works as expected with a special character such as '*' as the buffer but when I try to use '\n' the messages are never sent. I must be implementing the 'enter' portion incorrectly. Any ideas on how to fix this issue?

Server:

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

using namespace std;

int main()
{

    int client, server;
    int portNum = 1500;
    bool isExit = false;
    int bufsize = 1024;
    char buffer[bufsize];

    struct sockaddr_in server_addr;
    socklen_t size;

    client = socket(AF_INET, SOCK_STREAM, 0);

    if (client < 0)
    {
        cout << "\nError establishing socket..." << endl;
        exit(1);
    }

    cout << "\n=> Socket server has been created..." << endl;

    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htons(INADDR_ANY);
    server_addr.sin_port = htons(portNum);


    if ((bind(client, (struct sockaddr*)&server_addr,sizeof(server_addr))) < 0)
    {
        cout << "=> Error binding connection, the socket has already been established..." << endl;
        return -1;
    }


    size = sizeof(server_addr);
    cout << "=> Looking for clients..." << endl;

    listen(client, 1);


    int clientCount = 1;
    server = accept(client,(struct sockaddr *)&server_addr,&size);

    // first check if it is valid or not
    if (server < 0)
        cout << "=> Error on accepting..." << endl;

    while (server > 0)
    {
        strcpy(buffer, "=> Server connected...\n");
        send(server, buffer, bufsize, 0);
        cout << "=> Connected with the client #" << clientCount << ", you are good to go..." << endl;
        cout << "\n=> Enter # to end the connection\n" << endl;

        cout << "Client: ";
        do {
            recv(server, buffer, bufsize, 0);
            cout << buffer << " ";
            if (*buffer == '#') {
                *buffer = '\n';
                isExit = true;
            }
        } while (*buffer != '\n');

        do {
            cout << "\nServer: ";
            do {
                cin >> buffer;
                send(server, buffer, bufsize, 0);
                if (*buffer == '#') {
                    send(server, buffer, bufsize, 0);
                    *buffer = '\n';
                    isExit = true;
                }
            } while (*buffer != '\n');

            cout << "Client: ";
            do {
                recv(server, buffer, bufsize, 0);
                cout << buffer << " ";
                if (*buffer == '#') {
                    *buffer = '\n';
                    isExit = true;
                }
            } while (*buffer != '\n');
        } while (!isExit);

        cout << "\n\n=> Connection terminated with IP " << inet_ntoa(server_addr.sin_addr);
        close(server);
        cout << "\nGoodbye..." << endl;
        isExit = false;
        exit(1);
    }

    close(client);
    return 0;
}

Client:

#include <iostream>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>

using namespace std;

int main()
{

    int client;
    int portNum = 1500; // NOTE that the port number is same for both client and server
    bool isExit = false;
    int bufsize = 1024;
    char buffer[bufsize];
    char* ip = "192.168.0.8";

    struct sockaddr_in server_addr;

    client = socket(AF_INET, SOCK_STREAM, 0);

    if (client < 0)
    {
        cout << "\nError establishing socket..." << endl;
        exit(1);
    }


    cout << "\n=> Socket client has been created..." << endl;

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(portNum);

    if (connect(client,(struct sockaddr *)&server_addr, sizeof(server_addr)) == 0)
        cout << "=> Connection to the server port number: " << portNum << endl;


    cout << "=> Awaiting confirmation from the server..." << endl; //line 40
    recv(client, buffer, bufsize, 0);
    cout << "=> Connection confirmed, you are good to go...";

    cout << "\n\n=> Enter # to end the connection\n" << endl;

    do {
        cout << "Client: ";
        do {
            cin >> buffer;
            send(client, buffer, bufsize, 0);
            if (*buffer == '#') {
                send(client, buffer, bufsize, 0);
                *buffer = '\n';
                isExit = true;
            }
        } while (*buffer != '\n');

        cout << "Server: ";
        do {
            recv(client, buffer, bufsize, 0);
            cout << buffer << " ";
            if (*buffer == '#') {
                *buffer = '\n';
                isExit = true;
            }

        } while (*buffer != '\n');
        cout << endl;

    } while (!isExit);

    cout << "\n=> Connection terminated.\nGoodbye...\n";

    close(client);
    return 0;
}

EDIT: I made the change referenced in the answer below and I am still not getting the expected results.

Here is what happens when I run the Server and Client: enter image description here

When I press Enter the message is not being sent to the Server. However, when I ran this same code with "buffer = '*'" it works as expected.

Eric Walters
  • 251
  • 3
  • 20
  • 1
    At least check return values of send and recv. Also, you are sending your entire buffer, even when most of it will be trash, which I supoose works, but is kinda... quaint. – hyde Jan 26 '16 at 18:01
  • I just compiled and ran your most recent code (as of this comment), and sending/receiving data works. Your problem is an application logic error, not a technical misuse of the socket API. What behavior are you attempting to achieve? When you send from the client, do you expect it to immediately echo on the server, and vice versa? – Aaron Burke Jan 26 '16 at 22:18

3 Answers3

2

I am unsure what your code should do.

*buffer == '\n';

Is this your error?

It is located in the server code:

        cout << "Client: ";
        do {
            recv(server, buffer, bufsize, 0);
            cout << buffer << " ";
            if (*buffer == '#') {
                *buffer == '\n';
                isExit = true;
            }
        } while (*buffer != '\n');

I think you meant to write:

        cout << "Client: ";
        do {
            recv(server, buffer, bufsize, 0);
            cout << buffer << " ";
            if (*buffer == '#') {
                *buffer = '\n';
                isExit = true;
            }
        } while (*buffer != '\n');

Take a look at the topic of test driven development.

Johannes
  • 5,639
  • 5
  • 52
  • 84
  • Thank you for response! I made that change and added additional detail above about the problem I'm experiencing. The message is not traveling to the server properly. – Eric Walters Jan 26 '16 at 19:30
1

@Johannes has identified the likely bug (an all-too-common one!) that is the culprit of the behavior you're witnessing, but you definitely need to listen to your compiler. When I compile your server source with clang (3.4.2 on CentOS 6) with all warnings enabled, I get the following output:

$ clang -Wall -lstdc++ server.cpp

server.cpp:93:29: warning: equality comparison result unused [-Wunused-comparison]
                    *buffer == '\n';
                    ~~~~~~~~^~~~~~~
server.cpp:93:29: note: use '=' to turn this equality comparison into an assignment
                    *buffer == '\n';
                            ^~
                            =
1 warning generated.

$ clang -Wall -lstdc++ client.cpp

client.cpp:21:16: warning: conversion from string literal to 'char *' is deprecated [-Wc++11-compat-deprecated-writable-strings]
    char* ip = "192.168.0.8";
               ^
client.cpp:21:11: warning: unused variable 'ip' [-Wunused-variable]
    char* ip = "192.168.0.8";
          ^
2 warnings generated.

You could also use any number of static analysis tools (a quick search gives me this wiki) to improve your code quality with minimal effort.

Community
  • 1
  • 1
Aaron Burke
  • 468
  • 3
  • 12
  • I made that change (see above) and I'm still not getting the expected results. – Eric Walters Jan 26 '16 at 19:52
  • You need to check the return values of your network calls to see where it's failing. Is it possible the application is being blocked by a local firewall? – Aaron Burke Jan 26 '16 at 20:25
  • 1
    Adding `-Wextra` warning flag for the compiler (*clang* or *gcc*) would be good too. – hyde Jan 26 '16 at 21:57
-1
if(inet_pton(AF_INET, "server_ip", &server_addr.sin_addr)<=0)  
    { 
        cout<<"Invalid address/ Address not supported"<<endl;
        return -1; 
    }