c++socketstcpnetwork-programmingtcpsocket

Failed TCP Socket Communication


I tried to communicate with my friend on terminal using TCP socket. But i failed.I think i can connect server but it cannot be. i gave ip address and port info when i run program, then i waited long time for entering message and i entered. After that there was nothing on server side.

server.cpp

#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h> 
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#include <string> 
using namespace std;

int main(int argc, char* argv[]){
 if (argc != 3){
 cout << "Usage: ./server <CLIENT_IP_ADDRESS> <PORT>\n"; 
 return -1;
 }

char* client_ip_address = argv[1];
int port = stoi(argv[2]);

// Create a socket for server
int serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket == -1) { // If the socket creation is unsuccessful, it returns -1
    cout << "Socket creation has failed.\n";
    return -1;
}

// Address and Port informations
sockaddr_in serverAddress; //sockaddr_in: It is the data type that is used to store the address of the socket.
serverAddress.sin_family = AF_INET; 
serverAddress.sin_port = htons(port); //This function is used to convert the unsigned int from machine byte order to network byte order.
serverAddress.sin_addr.s_addr = inet_addr(client_ip_address);


// Socket binding
bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)); 
   

if (listen(serverSocket, 10) == -1) {
    cout << "Connection listening error: " <<endl;
    close(serverSocket);
    return -1;
}

std::cout << "The server has been started. Listening for connections...\n";

sockaddr_in clientAddr;
socklen_t clientSize = sizeof(clientAddr);
int clientSocket = accept(serverSocket, (sockaddr*)&clientAddr, &clientSize);

while (true) {
    
    char messageBuffer[1024] = {0};
    recv(clientSocket, messageBuffer, sizeof(messageBuffer), 0);
    cout << "Message from client: " << messageBuffer << endl;

    if (strcmp(messageBuffer, "Fin") == 0) {
        close(serverSocket);
        break;
    }
    // Sending a message to the client.
    char buffer[1024] = {0};
    cout << "Enter a message: ";
    cin.getline(buffer, sizeof(buffer));
    send(clientSocket, buffer, strlen(buffer), 0);
    if (strcmp(buffer, "Fin") == 0) {
        close(serverSocket);
        break;
    }
}

std::cout << "(Fin) message received. Server is shutting down...\n";

return 0;
}

client.cpp

#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h> 
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#include <string> 
using namespace std;

int main(int argc, char* argv[]){
 if (argc != 3){
 cout << "Usage: ./client <SERVER_IP_ADRES> <PORT>\n"; 
 return -1;
 }


char* server_ip_address = argv[1];
int port = stoi(argv[2]);

// Create a socket for client
int clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket == -1) {
    cout << "Socket creation has failed.\n";
    return -1;
}

// Address and Port informations
sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(port);
server_address.sin_addr.s_addr = inet_addr(server_ip_address);


// Connecting server
  connect(clientSocket, (struct sockaddr*)&server_address, sizeof(server_address));

while (true) {
    // Kullanıcıdan bir mesaj al
    char messageBuffer[1024] = {0};
    std::cout << "Enter a message: ";
    cin.getline(messageBuffer, sizeof(messageBuffer));
    // Sending a message to the server.
    send(clientSocket, messageBuffer, strlen(messageBuffer), 0);
    if (string(messageBuffer)== "Fin"){
        close(clientSocket);
        break;
    }
    
    char buffer[1024] = {0};
    ssize_t bytesReceived = recv(clientSocket, buffer, sizeof(buffer), 0);
    cout << "Message from server: " << string(buffer, bytesReceived) << std::endl;
    if (string(buffer)== "Fin"){
        close(clientSocket);
        break;
    }

    }
    std::cout << "(Fin) message received. Client is shutting down...\n";


return 0;
}

I took turns waiting to communicate with my friend. I achieved this in my own local. I opened a new tab in my terminal and ran and tested both the server and the client from there, it worked without any problems. I can't do this with my friend from another city.


Solution

  • Since your friend is in another city, they are likely on a different network (unless you setup a private VPN between your two computers).

    When communicating with computers on different networks, there are additional steps you need to do outside of your code:


    As for your code itself, there are several problems with it.

    In the server:

    In the client:

    Try something more like this:

    server.cpp

    #include <iostream>
    #include <sys/socket.h>
    #include <netinet/in.h> 
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string> 
    #include <cstdint>
    using namespace std;
        
    bool readRaw(int sckt, void* buffer, size_t bufsize) {
        char *ptr = static_cast<char*>(buffer);
        while (bufsize > 0) {
            ssize_t numBytes = recv(sckt, ptr, bufsize, 0);
            if (numBytes < 0) {
                cout << "Read error: " << errno << '\n';
                return false;
            }
            if (numBytes == 0) {
                cout << "Client disconnected\n";
                return false;
            }
            ptr += numBytes;
            bufsize -= numBytes;
        }
        return true;
    }
    
    bool sendRaw(int sckt, const void* buffer, size_t bufsize) {
        const char *ptr = static_cast<const char*>(buffer);
        while (bufsize > 0) {
            ssize_t numBytes = send(sckt, ptr, bufsize, 0);
            if (numBytes < 0) {
                cout << "Send error: " << errno << '\n';
                return false;
            }
            ptr += numBytes;
            bufsize -= numBytes;
        }
        return true;
    }
    
    bool readUint32(int sckt, uint32_t &value) {
        if (!readRaw(sckt, &value, sizeof(value))) return false;        
        value = ntohl(value);
        return true;
    }
    
    bool sendUint32(int sckt, uint32_t value) {
        value = htonl(value);
        return sendRaw(sckt, &value, sizeof(value)));
    }
    
    bool readString(int sckt, string &message) {
        message.clear();
        uint32_t len;
        if (!readUint32(sckt, len)) return false;
        message.resize(len);
        return readRaw(sckt, message.data(), len);
    }   
    
    bool sendString(int sckt, const string &message) {
        uint32_t len = message.size();
        if (!sendUint32(len)) return false;
        return sendRaw(sckt, message.c_str(), len);
    }
    
    /* alternatively:
    
    bool readString(int sckt, string &message) {
        char buffer[1024], ch;
        size_t len = 0;
        message.clear();
        while (true) {
            if (!readRaw(sckt, &ch, 1)) return false;
            if (ch == '\0') {
                if (len > 0) message.append(buffer, len);
                break;
            }
            if (len == sizeof(buffer)) {
                message.append(buffer, len);
                len = 0;
            }
            buffer[len++] = ch;
        }
        return true;    
    }
    
    bool sendString(int sckt, const string &message) {
        return sendRaw(sckt, message.c_str(), message.size()+1);    
    }
    
    */
    
    int main(int argc, char* argv[]) {
        if (argc != 3) {
            cout << "Usage: ./server <LISTEN_IP_ADDRESS> <PORT>\n"; 
            return -1;
        }
        
        char* listen_ip_address = argv[1];
        int port = stoi(argv[2]);
        
        int serverSocket = socket(AF_INET, SOCK_STREAM, 0);
        if (serverSocket < 0) {
            cout << "Socket creation error: " << errno << '\n';
            return -1;
        }
        
        sockaddr_in serverAddress; //sockaddr_in: It is the data type that is used to store the address of the socket.
        serverAddress.sin_family = AF_INET; 
        serverAddress.sin_port = htons(port); //This function is used to convert the unsigned int from machine byte order to network byte order.
        serverAddress.sin_addr.s_addr = inet_addr(listen_ip_address);
        
        if (bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) < 0) {
            cout << "Socket bind error: " << errno << '\n';
            close(serverSocket);
            return -1;
        }
    
        if (listen(serverSocket, 1) == -1) {
            cout << "Socket listen error: " << errno << '\n';
            close(serverSocket);
            return -1;
        }
        
        cout << "The server has been started. Listening for connection...\n";
        
        sockaddr_in clientAddr;
        socklen_t clientSize = sizeof(clientAddr);
    
        int clientSocket = accept(serverSocket, (sockaddr*)&clientAddr, &clientSize);
        if (clientSocket < 0) {
            cout << "Connection accept error: " << errno << '\n';
            close(serverSocket);
            return -1;
        }
    
        cout << "Client connected\n";
    
        while (true) {
            
            std::string message;
            if (!readString(clientSocket, message))
                break;
    
            cout << "Message from client: " << message << '\n'; 
    
            if (message == "Fin")
                break;
    
            message.clear();
    
            cout << "Enter a message: ";
            if (!getline(cin, message))
                break;
    
            if (!sendString(clientSocket, message))
                break;
    
            if (message == "Fin")
                break;
        }
        
        cout << "Server is shutting down...\n";
        close(serverSocket);
        
        return 0;
    }
    

    client.cpp

    #include <iostream>
    #include <sys/socket.h>
    #include <netinet/in.h> 
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string> 
    #include <cstdint>
    using namespace std;
        
    bool readRaw(int sckt, void* buffer, size_t bufsize) {
        char *ptr = static_cast<char*>(buffer);
        while (bufsize > 0) {
            ssize_t numBytes = recv(sckt, ptr, bufsize, 0);
            if (numBytes < 0) {
                cout << "Read error: " << errno << '\n';
                return false;
            }
            if (numBytes == 0) {
                cout << "Server disconnected\n";
                return false;
            }
            ptr += numBytes;
            bufsize -= numBytes;
        }
        return true;
    }
    
    bool sendRaw(int sckt, const void* buffer, size_t bufsize) {
        const char *ptr = static_cast<const char*>(buffer);
        while (bufsize > 0) {
            ssize_t numBytes = send(sckt, ptr, bufsize, 0);
            if (numBytes < 0) {
                cout << "Send error: " << errno << '\n';
                return false;
            }
            ptr += numBytes;
            bufsize -= numBytes;
        }
        return true;
    }
    
    bool readUint32(int sckt, uint32_t &value) {
        if (!readRaw(sckt, &value, sizeof(value))) return false;        
        value = ntohl(value);
        return true;
    }
    
    bool sendUint32(int sckt, uint32_t value) {
        value = htonl(value);
        return sendRaw(sckt, &value, sizeof(value)));
    }
    
    bool readString(int sckt, string &message) {
        message.clear();
        uint32_t len;
        if (!readUint32(sckt, len)) return false;
        message.resize(len);
        return readRaw(sckt, message.data(), len);
    }
    
    bool sendString(int sckt, const string &message) {
        uint32_t len = message.size();
        if (!sendUint32(len)) return false;
        return sendRaw(sckt, message.c_str(), len);
    }
    
    /* alternatively:
    
    bool readString(int sckt, string &message) {
        char buffer[1024], ch;
        size_t len = 0;
        message.clear();
        while (true) {
            if (!readRaw(sckt, &ch, 1)) return false;
            if (ch == '\0') {
                if (len > 0) message.append(buffer, len);
                break;
            }
            if (len == sizeof(buffer)) {
                message.append(buffer, len);
                len = 0;
            }
            buffer[len++] = ch;
        }
        return true;    
    }
    
    bool sendString(int sckt, const string &message) {
        return sendRaw(sckt, message.c_str(), message.size()+1);    
    }
    
    */
    
    int main(int argc, char* argv[]){
        if (argc != 3){
            cout << "Usage: ./client <SERVER_IP_ADRES> <PORT>\n"; 
            return -1;
        }
    
        char* server_ip_address = argv[1];
        int port = stoi(argv[2]);
    
        int clientSocket = socket(AF_INET, SOCK_STREAM, 0);
        if (clientSocket < 0) {
            cout << "Socket creation error: " << errno << '\n';
            return -1;
        }
        
        sockaddr_in server_address;
        server_address.sin_family = AF_INET;
        server_address.sin_port = htons(port);
        server_address.sin_addr.s_addr = inet_addr(server_ip_address);
        
        if (connect(clientSocket, (struct sockaddr*)&server_address, sizeof(server_address)) < 0) {
            cout << "Socket connect error: " << errno << '\n';
            close(clientSocket);
            return -1;
        }
        
        while (true) {
    
            cout << "Enter a message: ";
    
            string message;
            if (!getline(cin, message))
                break;
    
            if (!sendString(clientSocket, message))
                break;
            
            if (message == "Fin")
                break;
            
            if (!readString(clientSocket, message))
                break;
            
            cout << "Message from server: " << meessage << '\n';
    
            if (message == "Fin")
                break;
        }
        
        cout << "Client is shutting down...\n";
        close(clientSocket);
        
        return 0;
    }