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.