Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7754069
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 1, 20262026-06-01T12:12:55+00:00 2026-06-01T12:12:55+00:00

I am learning APUE.2e (Advanced Programming in the UNIX® Environment, Second Edition) these days

  • 0

I am learning APUE.2e (Advanced Programming in the UNIX® Environment, Second Edition) these days and have got to the chapter 16 Network IPC: sockets. When I run the program ruptime (for the client end) and ruptimed (for the server end), something weird happened. The client program shows a client command that communicates with a server to obtain the output from a
system’s uptime command, and the server program ruptimed (note the ‘d’) receives the command, exec’s the uptime command and return the output of uptime to the client. The two programs compiled OK, and I add the ruptime 4000/tcp to the file /etc/service which means the service ruptime binds to the port 4000/tcp. I ran the two programs on the same machine (Ubuntu 11.04) and the ruptimed first (of course):

$ ./ruptimed
$ ./ruptime 127.0.0.1
 21:35:48 up 13:06,  3 users,  load average: 0.56, 0.85, 0.94 

The output is what I have expected. However, when I ran:

$ ./ruptimed
$ ./ruptime 192.168.1.221
  # the terminal blocks here

The IP address 192.168.1.221 is the machine’s actual IP in the intranet. What’s wrong here? I searched the Internet, and found out it seems to need a shell script in the /etc/init.d/. Then I add a file named ruptime in the /etc/init.d/ directory. Here it is:

#! /bin/sh

### BEGIN INIT INFO
# Provides:     ruptimed
# Required-Start:   $remote_fs $syslog
# Required-Stop:    $remote_fs $syslog
# Default-Start:    2 3 4 5
# Default-Stop:     
# Short-Description:    ruptime
### END INIT INFO
start()
{
    echo "start ruptime"
    /home/tlh1987/apue-practice/tlh-practice/ruptimed
    exit 0;
}
stop()
{
    killall ruptimed
    echo "stop ruptime"
}

case "$1" in
    start)
    start
    ;;
    stop)
    stop
    ;;
    restart)
    stop
    start
    ;;
    *)
    echo "usage: $0 start|stop|restart"
    exit 0;
esac

However, it didn’t work and I don’t know why. I also set the ufw enabled and allowed ruptime
like this:

sudo ufw allow ruptime

It didn’t work either. The source code for ruptime and ruptimed are as follows:

connect_retry()

// the  functions used in the two program
// the  connect_retry() function 
#include "apue.h"
#include <sys/socket.h>

#define MAXSLEEP 128

int
connect_retry(int sockfd, const struct sockaddr *addr, socklen_t alen)
{
  int nsec;

  for (nsec = 1; nsec <= MAXSLEEP; nsec <<= 1) {
    if (connect(sockfd, addr, alen) == 0) {
      return (0);
    }
    if (nsec <= MAXSLEEP/2)
      sleep(nsec);
  }
  return (-1);
}

init_server()

// the initserver function 
#include "apue.h"
#include <errno.h>
#include <sys/socket.h>

int
initserver(int type, const struct sockaddr *addr, socklen_t alen, 
       int qlen)
{
  int fd;
  int err = 0;
  if ((fd = socket(addr->sa_family, type, 0)) < 0)
    return (-1);
  if (bind(fd, addr, alen) < 0) {
    err = errno;
    goto errout;
  }
  if (type == SOCK_STREAM || type == SOCK_SEQPACKET) {
    if (listen(fd, qlen) < 0) {
      err = errno;
      goto errout;
    }
  }
  return(fd);

 errout:
  close(fd);
  errno = err;
  return (-1);
}

The client end

// the client end i.e. ruptime.c
#include "apue.h"
#include <netdb.h>
#include <errno.h>
#include <sys/socket.h>

#define MAXADDRLEN 256

#define BUFLEN 128
extern int connect_retry(int, const struct sockaddr *, socklen_t);

void
print_uptime(int sockfd)
{
  int n;
  char buf[BUFLEN];

  while ((n = recv(sockfd, buf, BUFLEN, 0)) > 0)
    write(STDOUT_FILENO, buf, n);
  if (n < 0)
    err_sys("recv error");
}

int
main(int argc, char *argv[])
{
  struct addrinfo   *ailist, *aip;
  struct addrinfo    hint;
  int            sockfd, err;

  if (argc !=2 )
    err_quit("usage: ruptime hostname");
  hint.ai_flags = 0;
  hint.ai_family = 0;
  hint.ai_socktype = SOCK_STREAM;
  hint.ai_protocol = 0;
  hint.ai_addrlen = 0;
  hint.ai_canonname = NULL;
  hint.ai_addr = NULL;
  hint.ai_next = NULL;
  if ((err = getaddrinfo(argv[1], "ruptime", &hint, &ailist)) != 0)
    err_quit("getaddrinfo error: %s", gai_strerror(err));
  for (aip = ailist; aip != NULL; aip = aip->ai_next) {
    if ((sockfd = socket(aip->ai_family, SOCK_STREAM, 0)) < 0)
      err = errno;
    if (connect_retry(sockfd, aip->ai_addr, aip->ai_addrlen) < 0) {
      err = errno;
    } else {
      print_uptime(sockfd);
      exit(0);
    }
  }
  fprintf(stderr, "can't connect to %s: %s\n", argv[1], 
      strerror(err));
  exit(1);
}

The server end

//the server end i.e. ruptimed is as follows:
#include "apue.h"
#include <netdb.h>
#include <errno.h>
#include <syslog.h>
#include <sys/socket.h>

#define BUFLEN 128
#define QLEN 10

#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 256
#endif

extern int initserver(int, struct sockaddr *, socklen_t, int);

void
serve(int sockfd)
{
  int   clfd;
  FILE *fp;
  char buf[BUFLEN];

  for ( ; ; ) {
    clfd = accept(sockfd, NULL, NULL);
    if (clfd < 0) {
      syslog(LOG_ERR, "ruptimed: accept error: %s", 
         strerror(errno));
      exit(1);
    }
    if ((fp = popen("/usr/bin/uptime", "r")) == NULL) {
      sprintf(buf, "error: %s\n", strerror(errno));
      send(clfd, buf, strlen(buf), 0);
    } else {
      while (fgets(buf, BUFLEN, fp) != NULL)
    send(clfd, buf, strlen(buf), 0);
      pclose(fp);
    }
    close(clfd);
  }
}

int 
main(int argc, char *argv[])
{
  struct addrinfo   *ailist, *aip;
  struct addrinfo    hint;
  int            sockfd, err, n;
  char          *host;

  if (argc != 1)
    err_quit("usage: ruptimed");
#ifdef _SC_HOST_NAME_MAX
  n = sysconf(_SC_HOST_NAME_MAX);
  if (n < 0)
#endif 
    n = HOST_NAME_MAX;
  host = malloc(n);
  if (host == NULL)
    err_sys("malloc error");
  if (gethostname(host, n) < 0)
    err_sys("gethostname error");
  daemonize("ruptimed");
  hint.ai_flags = AI_CANONNAME;
  hint.ai_family = 0;
  hint.ai_socktype = SOCK_STREAM;
  hint.ai_protocol = 0;
  hint.ai_addrlen = 0;
  hint.ai_canonname = NULL;
  hint.ai_addr = NULL;
  hint.ai_next = NULL;
  if ((err = getaddrinfo(host, "ruptime", &hint, &ailist)) != 0) {
    syslog(LOG_ERR, "ruptimed: getaddrinfo error: %s", 
       gai_strerror(err));
    exit(1);
  }
  for (aip = ailist; aip != NULL; aip = aip->ai_next) {
    if ((sockfd = initserver(SOCK_STREAM, aip->ai_addr, 
                 aip->ai_addrlen, QLEN)) >= 0)
      serve(sockfd);
    exit(0);
  }
  exit(1);
}

Is there anyone can help?

The header lines of the command netstat -nap:

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -               
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      -               
tcp        0      0 127.0.0.1:4000          0.0.0.0:*               LISTEN      2252/ruptimed   
tcp        0  13033 192.168.1.221:47380     91.189.89.114:443       LAST_ACK    -               
tcp       74      0 192.168.1.221:43914     91.189.89.76:443        ESTABLISHED 1846/python     
tcp        0      0 127.0.0.1:4000          127.0.0.1:56344         TIME_WAIT   -               
tcp        0      1 192.168.1.221:35442     192.168.1.89:24800      SYN_SENT    1478/synergyc   
tcp        0      0 192.168.1.221:34957     74.125.71.125:5222      ESTABLISHED 1618/chrome     
tcp        0      0 192.168.1.221:57795     203.208.46.163:443      ESTABLISHED 1618/chrome     
tcp6       0      0 :::22                   :::*                    LISTEN      -  

The 3th record is my service ruptime. Is it something wrong? I don’t know much about its meanig.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-01T12:12:56+00:00Added an answer on June 1, 2026 at 12:12 pm

    I’m not a C expert but I know one thing: your daemon is probably binding to just one address/interface, and is accepting connections only from it.

    Use netstat -nap to check to which address the daemon is binding to.

    If it is listening to 0.0.0.0 then it is accepting connections from every interface, including localhost.

    If it is listening to 127.0.0.1 it will only accept from localhost.

    I bet it’s bound only to 127.0.0.1, that’s why you can’t connect with any other address.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

learning about loops (still a beginner) in VB.net. I have got the below code
Learning a lot in my few years of programming that the best projects are
Learning xml, Can anyone help me? I have following XML code: **<book lang=en>name of
Learning jquery, so please be kind :) Using PHP, I have a table with
Learning rails and something smells a little funny. I have the following form for
(learning c#) I have a C# WPF application which when a certain form is
Learning php! I have a sql database which contains a table called 'images' which
Learning .NET: I have a form with a split container, I want to load
learning Jquery and integrating with PHP - getting there, but have one last challenge
Learning basic Objective-C and have a few beginner questions. How would I define and

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.