Principles of TCP/IP Networks
In an Internet Protocol network, each computer has a 32-bit IP address. The IP address of each computer is unique. WWW is an extremely large and growing IP network. Therefore, each computer on the network must have a unique IP address. An IP address is a four-digit number separated by., for example, 16.42.0.9. In fact, IP addresses can be divided into two parts: one is the network address and the other is the host address. For example, in 16.42.0.9, 16.42 is the network address and 0.9 is the host address. Host addresses can be divided into subnet addresses and host addresses. The IP address of a computer is hard to remember. It is much easier to use a name. If you use a name, you must have a mechanism to convert the name to an IP address. These names can be statically stored in the/etc/hosts file, or the Linux system requests the Domain Name Server (DNS server) to convert the names. If you use a DNS server, the local host must know the IP addresses of one or more DNS servers. The information is stored in the/etc/resolv. conf file.
When you are connected to other computers, the system uses IP addresses to exchange data with other computers. Data is stored in IP data packets. Each IP packet has an IP data header, including the source address and destination address, a data checksum and other related information. The size of IP data packets varies with the transmission media. For example, Ethernet data packets must be larger than PPP data packets. After receiving data packets, the host at the destination address must assemble the data and send it to the received application.
IP data packets can be directly transmitted between hosts connected to the same IP subnet, while gateways are required for hosts connected to different subnets. The gateway is used to transmit data packets between different subnets.
The IP protocol is a Transport Layer Protocol. Other protocols can use the IP protocol to transmit data. TCP (Transmission Control Protocol) is a reliable protocol between point-to-point. It uses the IP protocol to transmit and receive its own data packets. TCP is a connection-based protocol. A virtual connection line will be established between the two applications that need to communicate, even if it goes through many subnets, gateways, and routers. TCP ensures that data is reliably transmitted and received between two applications, and that no data packets are lost or duplicated. When TCP uses the IP protocol to send its own data packets, the data in the IP data packet is the TCP data packet itself. The IP protocol layer in the host that communicates with each other is responsible for transmitting and receiving IP data packets. Each IP data header contains a protocol identifier of a byte. When TCP requests an IP packet from the IP protocol layer, the Protocol identifier in the IP data header indicates that the packet is a TCP packet. The IP layer of the acceptor can use this Protocol identifier to determine the layer to which the received packets are transmitted. Here, it is the TCP layer.
When applications use TCP/IP for communication, they must specify not only the IP address of the target computer, but also the port address used by the application. A port address can uniquely represent an application. A standard network application uses a standard port address. For example, a Web server uses port 80. You can view the registered port addresses in/etc/services.
The IP protocol layer can also use different physical media to transmit IP packets to other IP address hosts. You can add protocol headers to these media sets. For example, the Ethernet protocol layer, PPP protocol layer, or slip protocol layer. Ethernet can be connected to multiple hosts at the same time, and each host has an ethernet address. This address is unique and saved in an Ethernet Card. Therefore, when an IP packet is transmitted over Ethernet, the IP address in the IP packet must be converted to the physical address in the ethernet card of the host. In Linux, Address Resolution Protocol (ARP) is used to translate IP addresses into physical addresses in the ethernet card of the host. Hosts that want to translate IP addresses into hardware addresses use broadcast addresses to send an ARP request packet containing IP addresses to all nodes in the network. After receiving the request, the target computer that owns this IP address returns an ARP response containing its physical address. ARP is not only limited to Ethernet, but can also be used in other physical media, such as FDDI. Network devices that cannot use ARP can be marked out, so that the Linux system will not try to use arp. The system also has a reverse translation protocol called RARP, which translates the host's physical address into an IP address. The gateway can use this Protocol to respond to ARP requests on behalf of IP addresses in the remote network.
BSD Interface
The BSD interface is the earliest implementation of network communication. It is supported by a management software that only processes BSD interfaces. The following is the inet interface layer, which manages the communication ends of TCP and UDP. UDP (User Data Protocol) is a connectionless protocol, while TCP is a reliable end-to-end protocol. When a UDP packet is transmitted over the network, the Linux system does not know whether or not these UDP packets are securely sent to the destination node. TCP data packets are numbered, and both ends of TCP transmission must confirm the correctness of the data packets. The IP protocol layer is used to implement the inter-network protocol. The code must prepare an IP data header for the previous layer of data, it is also necessary to decide how to transmit the received IP packet to the TCP or UDP protocol layer. Below the IP protocol layer is a network device that supports the entire Linux network system, such as PPP and Ethernet. Network devices are not exactly the same as physical devices, because some network devices, such as feedback devices, are completely implemented by software. Unlike standard devices that use the mknod command to create Linux systems, network devices only appear in the system when the software detects and initializes these devices. When you build the system kernel, you can only see/dev/eth0 even if the system has the corresponding Ethernet device driver. The ARP protocol is between the IP protocol layer and the protocol that supports ARP translation addresses.
======================================
Network Application
User Layer
--------------------------------
BSD core layer
Set Interface Layer
|
Lnet
Set Interface Layer
|
//
TCP UDP
|
IP
|
PPP | slip | Ethernet ---> ARP
======================================
BSD is a common network interface in Unix systems. It not only supports different network types, but also supports communication between internal processes. Both communication processes use a set of interfaces to describe the two ends of the communication link. The Set interface can be considered as a special pipe, but unlike the pipe, the set interface has no limit on the size of data that can be accommodated. Linux supports multiple types of interfaces, also known as the set interface addressing family, because each type of interfaces has its own addressing method.
Linux BSD interfaces support the following interface types:
1. Stream)
These interfaces provide reliable bidirectional sequential data stream connections. They can ensure the integrity, correctness, and singularity of data transmission. The TCP protocol in the inet addressing family supports this type of set interface.
The data stream set interface is a reliable two-way connection communication data stream. If you put two pieces of data in the order of "1, 2" in the Set interface, they will also arrive in the order of "1, 2" at the other end. They can also be considered as error-free transmission.
The commonly used Telnet application is an example of using the data stream set interface. The http www browser also uses the data stream interface to read webpages. In fact, if you use Telnet to log on to port 8 0 of a WWW site and type "Get webpage name", you will get this HTML page. Data Stream sets use TCP for high-quality data transmission. The datagram set interface uses UDP, so the order of the datagram is not guaranteed. Data is transmitted in a response mode.
2. Data Packets)
This type of set interface can also provide two-way data transmission like a stream set interface, but they cannot guarantee that the transmitted data will certainly reach the target node. Even if the data can arrive, it cannot be ensured that the data arrives in the correct order and that the data is single and correct. The u d p protocol supports this type of interface.
3. Raw)
This type of interface allows the process to directly access the underlying protocol.
4. reliable message delivery)
This interface is the same as the datagram interface, and can only ensure the arrival of data.
5. sequenced packets)
This type of set interface is the same as the stream set interface, except that the packet size is fixed.
6. Packet)
This is not a standard BSD interface type, but an extension in Linux. It allows processes to directly access data packets at the device layer.
Basic set Interface Options
So_keepalive
Checks whether the host of the other party crashes to prevent (the server) from blocking the input of the TCP connection forever. After this option is set, if no data is exchanged in any direction of this interface within two hours, TCP automatically sends a keepalive probe to the other side ). This is a TCP shard that the other party must respond to. It may cause the following three situations:
The other party receives the desired ack response. 2 hours later, TCP sends out another detection shard.
The other party has crashed and restarted: respond with RST. The interface to be processed is set to econnreset, and the interface itself is closed. The other party has no response: TCP sent from the Berkeley sends an additional eight detection segments, one in 75 seconds, and tries to get a response. If no response is returned after the first probe is sent for 11 minutes and 15 seconds, give up. The processing error of the Set interface is set to etimeout by mistake, and the Set interface itself is disabled. For example, if the ICMP error is "Host Unreachable (host inaccessible)", it indicates that the host of the other party has not crashed but is not reachable. In this case, the error to be handled is set to ehostunreach.
So_rcvbuf and so_sndbuf
Each set of interfaces has a sending buffer and a receiving buffer. The receiving buffer is used by TCP and UDP to keep the received data for read by the application process. TCP: The window size of TCP advertised to the other end. The receiving buffer of the TCP interface cannot overflow, because the other party cannot send data that exceeds the size of the advertised window. This is the traffic control of TCP. If the recipient ignores the window size and sends out data that exceeds the Zhoukou size, the receiver TCP will discard it. UDP: When the received data report is not included in the interface to receive the buffer, the datagram is discarded. There is no traffic control for UDP. A fast sender can easily drown out slow recipients, causing the receiver to discard the UDP datagram.
So_linger
Specify how the function closes the interface connection protocol-processing the linger structure when data remains in the buffer zone sent by the interface
Struct linger {int l_onoff; // 0 = OFF, nonzero = on Int l_linger; // linger time in seconds };
So_rcvlowat and so_sndlowat
Each set of interfaces has a receiving low tide limit and a sending low tide limit. They are used by the function select, and the threshold for receiving low tide is to make the select return "readable" and the total amount of data required in the buffer zone received by the interface. -- For a TCP or UDP interface, the default value is 1. Sending low tide limit is to allow the SELECT statement to return "writable", and the available space is required in the interface sending buffer. For TCP interfaces, the default value is 2048. For the low-tide limit of UDP usage, because the number of bytes in the available space in the sending buffer is never changed, as long as the buffer size of the UDP interface sending is greater than the low-tide limit of the Set interface, this UDP interface is always writable. UDP has no sending buffer, only the size of the sending buffer.
So_broadcast set Interface Options
This option allows us to enable or disable the sending and broadcasting capabilities of an interface. Broadcast can only be used in the datagram mode, and must also be an Ethernet network that supports broadcast messages. This cannot be done on point-to-point links.
Because the broadcast function must be explicitly executed. Therefore, some UDP programs can avoid sending broadcast addresses as the destination addresses. However, when processing broadcast addresses in Linux, they are not identified by users. The address formats seen in the user space are not different. It is not until the kernel recognizes the broadcast address and processes it accordingly.
Data Structure
Next we will discuss the data structures that may be used to write programs using a set of interfaces.
The first is an interface descriptor. An interface descriptor is only an integer value: I n t.
The first data structure is struct sockaddr, which stores the address information of the interface.
Struct sockaddr {
Unsigned short sa_family;/* address family, af_xxx */
Char sa_data [14];/* 14 bytes of Protocol address */
};
Sa_family can be many other values, but here we assign it "af_inet ". Sa_data includes a destination address and a port address.
You can also use another data structure sockaddr_in, as shown below:
Struct sockaddr_in {
Short int sin_family;/* address family */
Unsigned short int sin_port;/* Port Number */
Struct in_addr sin_addr;/* Internet address */
Unsigned char sin_zero [8];/* same size as struct sockaddr */
};
This data structure makes it easier to use each element. Note that sin_zero should use bzero () or memset () and set it to all 0. In addition, a pointer pointing to the sockaddr_in data structure can be projected to a pointer pointing to the sockaddr data structure, and vice versa.
IP address and how to use IP Address
There are a series of programs that allow you to process the I P address.
First, you can use the inet_addr () program to convert an I P address in the form of "132.241.5.10" to an unsigned integer number.
Ina. sin_addrs_addr = inet_addr ("132.241.5.10 ");
If an error occurs, the inet_addr () program returns-1.
You can also call inet_ntoa () to convert the address into numbers and periods:
Printf ("% s", inet_ntoa (INA. sin_addr ));
This will print the I P address. It returns a pointer to a string.
Socket ()
We use the system to call socket () to obtain the file descriptor:
# Include
# Include
Int socket (INT domain, int type, int Protocol );
Set the first parameter domain to "af_inet ".
The second parameter is the set interface type: sock_dgram.
The third parameter is set to 0.
The system calls socket () and returns only one set of interface descriptors. If an error occurs,-1 is returned.
BIND ()
Once you have an interface set, the next step is to bind the interface set to a port on the local computer. However, it is unnecessary if you only want to use connect.
The following is how the system calls BIND:
# Include
# Include
Int BIND (INT sockfd, struct sockaddr * my_addr, int addrlen );
The first parameter sockfd is the set of interface file descriptors returned by the socket () call.
The second parameter my_addr is a pointer to the sockaddr data structure. The data structure sockaddr contains information about your address, port, and IP address.
The third parameter addrlen can be set to sizeof (struct sockaddr ). The following is an example:
# Include
# Include
# Include
# Define myport 3490
Main ()
{
Int sockfd;
Struct sockaddr_in my_addr; // describes the sock address structure.
Sockfd = socket (af_inet, sock_stream, 0);/* basically build UDP socket, it is best to perform some checks */
My_addr.sin_family = af_inet;/* sets the Protocol set based on Internet Protocol */
My_addr.sin_port = htons (myport); // port number
My_addr. sin_addr.s_addr = inet_addr ("132.241.5.10"); // converts a string to a standard address format.
Bzero (& (my_addr.sin_zero), 8);/* zero the rest of the struct */
/* Don't forget your error checking for BIND ():*/
BIND (sockfd, (struct sockaddr *) & my_addr, sizeof (struct sockaddr ));
// Bind the listening process to the socket
If an error occurs, BIND () also returns-1.
If you use the connect () system call, you do not have to know the port number you are using. When you call connect (), it checks whether the set interface is bound. If not, it will allocate an idle port.
Sendto () and recvfrom ()
Because the datagram set interface is not connected to a remote host, we must first provide the destination address before sending data packets. Please refer
Int sendto (INT sockfd, const void * MSG, int Len, unsigned int flags,
Const struct sockaddr * To, int tolen );
Except for the two parameters, the other parameters are the same as when the system calls s e n d. The t o parameter is a pointer to the data structure s o c k a d r that contains the destination I P address and port number. The t o l e n parameter can be set to sizeof (struct sockaddr ).
The system calls sendto () to return the actual number of bytes sent. If an error occurs,-1 is returned.
The usage of the system call recvfrom () is also very similar to that of r e c v:
Int recvfrom (INT sockfd, void * Buf, int Len, unsigned int flags
Struct sockaddr * From, int * fromlen );
Sockfd: Description
Buff: pointer to the input buffer
Nbytes: Read byte size
Flag: 0
From: Peer protocol address
Addrlen: Protocol address length of the peer
Function return value: the length of the read data, which can be 0.
The from parameter is a pointer to the sockaddr Data Structure on the local computer that contains the source I P address and port number. The fromlen parameter is set to sizeof (struct sockaddr ).
The system calls recvfrom () to return the number of received bytes. If an error occurs,-1 is returned.
Close () and Shutdown ()
You can use close () to call the set interface file descriptor for closing the connection:
Close (sockfd );
In this way, no read/write operations can be performed on this interface.
You can use the system call Shutdown () to gain more control. It allows you to cut off the communication in a certain direction, or cut off the communication between the two parties:
Int Shutdown (INT sockfd, int how );
The first parameter is the set interface file descriptor that you want to disconnect communication. The value of h o w in the second parameter is as follows:
0-further specified es are disallowed
1-further sends are disallowed
2-further sends and Es are disallowed (like close ())
If Shutdown () succeeds, 0 is returned. If it fails,-1 is returned.
Client/Server mode
Most of the communication on the network is in the Client/Server mode. For example, Telnet. When you use Telnet to connect to port 23 of the remote host, a program called telnetd on the host starts to run. It processes all incoming Telnet connections and sets a logon prompt for you.
It should be noted that the Client/Server mode can use sock_stream, sock_dgram, or any other method. For example, Telnet/telnetd, FTP/ftpd, and BOOTP/bootpd. Every time you use ftp, a remote computer is running an FTPd to serve you.
Generally, a machine has only one server program. It uses fork () to process requests from multiple client programs. The most basic solution is to wait for a connection on the server, use accept () to accept the connection, and call fork () to generate a sub-process to process the connection.
UDP broadcast mode
One of the purposes of broadcast is to assume that the server host is located on the local subnet but does not know its unicast IP address. This is resource discovery ). Another purpose is to reduce data traffic on the LAN when multiple customers communicate with a single server. The following are some Internet application instances that use broadcast for this purpose.
★Address Resolution Protocol (ARP. ARP is a basic component of IPv4, not a user application. ARP broadcasts a request on the local subnet: "If the system has an IP address a. B .c.d, please indicate yourself and tell me your hardware address ."
★BOOTP (Bootstrap Protocol ). The customer assumes that there is a server host on the local subnet. It sends its own boot request to the destination address (generally 255.255.255.255, because the customer does not know its own IP address, subnet mask, or subnet restricted broadcast address.
★NTP (Network Time Protocol ). A common situation is that an NTP client host may be configured to use the IP addresses of one or more server hosts, the NTP customer above poll these servers at a certain frequency (every 64 seconds or longer. The customer uses an accurate Algorithm Based on the server return time and the return time to the server to update the clock. However, in the LAN that supports broadcast, the customer does not need to poll the server, instead, the server broadcasts the current time to all customers on the local subnet at a frequency every 64 seconds. In this way, data traffic on the network can be reduced.
★Routing background process. Routed is the most common background process. The route table output method is lan broadcast. All other routers connected to these LAN can receive these route notifications at the same time, instead of having to configure the IP address of their neighbor router for each router. This feature is also used by hosts on the LAN to listen for Route announcements and update their route tables accordingly (many people think this is a "misuse ")
If {netid, subnetid, hostoid} is used }. ({Network ID, subnet ID, host ID}) indicates an IPv4 address. There are four types of broadcast addresses. We use-1 to indicate that all bits are 1 fields.
1. subnet broadcast address: {netid, subnetid,-1 }. This type of address orchestration refers to all interfaces on the subnetwork. For example, if we use 8-bit subnet ID for Class B address 128.7, 128.7.6.225 will be the subnet broadcast address of all interfaces on the subnet of 128.7.6.
Vro generally does not forward such broadcasts (tcpv2). Figure 18.2 shows a router connected to the 128.7.1 and 128.7.6 subnets. The vro receives a unicast IP datagram with a destination address of 210.37.6.255 (the subnet broadcast address of another interface) on the 127.1. The router generally does not forward this datagram to the 128.7.6 subnet. Some systems have configuration options for running forwarding subnet broadcast datagram.
2. All subnet broadcast addresses: {netid,-1,-1 }. This type of broadcast address orchestration specifies all subnets on the network. If this type of address layer has been used, it is rare to see it now.
3. network broadcast address: {netid,-1 }. This type of address is used for networks without subnet division. However, networks that do not divide subnets almost do not exist.
4. Restricted broadcast address: {-1,-1,-1} Or 255.255.255.255. The router never forwards IP data packets whose destination address is 255.255.255.255.
Among the four types of broadcast addresses, subnet broadcast addresses are the most common today. However, some old systems still send data packets whose destination address is 255.255.255.255. Some old systems do not understand subnet broadcast addresses. They interpret only the datagram sent to 255.255.255.255 as broadcast.
Before viewing the broadcast, we should be clear about the process of sending UDP datagram to the unicast address. In the figure, the network address is 192.168.0, eight of which are used as the subnet ID and eight are used as the host ID. The application on the left-side host calls the sendto function on a UDP interface and sends the datagram to the IP address 192.168.0.3 and port 1234. The UDP layer attaches a UDP header and transmits the UDP datagram to the IP layer. The IP layer attaches an IPv4 header to it and determines its outbound interface. In the case of Ethernet, ARP will be called to determine the ethernet address corresponding to the destination IP address: 08: 00: 22: 03: FF: 42. Then, the group is sent out as an Ethernet frame. The destination address of the Ethernet frame is the above 48-bit address. The value of the frame type field is 0800, indicating that this is an IPv4 group. The value of the IPv6 Frame Type field is 86dd.
The Ethernet interface of the intermediate host sees the frame and compares its destination ethernet address with its own ethernet address (02: 60: 8c: 2f: 4E: 13. Because the two are not equal, the interface ignores the frame. Therefore, unicast frames do not cause any additional overhead on this host. This frame is also displayed on the Ethernet interface of the host on the right. When it compares the destination ethernet address of the frame with its own ethernet address, it finds that the two are equal and the interface reads the entire frame. Since the Frame Type field is only 0800, the group is put into the IP input queue.
When the IP layer processes this group, it first compares the destination IP address. Because the destination address is one of them, it accepts this group.
Then, the IP layer checks the IPv4 header protocol field and its value is 17 for UDP. Therefore, the IP datagram is sent to the UDP layer.
The UDP layer checks the destination port (if its UDP interface is connected, it may also check the source port) and sends the datagram party to the receiving queue of the corresponding interface. If necessary, wake up the process and the process reads the newly received datagram.
In this example, the unicast IP datagram can only be received by the host specified by the destination IP address. Other hosts on the subnet are not affected. Now let's consider a similar example: the same subnet, but the sender sends a subnet broadcast datagram whose address is 192.168.0.255.
When the host on the left sends a data report, it notices that the destination IP address is a subnet broadcast address, and maps it to a 48-bit ethernet address ff. This allows each Ethernet interface on the subnet to receive the frame. In the figure, the two hosts running IPv4 on the right side receive the frame. Since the Ethernet frame type is 0800, both hosts transmit the datagram to the IP layer. Because the destination IP address matches the broadcast address and the protocol field is 17 (UDP), both hosts upload the group to UDP.
The rightmost host transmits the UDP datagram to the application process bound to port 1234. The application process that receives the broadcast UDP datagram does not need any special processing. It only creates a UDP interface and binds the application port number to it. (We assume that the bound IP address is inaddr_any. This is a typical case.) However, the intermediate host does not have any application process bound to UDP port 1234. The UDP code of the host discards the received datagram. This host prohibits the sending of ICMP messages with inaccessible ports, because this will generate a broadcast storm (broadcast storm): Many hosts on the subnet will respond at the same time, this will make the network unavailable in a few seconds. In the figure, we also show that the host on the left delivers the output data to itself. This is a broadcast attribute: According to the definition, the broadcast will reach all hosts on the subnet, including the sender itself.
We also assume that the sending application process has been bound to the port (1234) to be sent, so it will receive a copy of each datagram it sends. (But generally, there is no requirement to send the process-bound datagram to the UDP port .)
This example also shows the underlying problem of broadcast: all hosts on the subnet that are not involved in the broadcast application system must also process the datagram protocol until it is discarded at the UDP layer. All non-IP hosts (such as those with Novell IPX lines) must also receive complete frames at the link layer and discard them at this layer (assuming these hosts do not support frame types, the value of the frame type field of the IPv4 group is 0800 ). Therefore, application systems (such as audio and video application systems) that generate IP datagram at a high rate will seriously affect the operation of other hosts on the subnet.
----------------------------------------------------------------------------
Udp echo server program
// Main program of the server
Int main (INT argc, char ** argv)
{
Int sockfd; // define a socket
Struct sockaddr_in servaddr, cliaddr; // IPv4 interface address Definition
Sockfd = socket (af_inet, sock_dgram, 0); // create a UDP socket
Bzero (& servaddr, sizeof (servaddr); // address structure resetting
Servaddr. sin_family = af_inet; // IPv4 protocol
Servaddr. sin_addr.s_addr = htonl (inaddr_any); // address specified by the kernel
Servaddr. sin_port = htons (serv_port); // server listening port
/* Allocate the Protocol address and bind the port */
BIND (sockfd, (Sa *) & servaddr, sizeof (servaddr ));
/* Echo subroutine */
Dg_echo (sockfd, (Sa *) & cliaddr, sizeof (cliaddr ));
}
Void dg_echo (INT sockfd, Sa * pcliaddr, socklen_t clilen)
{
Int N; // number of bytes read
Socklen_t Len; // Protocol address length. clilen can be used without this parameter.
Char mesg [maxline];
For (;;){
Len = clilen;
/* Read a row */
N = recvfrom (sockfd, mesg, maxline, 0, pcliaddr, & Len );
/* Return to the peer interface */
Sendto (sockfd, mesg, N, 0, pcliaddr, Len );
}
========================================================== ===
Udp echo client program
// Main client program
Int main (INT argc, char ** argv) // The second parameter of the command line represents the server address
{
Int sockfd; // socket
Struct sockaddr_in servaddr; // server address Structure
Const int on = 1; // set a constant to enable broadcast mode.
/* The server address must be specified on the command line */
If (argc! = 2) err_quit ("Usage: udpcli ");
Bzero (& servaddr, sizeof (servaddr); // address structure resetting
Servaddr. sin_family = af_inet; // IPv4
Servaddr. sin_port = htons (serv_port); // port 9877
/* Network IP address in byte order */
Inet_ton (af_inet, argv [1], & servaddr. sin_addr );
/* Create a UPD interface */
Sockfd = socket (af_inet, sock_dgram, 0 );
// Set the broadcast mode on this interface
Setsockopt (sockfd, sol_socket, so_broadcast, & on, sizeof (on ));
/* Echo client subroutine. stdin is the standard input: keyboard */
Dg_cli (stdin, sockfd, (Sa *) & servaddr, sizeof (servaddr ));
Exit (0); // exit the program after the subroutine ends.
}
The client sends the echo subroutine.
Void dg_cli (File * FP, int sockfd, const Sa * pservaddr, socklen_t servlen)
{
Int N; // number of bytes read
Char sendline [maxline], recvline [maxline + 1]; // 1: occupied by the end mark
/* Read a row from the keyboard */
While (fgets (sendline, maxline, FP )! = NULL) {// if the end is not ^ d
/* Send the read row to the broadcast address */
Sendto (sockfd, sendline, strlen (sendline), 0, pservaddr, servlen );
/* Read back. The number of read bytes is N, and you do not care where to read the data.
N = recvfrom (sockfd, recvline, maxline, 0, null, null );
Recvline [N] = 0;/* End mark of the recvline string */
Fputs (recvline, stdout); // output to standard output: Display
} // While loop ends: until the end character ^ d is read from the keyboard
Verify received response
Void dg_cli (File * FP, int sockfd, const Sa * pservaddr, socklen_t servlen)
{
Int N; socklen_t Len;
Char sendline [maxline], recvline [maxline + 1];
Struct sockaddr * preply_addr; // address pointer of the other party (response)
Preply_addr = malloc (servlen); // allocate the address Structure
While (fgets (sendline, maxline, FP )! = NULL ){
Sendto (sockfd, sendline, strlen (sendline), 0, pservaddr, servlen );
Len = servlen;
/* Read a row and obtain the peer interface address */
N = recvfrom (sockfd, recvline, maxline, 0, preply_addr, & Len );
/* The length of the peer interface address is different from that of the specified server address */
/* Or the interface address structure is not the same ,*/
If (Len! = Servlen | memcmp (pservaddr, preply_addr, Len )! = 0 ){
Printf ("reply from % s (ignored)/n", // ignore the echo line and output the recipient's address
Sock_ntop (preply_addr, Len ));
Continue; // the next cycle
}
Recvline [N] = 0;/* null terminate */
Fputs (recvline, stdout );
}
}