0

Why does this header file go into a freeze state or it does not output anything even if the server is accepting connection form other scripts/tools

tcpclient.h

#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#pragma once

int socket_desc;
struct sockaddr_in server_addr;

int init_client()
{
    socket_desc = socket(AF_INET, SOCK_STREAM, 0);  

    if (socket_desc < 0 )
    {
        printf("Failed to create socket\n");
        return -1;
    }
    return 0;
}

int connection(char *host,int port )
{

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    server_addr.sin_addr.s_addr = inet_addr(host);

    if (connect(socket_desc, (struct sockaddr*)&server_addr, sizeof(server_addr))<0)
    {
        printf("Failed to connect @ %s:%d\n",host,port);
        return -1;
    }
    printf("Connected to [%s:%d]\n",host,port);
    return 0;
}

using a main.c like so

int main()
{
    int soc = init_client();
    int con = connection("192.168.0.12",6666);
    return 0;
}

the only warning I get is that the variable soc is not used

10
  • If connect fails, check errno to see what's wrong. Use e.g. strerror to get a printable string of the error. Commented Apr 10, 2022 at 17:28
  • Also, did socket succeed? As for connect , if socket fails you need to check errno to check what problems you have. Commented Apr 10, 2022 at 17:29
  • 2
    typically a header file .h does not contain code. Commented Apr 10, 2022 at 17:30
  • @Someprogrammerdude I tried adding printf("%d\n",errno); but still no output in the console and no connection on the server Commented Apr 10, 2022 at 17:33
  • @stark I know but i am not developing a production library I am just learning here Commented Apr 10, 2022 at 17:33

1 Answer 1

1

Your program works correctly in my computer.... It's not clear what do you claim on.

Anyway, after tweaking it a bit, I have some points to comment on it. I changed the ip address to 127.0.0.1 and port to 80 and started an apache server locally to check that the server is, indeed ready to accept connections.

First I checked that the connection opened locally with a telnet(1) command (you will probably have to install it in your machine as it is not installed now by default)

$ telnet localhost 80
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
^]
telnet> close
Connection closed.
$ _

then I changed several things in your code (they should not affect the run, but they will make you trouble in the future if you don't take this path)

  • I first created a socket.h file to put prototypes for both functions, so you don't run in trouble if you later change the prototypes.

socket.h

#ifndef _SOCKET_H
#define _SOCKET_H

int init_client(void);
int connection(const char *host, int port);

#endif /* _SOCKET_H */
As you see, I changed the parameter `host` into a `const char *` type, so the compiler knows that the string is not changed inside the function and can optimize calls, based on that.
  • Second, I #included the file in both modules, so if you change the interface, both modules (provider and consumer) know about the interface change.

socket.c

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

I used the last two includes to use strerror(errno), that gives you the reason for the connection error (mainly being a connection refused error)


#include "socket.h"

int socket_desc = -1;
struct sockaddr_in server_addr;

this is not good practice. A better solution would be to return the socket and pass it as parameter to the connection call below. Using global variables will run you into trouble later if you want to use these functions in different threads, as the socket_desc global variable is common to all the threads you will have.


int init_client(void)
{
    socket_desc = socket(AF_INET, SOCK_STREAM, 0);

    if (socket_desc < 0 )
    {
        printf("Failed to create socket, %s\n",
            strerror(errno));
        return -1;
    }
    return 0;
}

int connection(const char *host, int port)
{

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    server_addr.sin_addr.s_addr = inet_addr(host);

    printf("trying connect to %s:%d\n", host, port);

    if (connect(socket_desc, (struct sockaddr*) &server_addr, sizeof(server_addr))<0)
    {
        printf("Failed to connect @ %s:%d, %s\n",
                host, port, strerror(errno));
        return -1;

printing here the reason of the non connection is a good idea to know what is happening.

    }
    printf("Connected to [%s:%d]\n",host,port);
    return 0;
}

A better solution would be the following:

socket.c

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

#include "socket.h"

int init_client(void)
{
    int socket_desc = socket(AF_INET, SOCK_STREAM, 0);

    if (socket_desc < 0 )
    {
        printf("Failed to create socket: %s\n",
            strerror(errno));
    }
    return socket_desc;
}

int connection(int sd, const char *host, int port)
{

    struct sockaddr_in server_addr;

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    server_addr.sin_addr.s_addr = inet_addr(host);

    printf("trying connect to %s:%d\n", host, port);

    if (connect(sd, (struct sockaddr*) &server_addr, sizeof(server_addr)) < 0) {
        printf("Failed to connect @ %s:%d, %s\n",
                host, port, strerror(errno));
        return -1;
    }
    printf("Connected to [%s:%d]\n", host, port);
    return 0;
}

where socket.h becomes:

socket.h

#ifndef _SOCKET_H
#define _SOCKET_H

int init_client(void);
int connection(int socket_descriptor, const char *host, int port);

#endif /* _SOCKET_H */

this modifications, made that calling the program to localhost:80 resulted in:

$ a.out
trying connect to 127.0.0.1:80
Connected to [127.0.0.1:80]
$ _

while using 79 as the port resulted in:

$ a.out
trying connect to 127.0.0.1:79
Failed to connect @ 127.0.0.1:79, Connection refused
Failed connection(), Connection refused
$ _
Sign up to request clarification or add additional context in comments.

4 Comments

thank you very much for the detailed explanation and extra tips but can you elaborate more on the second point I don't fully get what you mean by Second, I #included the file in both modules, so if you change the interface, both modules (provider and consumer) know about the interface change.
Including the #include directive in both files (client and provider) warrants that the definition in provider module and client module is exactly the same (for example, you defined the init_client() using an empty parameter list, which means undefined parameter list, not an empty one --- which is defined specifying void as the parameter list) That approach ensures that if you change one side only, you'll get an error.
can I use #pragma once instead of using #ifndef ... #endif
you can, but probably you will run in trouble if you get a compiler that doesn't understand that pragma. I'm not sure if Visual C understands it, for example. Today all popular compilers are derived in some way or another from GCC or CLANG, but despite of that fact, you can run in an environment in which you have to use a compiler that doesn't support the #pragma once.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.