Search code examples
csocketstcp

Extracting last 4 characters from a string in C


Been working on a requirement to connect to the servers running on a system. I have 2 hosts, Host A and Host B. Host A("hostname: o755-gksr") contains two servers running at ports 4840 and 4841. the server running on port 4840, has mDNS enabled and advertises packets for the network. I have a server running at 4840 on Host B. It is also mDNS enabled. Now when running the client API from the Host B, it will check all the servers which are announced on the network and get the information on the list of servers. Now, on top of this API, I am trying to connect to each of the servers individually(to check if the servers are still running on a network breakdown). I am able to extract the hostname and figure the IP and try to connect to it. But I am not able to extract the port information. For eg: if URL is opc.tcp://o755-gksr:4840, I want to extract the port information in an character array or integer.. Would be really grateful for the guidance.

    printf("--Checking for network connectivity--\n");
    for (size_t i = 0; i < serverOnNetworkSize; i++) {
        UA_ServerOnNetwork *server = &serverOnNetwork[i];
        A[i] = (char *)UA_malloc(server->discoveryUrl.length + 1);
        memcpy(A[i], server->discoveryUrl.data, server->discoveryUrl.length);
        A[i][server->discoveryUrl.length] = 0;
        int length = strlen(A[i]);  //URL is of the form A[1] = "opc.tcp://o755-gksr:4840"
        //removing the port and extracting hostname to find IP
        A[i][length - 5] = '\0';
        //without initial tcp binding
        B[i] = A[i] + 10;
        // printf("Hostname: %s\n", B[i]);
        if (i != 0) { //because i=0 will be the server running on the same machine
            char ip_address[50];
            find_ip_address(B[i], ip_address);       
            socketCommunication(ip_address, B[i]);   ///,&B[i]);
        }
    }

Finding IP:

int find_ip_address(char *hostname, char *ip_address) {
    struct hostent *host_name;
    struct in_addr **ipaddress;
    int count;

    if ((host_name = gethostbyname(hostname)) == NULL) {
        herror("\nIP Address Not Found\n");
        return 1;
    } else {
        ipaddress = (struct in_addr **)host_name->h_addr_list;
        for (count = 0; ipaddress[count] != NULL; count++) {
            strcpy(ip_address, inet_ntoa(*ipaddress[count]));
            return 0;
        }
    }
    return 1;
}

socket communication:

void socketCommunication(char *ip_address, char *hostname) {
    int clientSocket, ret;
    struct  sockaddr_in serverAddr;
    char buffer[1024];
 
    clientSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (clientSocket < 0) {
        printf("Error in connection \n");
        exit(1);
    }

    //printf("Client socket is created\n");

    memset(&serverAddr, '\0', sizeof(serverAddr));
    // printf("MEMSET DONE\n");

    serverAddr.sin_port = htons(4844);
    //printf("PORT DONE\n");
    serverAddr.sin_family = AF_INET;
    //printf("afnet DONE\n");
    serverAddr.sin_addr.s_addr = inet_addr(ip_address);

    //printf("%s\n", *ip_address);

    //printf("Config done: \n");

    ret = connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
    if (ret < 0) {
        printf("LOOKS LIKE NETWORK CONNECTION HAS FAILED. HAVE A LOOK AT THE NETWORK CONNECTIVITY at host : %s\n",hostname);
        printf("----Updated Status Information----:\n");
        printf("\tHostname :%s\n", hostname);
        printf("\tStatus:CONNECTON TIMED OUT");
        //exit(1);
    }
    //printf("Connected to Server\n");
}

Currently I am hardcoding the port in socket communication. Please guide me to extract the port information from the URL so that I can pass it as parameters in the function to dynamically allocate the port to the socket communication.


Solution

  • You most likely want to use a function like strrchr(const char *, int c) . this will search for the last occurrence of a character and return a pointer to it.

    You can search for the colon and then use the pointer to copy your last 4 chars or use a function like strtol to transform the chars into an integer.

    char *p = strrchr(input_buffer, ':');
    unsigned long port = strtoul(p+1, NULL, 10);
    

    You could also use strlen to get the length of the string and use the end as your offset, however ports are in the range 0...65535 I believe? So you're most likely going to be better off with the first option, unless you know it will always be 4 digits long.