0

In chapter 60,source code list

id_echo.h

/*************************************************************************\
*                  Copyright (C) Michael Kerrisk, 2018.                   *
*                                                                         *
* This program is free software. You may use, modify, and redistribute it *
* under the terms of the GNU General Public License as published by the   *
* Free Software Foundation, either version 3 or (at your option) any      *
* later version. This program is distributed without any warranty.  See   *
* the file COPYING.gpl-v3 for details.                                    *
\*************************************************************************/

/* Listing 60-1 */

/* id_echo.h

   Header file for id_echo_sv.c and id_echo_cl.c.
*/
#include "inet_sockets.h"       /* Declares our socket functions */
#include "tlpi_hdr.h"

#define SERVICE "echo"          /* Name of UDP service */

#define BUF_SIZE 500            /* Maximum size of datagrams that can
                                   be read by client and server */

id_echo_sv.c

/*************************************************************************\
*                  Copyright (C) Michael Kerrisk, 2018.                   *
*                                                                         *
* This program is free software. You may use, modify, and redistribute it *
* under the terms of the GNU General Public License as published by the   *
* Free Software Foundation, either version 3 or (at your option) any      *
* later version. This program is distributed without any warranty.  See   *
* the file COPYING.gpl-v3 for details.                                    *
\*************************************************************************/

/* Listing 60-2 */

/* id_echo_sv.c

   This program implements a daemon that provides the UDP "echo" service. It
   reads datagrams and then sends copies back to the originating address.

   NOTE: this program must be run under a root login, in order to allow the
   "echo" port (7) to be bound. Alternatively, for test purposes, you can edit
   id_echo.h and replace the SERVICE name with a suitable unreserved port
   number (e.g., "51000"), and make a corresponding change in the client.

   See also id_echo_cl.c.
*/
#include <syslog.h>
#include "id_echo.h"
#include "become_daemon.h"

int
main(int argc, char *argv[])
{
    int sfd;
    ssize_t numRead;
    socklen_t len;
    struct sockaddr_storage claddr;
    char buf[BUF_SIZE];
    char addrStr[IS_ADDR_STR_LEN];

    if (becomeDaemon(0) == -1)
        errExit("becomeDaemon");

    sfd = inetBind(SERVICE, SOCK_DGRAM, NULL);
    if (sfd == -1) {
        syslog(LOG_ERR, "Could not create server socket (%s)", strerror(errno));
        exit(EXIT_FAILURE);
    }

    /* Receive datagrams and return copies to senders */

    for (;;) {
        len = sizeof(struct sockaddr_storage);
        numRead = recvfrom(sfd, buf, BUF_SIZE, 0,
                           (struct sockaddr *) &claddr, &len);
        if (numRead == -1)
            errExit("recvfrom");

        if (sendto(sfd, buf, numRead, 0, (struct sockaddr *) &claddr, len)
                        != numRead)
            syslog(LOG_WARNING, "Error echoing response to %s (%s)",
                    inetAddressStr((struct sockaddr *) &claddr, len,
                                   addrStr, IS_ADDR_STR_LEN),
                    strerror(errno));
    }
}

id_echo_cl.c

/*************************************************************************\
*                  Copyright (C) Michael Kerrisk, 2018.                   *
*                                                                         *
* This program is free software. You may use, modify, and redistribute it *
* under the terms of the GNU General Public License as published by the   *
* Free Software Foundation, either version 3 or (at your option) any      *
* later version. This program is distributed without any warranty.  See   *
* the file COPYING.gpl-v3 for details.                                    *
\*************************************************************************/

/* Listing 60-3 */

/* id_echo_cl.c

   A client for the UDP "echo" service. This program sends each of its
   command-line arguments as a datagram to the server and echoes the
   contents of the datagrams that the server sends in response.

   See also id_echo_sv.c.
*/
#include "id_echo.h"

int
main(int argc, char *argv[])
{
    int sfd, j;
    size_t len;
    ssize_t numRead;
    char buf[BUF_SIZE];

    if (argc < 2 || strcmp(argv[1], "--help") == 0)
        usageErr("%s host msg...\n", argv[0]);

    /* Construct server address from first command-line argument */

    sfd = inetConnect(argv[1], SERVICE, SOCK_DGRAM);
    if (sfd == -1)
        fatal("Could not connect to server socket");

    /* Send remaining command-line arguments to server as separate datagrams */

    for (j = 2; j < argc; j++) {
        len = strlen(argv[j]);
        if (write(sfd, argv[j], len) != len)
            fatal("partial/failed write");

        numRead = read(sfd, buf, BUF_SIZE);
        if (numRead == -1)
            errExit("read");

        printf("[%ld bytes] %.*s\n", (long) numRead, (int) numRead, buf);
    }

    exit(EXIT_SUCCESS);
}

here is my question: ./id_echo_sv (su need privilege to bind reserved port)

./id_echo_cl localhost hello

things goes wrong with : ERROR [ECONNREFUSED Connection refused] read

If I change localhost to 127.0.0.1,things goes well. In the third line 1988/id_echo_sv runs well,I dont't figure out why does this happen,using localhost read function failed in client code.

[root@centos7-10 sockets]# netstat -nupl | grep 7
udp        0      0 0.0.0.0:5353            0.0.0.0:*                           874/avahi-daemon: r 
udp        0      0 127.0.0.1:323           0.0.0.0:*                           884/chronyd         
udp        0      0 0.0.0.0:7               0.0.0.0:*                           1988/id_echo_sv     
udp        0      0 0.0.0.0:35873           0.0.0.0:*                           874/avahi-daemon: r 
udp        0      0 192.168.122.1:53        0.0.0.0:*                           1782/dnsmasq        
udp        0      0 0.0.0.0:67              0.0.0.0:*                           1782/dnsmasq 

due to the function inetBind() etc use the author's version,so if you want to run,have to download the source code in tlpi

If you have any idea,please let me know,thanks in advance.

52coder
  • 179
  • 1
  • 2
  • 11
  • *"Here is my question: `./id_echo_sv` (su need privilege to bind reserved port)"* - You have several choices; see [Allow non-root process to bind to port 80 and 443?](https://superuser.com/q/710253/173513), [Bind to ports less than 1024 without root access](https://serverfault.com/q/268099/145545), and [Is there a way for non-root processes to bind to “privileged” ports on Linux?](https://stackoverflow.com/q/413807/608639) – jww Oct 21 '18 at 12:30
  • @jww yeah,I know,this is not question,I just don't know why localhost and 127.0.0.1 make difference. – 52coder Oct 21 '18 at 14:59
  • comment the line ::1 localhost may work – rick Mar 11 '22 at 05:21

0 Answers0