Author Topic: C networking, not working on 127.0.0.1  (Read 1397 times)

0 Members and 1 Guest are viewing this topic.

Offline legacy

  • Super Contributor
  • ***
  • !
  • Posts: 4415
  • Country: ch
C networking, not working on 127.0.0.1
« on: March 03, 2019, 08:03:52 pm »
so I have these two examples, a simple server and a simple client (config.h, Makefile); They work perfectly on a Linux MachineA, but they do not work on a MachineB.

MachineA(ip=192.168.1.81):
Code: [Select]
./server &
./client 127.0.0.1
Sun Mar  3 17:32:18 2019
./client 192.168.1.81
Sun Mar  3 17:32:46 2019

MachineB(ip=192.168.1.24):
Code: [Select]
./server &
./client 127.0.0.1

^C
./client 192.168.1.24

^C
the client was blocked, so I terminated the client by pressing CTRL + C


MachineB, connecting to MachineA
Code: [Select]
./client 192.168.1.81
Sun Mar  3 17:32:46 2019


so ... I am a bit perplexed  :-//
« Last Edit: March 04, 2019, 10:45:37 am by legacy »
 

Offline mrflibble

  • Super Contributor
  • ***
  • Posts: 2024
  • Country: nl
Re: C networking, not working on 127.0.0.1
« Reply #1 on: March 04, 2019, 12:27:37 am »
Presumably because you try to listen on a privileged port?  :-//

I notice that in config.h the port number is defined as 501. Certain problems might just go away when you change that to the carefully crafted port number of 10501.

Chances are pretty good that the bind() call in server.c returns -1. Since there is currently no check on this return value, this error is silently ignored, possibly causing some head scratching moments. :)

man bind:
RETURN VALUE
       On success, zero is returned.  On error, -1 is returned, and errno is set appropriately.


Checking of return values is left as an exercise for the reader. ;)
 

Offline ejeffrey

  • Super Contributor
  • ***
  • Posts: 2153
  • Country: us
Re: C networking, not working on 127.0.0.1
« Reply #2 on: March 04, 2019, 03:26:42 am »
A quick way to check this is 'netstat -l' will show you all listening sockets.  If something has bound to the socket you should be able to see it 'netstat -np' will show you the PID holding the socket.

Another possibility is that machine B already has a process bound to the port you are trying to use, or machine B has messed up firewall rules.  Checking of return values is always a good place to start diagnosing problems.

In particular, I expect that if the problem is failing to bind to a privileged port, the client should fail with a connection refused -- unless the firewall is also set up to block connection refused even on localhost.  On the other hand, if there is another server on that port that doesn't do what you expect then you could see the stall you describe.

Note: both of your links are to the server code.
 

Offline MarkF

  • Super Contributor
  • ***
  • Posts: 1741
  • Country: us
Re: C networking, not working on 127.0.0.1
« Reply #3 on: March 04, 2019, 04:43:32 am »
I wrote a TCP Socket C++ socket class years ago for a SGI, REDHAT and Windows machines.
I removed the SGI code.  So, hopefully I didn't mess anything up.
REDHAT should work for a Linux machine.

tcpSocket.h:
Code: [Select]
#ifndef __TCPSOCKET_H
#define __TCPSOCKET_H

#ifdef REDHAT
   #define INVALID_SOCKET -1
   #include <stdio.h>
   #include <unistd.h>
   #include <fcntl.h>
   #include <strings.h>
   #include <sys/types.h>
   #include <sys/ipc.h>
   #include <sys/shm.h>
   #include <sys/socket.h>
   #include <netinet/in.h>
   #include <netinet/tcp.h>
   #include <arpa/inet.h>

   #if   !defined(TRUE) || ((TRUE) != 1)
   #define  TRUE  (1)
   #endif
   #if   !defined(FALSE) || ((FALSE) != 0)
   #define  FALSE (0)
   #endif
#endif

#ifdef WIN32
   #include <stdio.h>
   #include <winsock2.h>
#endif

class tcpSocket {

public:
   tcpSocket();
   ~tcpSocket();

   int openClient(unsigned short port, char *addr);
   int openServer(unsigned short port, char *addr);
   void checkSocket(void);
   void closeSocket(void);

   // WRITE MESSAGE
   //    Return:  -1=Error writing message, >0=Number bytes written
   int writeMsg(char *msg, int size);

   // READ MESSAGE
   //    Return:  -1=Error reading message, 0=No message, >0=Number bytes read
   int readMsg(char *msg, int maxSize);

   int peek(char *msg, int size);


private:

#ifdef REDHAT
   int      sock;
   int      sockServer;
   struct sockaddr_in   local, to;
#endif

#ifdef WIN32
   SOCKET   sock;
   SOCKET   sockServer;
   struct sockaddr_in   local, to;
#endif

};

#endif


tcpSocket.cpp:
Code: [Select]
#include "tcpSocket.h"

//--------------------------------------------------------------------------------
tcpSocket::tcpSocket()
{
   sock = INVALID_SOCKET;
   sockServer = INVALID_SOCKET;
}

//--------------------------------------------------------------------------------
tcpSocket::~tcpSocket()
{
}

//--------------------------------------------------------------------------------
int tcpSocket::openClient(unsigned short port, char *addr)
{
   if (port == 0) return TRUE;

#ifdef REDHAT
   int   flags;
   int   on=1;

   if (sock == INVALID_SOCKET) {

      bzero(&to, sizeof(to));
      to.sin_family = AF_INET;
      to.sin_port = htons( port );
      to.sin_addr.s_addr = inet_addr( addr );

      sock = socket(AF_INET, SOCK_STREAM, 0);
      if (sock == -1) {
         printf("ERROR - Unable to create socket\n");
         return TRUE;
      }

      // Enable Address Reuse
      setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
      // Enable No_Delay
      setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));

      if ( connect(sock, (const sockaddr*)&to, sizeof(to)) == -1 ) {
         printf("ERROR - Unable to connect to socket\n");
         return TRUE;
      }

      // Enable Non-blocking I/O
      flags = fcntl(sock, F_GETFL, 0);
      if ( fcntl(sock, F_SETFL, flags | FNONBLOCK) == -1 ) {
         printf("ERROR - Unable to set as nonblocking socket\n");
         return TRUE;
      }

   }
   return FALSE;
#endif

#ifdef WIN32
   int      stat;
   int      on=1;
   unsigned long onl=1;
   WSADATA  wsaData;

   if (sock == INVALID_SOCKET) {

      if ( WSAStartup( 0x202, &wsaData ) == SOCKET_ERROR ) {
         WSACleanup();
         return TRUE;
      }

      sock = socket( AF_INET, SOCK_STREAM, 0 );
      if ( sock < 0 ) {
         printf("ERROR - Opening socket\n");
         WSACleanup();
         return TRUE;
      }

      to.sin_family = AF_INET;
      to.sin_port = htons( port );
      to.sin_addr.s_addr = inet_addr( addr );

      // Enable Address Reuse (MUST be before the bind!)
      stat = setsockopt( sock,
                         SOL_SOCKET,
                         SO_REUSEADDR,
                         (const char *)&on,
                         sizeof(on) );
      if ( stat == SOCKET_ERROR ) {
         printf("ERROR - Unable to enable address reuse\n");
         closesocket( sock );
         WSACleanup();
         return TRUE;
      }

      stat = connect( sock,
                      (struct sockaddr *)&to,
                      sizeof(to) );
      if ( stat == SOCKET_ERROR ) {
         printf("ERROR - Connect to socket\n");
//         fprintf(stderr,"connect() failed: %d\n",WSAGetLastError());
         closesocket( sock );
         WSACleanup();
         return TRUE;
      }

      // Enable Non-blocking I/O
      stat = ioctlsocket( sock,
                          FIONBIO,
                          &onl );
      if ( stat == SOCKET_ERROR ) {
         printf("ERROR - Unable to enable Non-blocking I/O\n");
         return TRUE;
      }

   }
   return FALSE;
#endif

}

//--------------------------------------------------------------------------------
int tcpSocket::openServer(unsigned short port, char *addr)
{
   if (port == 0) return TRUE;

#ifdef REDHAT
   int   flags;
   int   on=1;
   int   len;
   struct sockaddr_in   clientAddr;

   if (sockServer == INVALID_SOCKET && sock == INVALID_SOCKET) {

      bzero(&local, sizeof(local));
      local.sin_family = AF_INET;
      local.sin_port = htons( port );
      local.sin_addr.s_addr = (in_addr_t)inet_addr("0.0.0.0");

      bzero(&to, sizeof(to));
      to.sin_family = AF_INET;
      to.sin_port = htons( port );
      to.sin_addr.s_addr = inet_addr( addr );

      sockServer = socket(AF_INET, SOCK_STREAM, 0);
      if (sockServer == INVALID_SOCKET) {
         printf("ERROR - Unable to create socket\n");
         return TRUE;
      }

      // Enable Address Reuse
      setsockopt(sockServer, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
      // Enable No_Delay
      setsockopt(sockServer, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));

      if ( bind(sockServer, (const sockaddr*)&local, sizeof(local)) == -1 ) {
         printf("ERROR - Unable to bind to socket\n");
         return TRUE;
      }

      if ( listen(sockServer,0) == -1) {
         printf("ERROR - Unable to listen to socket\n");
         return TRUE;
      }

      // Get client
      printf("Server waiting for client\n");
      len = sizeof(clientAddr);
      while (sock == INVALID_SOCKET) {
         sock = accept( sockServer,
                        (struct sockaddr *)&clientAddr,
                        (socklen_t *)&len );
      }
      printf("Accepted connection from %s, port %d\n",
                     inet_ntoa(clientAddr.sin_addr),
                     port) ;

      // Enable Non-blocking I/O
      flags = fcntl(sock, F_GETFL, 0);
      if ( fcntl(sock, F_SETFL, flags | FNONBLOCK) == -1 ) {
         printf("ERROR - Unable to set as nonblocking socket\n");
         return TRUE;
      }

   }
   return FALSE;
#endif

#ifdef WIN32
   int      stat;
   int      len;
   int      on=1;
   unsigned long onl=1;
   WSADATA  wsaData;
   struct sockaddr_in   clientAddr;

   if (sockServer == INVALID_SOCKET && sock == INVALID_SOCKET) {

      if ( WSAStartup( 0x202, &wsaData ) == SOCKET_ERROR ) {
         WSACleanup();
         return TRUE;
      }

      sockServer = socket( AF_INET, SOCK_STREAM, 0 );
      if ( sockServer < 0 ) {
         printf("ERROR - Opening socket\n");
         WSACleanup();
         return TRUE;
      }

      local.sin_family = AF_INET;
      local.sin_port = htons( port );
      local.sin_addr.s_addr = INADDR_ANY;

      to.sin_family = AF_INET;
      to.sin_port = htons( port );
      to.sin_addr.s_addr = inet_addr( addr );

      // Enable Address Reuse (MUST be before the bind!)
      stat = setsockopt( sockServer,
                         SOL_SOCKET,
                         SO_REUSEADDR,
                         (const char *)&on,
                         sizeof(on) );
      if ( stat == SOCKET_ERROR ) {
         printf("ERROR - Unable to enable address reuse\n");
         closesocket( sockServer );
         WSACleanup();
         return TRUE;
      }

      stat = bind( sockServer,
                   (struct sockaddr *)&local,
                   sizeof(local) );
      if ( stat == SOCKET_ERROR ) {
         printf("ERROR - Bind to socket\n");
         closesocket( sockServer );
         WSACleanup();
         return TRUE;
      }

      stat = listen( sockServer,
                     SOMAXCONN );
      if ( stat == SOCKET_ERROR ) {
         printf("ERROR - Listen to socket\n");
         closesocket( sockServer );
         WSACleanup();
         return TRUE;
      }

      // Get Client
      printf("Server waiting for client\n");
      len = sizeof(clientAddr);
      clientAddr.sin_port = 0;
      while (sock == INVALID_SOCKET) {
         sock = accept( sockServer,
                        (struct sockaddr *)&clientAddr,
                        &len );
      }
      printf("Accepted connection from %s, port %d\n",
                     inet_ntoa(clientAddr.sin_addr),
                     port) ;

      // Enable Non-blocking I/O
      stat = ioctlsocket( sock,
                          FIONBIO,
                          &onl );
      if ( stat == SOCKET_ERROR ) {
         printf("ERROR - Unable to enable Non-blocking I/O\n");
         return TRUE;
      }

   }
   return FALSE;
#endif

}

//--------------------------------------------------------------------------------
void tcpSocket::checkSocket(void)
{

#ifdef REDHAT
   int   len;
   int   flags;
   int   tempSock;
   struct sockaddr_in   clientAddr;

   // Enable Non-blocking I/O
   flags = fcntl(sockServer, F_GETFL, 0);
   fcntl(sockServer, F_SETFL, flags | FNONBLOCK);

   // Get Client
   len = sizeof(clientAddr);
   tempSock = accept( sockServer,
                      (struct sockaddr *)&clientAddr,
                      (socklen_t *)&len );
   if (tempSock != INVALID_SOCKET) {
      if (sock != INVALID_SOCKET) {
         shutdown(sock, 2);
         close(sock);
      }
      sock = tempSock;
   }
#endif

#ifdef WIN32
   int      len;
   unsigned long onl=1;
   SOCKET   tempSock;
   struct sockaddr_in   clientAddr;

   // Enable Non-blocking I/O
   ioctlsocket( sockServer, FIONBIO, &onl );

   // Get Client
   len = sizeof(clientAddr);
   clientAddr.sin_port = 0;
   tempSock = accept( sockServer,
                      (struct sockaddr *)&clientAddr,
                      &len );
   if (tempSock != INVALID_SOCKET) {
      if (sock != INVALID_SOCKET) {
         shutdown( sock, SD_BOTH );
         closesocket( sock );
      }
      sock = tempSock;
   }
#endif

}

//--------------------------------------------------------------------------------
void tcpSocket::closeSocket(void)
{

#ifdef REDHAT
   if (sockServer != INVALID_SOCKET) {
      shutdown(sockServer, 2);
      close(sockServer);
      sockServer = INVALID_SOCKET;
   }
   if (sock != INVALID_SOCKET) {
      shutdown(sock, 2);
      close(sock);
      sock = INVALID_SOCKET;
   }
#endif

#ifdef WIN32
   if (sockServer != INVALID_SOCKET) {
      shutdown( sockServer, SD_BOTH );
      closesocket( sockServer );
      sockServer = INVALID_SOCKET;
   }
   if (sock != INVALID_SOCKET) {
      shutdown( sock, SD_BOTH );
      closesocket( sock );
      sock = INVALID_SOCKET;
   }
   WSACleanup();
#endif

}

//--------------------------------------------------------------------------------
int tcpSocket::writeMsg(char *msg, int size)
{
   int   cnt;

   if (sock != INVALID_SOCKET) {
      cnt = sendto(sock, msg, size, 0, (struct sockaddr *)&to, sizeof(to));
      if (cnt == size) return cnt;
      else return -1;
   }
   return 0;
}

//--------------------------------------------------------------------------------
int tcpSocket::readMsg(char *msg, int maxSize)
{
   int   len;
   int   cnt;
   struct sockaddr_in   inSockAddr;

#ifdef REDHAT
   if (sock != INVALID_SOCKET) {
      len = sizeof(inSockAddr);
      cnt = recvfrom(sock, msg, maxSize, 0, (struct sockaddr *)&inSockAddr, (socklen_t *)&len);
      return cnt;
   }
#else
   if (sock != INVALID_SOCKET) {
      len = sizeof(inSockAddr);
      cnt = recvfrom(sock, msg, maxSize, 0, (struct sockaddr *)&inSockAddr, &len);
      return cnt;
   }
#endif
   return 0;
}

//--------------------------------------------------------------------------------
int tcpSocket::peek(char *msg, int size)
{
   int   len;
   int   cnt;
   struct sockaddr_in   inSockAddr;

#ifdef REDHAT
   if (sock != INVALID_SOCKET) {
      len = sizeof(inSockAddr);
      cnt = recvfrom(sock, msg, size, MSG_PEEK, (struct sockaddr *)&inSockAddr, (socklen_t *)&len);
      return cnt;
   }
#else
   if (sock != INVALID_SOCKET) {
      len = sizeof(inSockAddr);
      cnt = recvfrom(sock, msg, size, MSG_PEEK, (struct sockaddr *)&inSockAddr, &len);
      return cnt;
   }
#endif
   return 0;
}

//--------------------------------------------------------------------------------


« Last Edit: March 04, 2019, 04:51:04 am by MarkF »
 

Offline legacy

  • Super Contributor
  • ***
  • !
  • Posts: 4415
  • Country: ch
Re: C networking, not working on 127.0.0.1
« Reply #4 on: March 04, 2019, 10:30:56 am »
I notice that in config.h the port number is defined as 501. Certain problems might just go away when you change that to the carefully crafted port number of 10501.

On MachineA, it happens for every port I choose.
Neither 501 nor 10501 were already in use.

Chances are pretty good that the bind() call in server.c returns -1.

Code: [Select]
bind(listenfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr));

bind return "0"  :-//
 

Offline legacy

  • Super Contributor
  • ***
  • !
  • Posts: 4415
  • Country: ch
Re: C networking, not working on 127.0.0.1
« Reply #5 on: March 04, 2019, 10:43:59 am »
A quick way to check this is 'netstat -l' will show you all listening sockets

Code: [Select]
netstat -l
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 0.0.0.0:10501           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:ftp             0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:ssh             0.0.0.0:*               LISTEN
tcp6       0      0 [::]:ssh                [::]:*                  LISTEN
Active UNIX domain sockets (only servers)
Proto RefCnt Flags       Type       State         I-Node   Path
unix  2      [ ACC ]     STREAM     LISTENING     150      /tmp/screen/S-root/1813.console.OrangeCube
unix  2      [ ACC ]     STREAM     LISTENING     10606478 /tmp/ssh-07m4yNlPiz/agent.32253
unix  2      [ ACC ]     STREAM     LISTENING     10602276 /tmp/ssh-r2fGrglbIw/agent.1366

Code: [Select]
tcp        0      0 0.0.0.0:10501           0.0.0.0:*               LISTEN

this is ./server, so there is "something" listening on the 10501 port.
In fact, if machineB tries to connect to this server running on MachineA: it works!
The problem is that a client on MachineA cannot connect to the server running on MachineA

so ./client 127.0.0.1 doesn't work, neither ./client 192.168.1.24 (which is the IP of machineA)

Quote
If something has bound to the socket you should be able to see it 'netstat -np' will show you the PID holding the socket.

Code: [Select]
netstat -np
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 192.168.1.24:22         192.168.1.12:1528       ESTABLISHED 32266/sshd: root@no
tcp        0      0 192.168.1.24:22         192.168.1.12:1176       ESTABLISHED 1366/sshd: root@pts
tcp        0     72 192.168.1.24:22         192.168.1.12:1526       ESTABLISHED 32253/sshd: root@pt
tcp        0      0 192.168.1.24:22         192.168.1.12:1178       ESTABLISHED 1400/sshd: root@not
Active UNIX domain sockets (w/o servers)
Proto RefCnt Flags       Type       State         I-Node   PID/Program name     Path
unix  2      [ ]         STREAM     CONNECTED     5335445  9038/sshd: root@not
unix  2      [ ]         STREAM     CONNECTED     10603692 32253/sshd: root@pt
unix  2      [ ]         STREAM     CONNECTED     10599293 1400/sshd: root@not
unix  2      [ ]         STREAM     CONNECTED     10599278 1366/sshd: root@pts
unix  2      [ ]         STREAM     CONNECTED     10603719 32266/sshd: root@no

Quote
Another possibility is that machine B already has a process bound to the port you are trying to use, or machine B has messed up firewall rules.  Checking of return values is always a good place to start diagnosing problems.

Quote
Note: both of your links are to the server code.

I will fix.
 

Offline legacy

  • Super Contributor
  • ***
  • !
  • Posts: 4415
  • Country: ch
Re: C networking, not working on 127.0.0.1
« Reply #6 on: March 04, 2019, 10:59:37 am »
I wrote a TCP Socket C++

Thanks! This will be certainly helpful in the future  :D

I am trying to investigate certain programs (not written by me) that suddenly stopped to work once moved and recompiled on MachineA (it's a Pentium4 @ 3Ghz, loaded with Linux 32bit, running kernel v4.9.16). They are basically TCP/IP servers, and basically, they do not work when the client tries to connect to 127.0.0.1, that was the original problem subjected to my attention. So I wrote a super simple POC, with a couple of super simple client and server, for checking what is wrong.

It *might* be also something with the kernel: cannot be excluded!
 

Offline stmdude

  • Frequent Contributor
  • **
  • Posts: 479
  • Country: se
Re: C networking, not working on 127.0.0.1
« Reply #7 on: March 04, 2019, 11:14:27 am »
Are sure your "lo" interface is up ?
 

Online bd139

  • Super Contributor
  • ***
  • Posts: 15468
  • Country: gb
Re: C networking, not working on 127.0.0.1
« Reply #8 on: March 04, 2019, 11:45:30 am »
If you're on a Redhat or Ubuntu derivative, check that SELinux or AppArmor isn't being a dick as well. But always check those API return values!
 

Offline legacy

  • Super Contributor
  • ***
  • !
  • Posts: 4415
  • Country: ch
Re: C networking, not working on 127.0.0.1
« Reply #9 on: March 04, 2019, 01:03:02 pm »
Are sure your "lo" interface is up ?

bingo  :D

it seems there was a mistake with one of the bootstrapping script, resulting in the local loopback not properly configured

Code: [Select]
ifconfig lo
lo: flags=8<LOOPBACK>  mtu 65536
        loop  txqueuelen 1  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

So I tried this

Code: [Select]
ifconfig lo 127.0.0.1

and now ./client 127.0.0.1 works!
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 5441
  • Country: fr
Re: C networking, not working on 127.0.0.1
« Reply #10 on: March 04, 2019, 05:18:28 pm »
Additionally, I suggest checking *all* return values. And in case of error, you can then check/print 'errno' which will give you a much better hint as to what is wrong than just '-1'.
 

Offline blueskull

  • Supporter
  • ****
  • Posts: 13863
  • Country: cn
  • Power Electronics Guy
Re: C networking, not working on 127.0.0.1
« Reply #11 on: March 04, 2019, 05:27:02 pm »
My reckless rule for debugging unix programs: if it doesn't work, sudo it.
 

Online bd139

  • Super Contributor
  • ***
  • Posts: 15468
  • Country: gb
Re: C networking, not working on 127.0.0.1
« Reply #12 on: March 04, 2019, 05:34:11 pm »
Disclaimer: don't do ths if it looks like a rootkit  :-DD
 
The following users thanked this post: blueskull


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf