Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Create a TCP socket connect using C to a predefined port

Tags:

c

tcp

sockets

I have a very simple question. I want to test whether a particular port is currently under use or not. For this, I want to bind a TCP socket to the port, if the connection is refused means the port is in use and if not that mean the port is free.

Can someone please tell me how can I write the TCP socket code in C? I am on a solaris platform.

I know its very basic. But I appreciate your help. Thanks in advance.

like image 917
krabhishek Avatar asked Oct 15 '08 09:10

krabhishek


2 Answers

The call to bind function will return -1 if there is an error. This includes the case where the address is already in use.

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PORT 12345

int main()
{
  struct sockaddr_in addr;
  int fd;

  fd = socket(AF_INET, SOCK_STREAM, 0);
  if(fd == -1)
  {
      printf("Error opening socket\n");
      return -1;
  }

  addr.sin_port = htons(PORT);
  addr.sin_addr.s_addr = 0;
  addr.sin_addr.s_addr = INADDR_ANY;
  addr.sin_family = AF_INET;

  if(bind(fd, (struct sockaddr *)&addr,sizeof(struct sockaddr_in) ) == -1)
  {
      printf("Error binding socket\n");
      return -1;
  }

  printf("Successfully bound to port %u\n", PORT);
}
like image 167
Joel Cunningham Avatar answered Sep 27 '22 15:09

Joel Cunningham


It depends slightly on exactly what you're trying to test.

Using bind() in the way that joelc suggested will tell you if the port is open on any interface on your machine. Although to be thorough, you should not only be checking the return value from bind(), but also checking errno == EADDRINUSE.

ie. (modification of joelc's code)


if(bind(socket, (struct sockaddr *)&sin,sizeof(struct sockaddr_in) ) == -1)
{
    if( errno == EADDRINUSE )
    {
        // handle port already open case
    }
    else
    {
        // handle other errors
    }
}

By changing the address used in the line: eg.


    sin.sin_addr.s_addr = inet_addr("192.168.1.1");

...you can test whether a port is available on a specific interface.

Be aware though that this isn't a perfect test for port state. If another process had the port open and was terminated before it gracefully closed the port (ie. before calling close() on the socket) then you will usually get the same EADDRINUSE error. (depending on whether the SO_REUSEADDR option had been set on the socket)

(side note: unless your test application is running with sufficient privileges you won't be able to bind() to any ports below 1024)

As Anonymous suggested, you can also have a look at netstat. This will give you all of the same information that you can get by repeatedly calling bind() much more quickly and without any of the side effects (like it doesn't have to actually bind to the ports, which would make them unusable to any other processes). Just calling netstat -a --numeric-ports -t and analysing the output should give you everything that you're after.

A comment on moogs suggestion though - calling telnet on each port will only tell you if a socket is listening on that port - not whether it's actually open.

like image 36
Andrew Edgecombe Avatar answered Sep 27 '22 15:09

Andrew Edgecombe