8.4
|
Running ping like this is an easy way
to see ICMP messages that are received by the host on which
ping is being run. We reduce the number of packets sent
from the normal one per second just to reduce the output. If we run
our UDP client on our host aix, specifying the server's IP
address as 192.168.42.1, and also run the ping program, we
get the following output:
aix % ping -v -i 60 127.0.0.1
PING 127.0.0.1: (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=255 time=0 ms
36 bytes from 192.168.42.1: Destination Port Unreachable
Vr HL TOS Len ID Flg off TTL Pro cks Src Dst Data
4 5 00 0022 0007 0 0000 1e 11 c770 192.168.42.2 192.168.42.1
UDP: from port 40645, to port 9877 (decimal)
Note that not all ping clients print
received ICMP errors, even with the -v flag.
|
8.6
|
We run the sock program on the
multihomed host freebsd, specifying the -u option
(use UDP) and the -l option (specifying the local IP
address and port).
freebsd % sock -u -l 12.106.32.254.4444 192.168.42.2 8888
hello
The local IP address is the Internet-side
interface in Figure 1.16, but the
datagram must go out the other interface to get to the destination.
Watching the network with tcpdump shows that the source IP
address is the one that was bound by the client, not the outgoing
interface address.
14:28:29.614846 12.106.32.254.4444 > 192.168.42.2.8888: udp 6
14:28:29.615225 192.168.42.2 > 12.106.32.254: icmp: 192.168.42.2
udp port 8888 unreachable
|
8.8
|
The largest IPv4 datagram is 65,535 bytes,
limited by the 16-bit total length field in Figure A.1. The
IP header requires 20 bytes and the UDP header requires 8 bytes,
leaving a maximum of 65,507 bytes for user data. With IPv6 without
jumbogram support, the size of the IPv6 header is 40 bytes, leaving
a maximum of 65,487 bytes for user data.
Figure
E.9 shows the new version of dg_cli. If you forget to
set the send buffer size, Berkeley-derived kernels return an error
of EMSGSIZE from sendto, since the size of the
socket send buffer is normally less than required for a
maximum-sized UDP datagram (be sure to do Exercise 7.1).
But if we set the client's socket buffer sizes as shown in
Figure E.9 and run the
client program, nothing is returned by the server. We can verify
that the client's datagram is sent to the server by running
tcpdump, but if we put a printf in the server,
its call to recvfrom does not return the datagram. The
problem is that the server's UDP socket receive buffer is smaller
than the datagram we are sending, so the datagram is discarded and
not delivered to the socket. On a FreeBSD system, we can verify
this by running netstat -s and looking at the "dropped due
to full socket buffers" counter before and after our big datagram
is received. The final solution is to modify the server, setting
its socket send and receive buffer sizes.
Figure E.9
Writing the maximum-sized UDP/IPv4 datagram.
udpcliserv/dgclibig.c
1 #include "unp.h"
2 #undef MAXLINE
3 #define MAXLINE 65507
4 void
5 dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)
6 {
7 int size;
8 char sendline[MAXLINE], recvline[MAXLINE + 1];
9 ssize_t n;
10 size = 70000;
11 Setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
12 Setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
13 Sendto(sockfd, sendline, MAXLINE, 0, pservaddr, servlen);
14 n = Recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);
15 printf("received %d bytes\n", n);
16 }
On most networks, a 65,535-byte IP datagram is
fragmented. Recall from Section 2.11 that
an IP layer must support a reassembly buffer size of only 576
bytes. Therefore, you may encounter hosts that will not receive the
maximum-sized datagrams sent in this exercise. Also, many
Berkeley-derived implementations, including 4.4BSD-Lite2, have a
sign bug that prevents UDP from accepting a datagram larger than
32,767 bytes (line 95 of p.770 of TCPv2).
|