I. Introduction
UDP is a type of transport layer protocol in TCP/IP protocol. This article describes how to compile a client/server model program based on UDP protocol in Linux, an echo Client/Server example program is provided.
II. Introduction to UDP protocol
UDP is a simple transport layer protocol, which is described in rfc768. UDP is a non-connection and unreliable data packet protocol. It is completely different from TCP protocol that provides connection-oriented and reliable byte stream. Although UDP has many shortcomings, there are still many network programs using it, such as DNS (Domain Name Resolution Service), NFS (Network File System), SNMP (Simple Network Management Protocol) and so on.
Generally, the UDP client program does not establish a connection with the server program, but directly uses sendto () to send data. Similarly, the UDP server program does not need to allow connection to the client program, but directly uses recvfrom () to wait until it receives the data sent by the client program.
Here, we use a simple echo client/server program to introduce how to write UDP programs in Linux. The client program reads data from stdin and sends the data to the server program through the network. After receiving the data, the server program directly sends the data back to the client program. The client program receives the data sent from the server and then outputs the data from stdout.
3. UDP server program
1. Write the UDP server program
(1) Use SOCKET () to establish a UDP socket, and the second parameter is sock_dgram.
(2) initialize the variables in the sockaddr_in structure and assign values. Sockaddr_in structure definition:
Struct sockaddr_in {
Uint8_t sin_len;
Sa_family_t sin_family;
In_port_t sin_port;
Struct in_addr sin_addr;
Char sin_zero [8];
};
Here, "08" is used as the port of the service program, and "inaddr_any" is used as the bound IP address, that is, the address on any host.
(3) bind the socket above and the defined IP address and port with BIND. Check whether BIND () is successfully executed. If any error occurs, exit. This prevents repeated running of service programs.
(4) enter the infinite loop program, use recvfrom () to enter the waiting state, and process the received data until it receives the data sent by the customer program, and send feedback to the customer program. Here, the received data is directly sent back to the customer program.
2. udpserv. C program content:
# Include <sys/types. h>
# Include <sys/socket. h>
# Include <string. h>
# Include <netinet/in. h>
# Include <stdio. h>
# Include <stdlib. h>
# Define maxline 80
# Define serv_port 8888
Void do_echo (INT sockfd, struct sockaddr * pcliaddr, socklen_t clilen)
{
Int N;
Socklen_t Len;
Char mesg [maxline];
For (;;)
{
Len = clilen;
N = recvfrom (sockfd, mesg, maxline, 0, pcliaddr, & Len );
Sendto (sockfd, mesg, N, 0, pcliaddr, Len );
}
}
Int main (void)
{
Int sockfd;
Struct sockaddr_in servaddr, cliaddr;
Sockfd = socket (af_inet, sock_dgram, 0 );
Bzero (& servaddr, sizeof (servaddr ));
Servaddr. sin_family = af_inet;
Servaddr. sin_addr.s_addr = htonl (inaddr_any );
Servaddr. sin_port = htons (serv_port );
If (BIND (sockfd, (struct sockaddr *) & servaddr, sizeof (servaddr) =-1)
{
Perror ("BIND error ");
Exit (1 );
}
Do_echo (sockfd, (struct sockaddr *) & cliaddr, sizeof (cliaddr ));
Return 0;
}
Iv. UDP client program
1. Write the UDP client program
(1) initialize the variables in the sockaddr_in structure and assign values. Here, "8888" is used as the port to connect to the service program, read the IP address from the command line parameters, and determine whether the IP address meets the requirements.
(2) Use SOCKET () to create a UDP socket. The second parameter is sock_dgram.
(3) connect () to establish a connection with the service program. Unlike TCP, UDP connect () does not shake hands with the service program three times. We mentioned above that UDP is not a connection, but it can also be a connection. Using the connected UDP, the kernel can directly return the error message to the user program, so as to avoid calling recvfrom () for a long time because no data is received, as if the customer program did not respond.
(4) send data to the service program. Because UDP is connected, write () is used instead of sendto (). The data here reads the user input directly from the standard input.
(5) receive data sent back by the service program, and use read () instead of recvfrom ().
(6) process the received data, which is directly output to the standard output.
2. udpclient. C program content:
# Include <sys/types. h>
# Include <sys/socket. h>
# Include <string. h>
# Include <netinet/in. h>
# Include <stdio. h>
# Include <stdlib. h>
# Include <ARPA/inet. h>
# Include <unistd. h>
# Define maxline 80
# Define serv_port 8888
Void do_cli (File * FP, int sockfd, struct sockaddr * pservaddr, socklen_t servlen)
{
Int N;
Char sendline [maxline], recvline [maxline + 1];
If (connect (sockfd, (struct sockaddr *) pservaddr, servlen) =-1)
{
Perror ("Connect error ");
Exit (1 );
}
While (fgets (sendline, maxline, FP )! = NULL)
{
Write (sockfd, sendline, strlen (sendline ));
N = read (sockfd, recvline, maxline );
If (n =-1)
{
Perror ("read error ");
Exit (1 );
}
Recvline [N] = 0;
Fputs (recvline, stdout );
}
}
Int main (INT argc, char ** argv)
{
Int sockfd;
Struct sockaddr_in servaddr;
If (argc! = 2)
{
Printf ("Usage: udpclient <IPaddress> \ n ");
Exit (1 );
}
Bzero (& servaddr, sizeof (servaddr ));
Servaddr. sin_family = af_inet;
Servaddr. sin_port = htons (serv_port );
If (inet_ton (af_inet, argv [1], & servaddr. sin_addr) <= 0)
{
Printf ("[% s] is not a valid IPaddress \ n", argv [1]);
Exit (1 );
}
Sockfd = socket (af_inet, sock_dgram, 0 );
Do_cli (stdin, sockfd, (struct sockaddr *) & servaddr, sizeof (servaddr ));
Return 0;
}
5. Run the example Program
1. Compile the example Program
Run the following command to compile the example program:
Gcc-wall-O udpserv. c
Gcc-wall-O udpclient. c
The udpserv and udpclient executable programs are generated after compilation.
2. Run the UDP server program
Run the./udpserv & command to start the service program. We can use the netstat-ln command to observe the IP address and port bound to the service program. Some output information is as follows:
Active Internet connections (only servers)
PROTO Recv-Q send-Q local address foreign address State
TCP 0 0 0.0.0.0: 32768 0.0.0.0: * listen
TCP 0 0 0.0.0.0: 111 0.0.0.0: * listen
TCP 0 0 0.0.0.0: 6000 0.0.0.0: * listen
TCP 0 0 127.0.0.1: 631 0.0.0.0: * listen
UDP 0 0 0.0.0.0: 32768 0.0.0.0 :*
UDP 0 0 0.0.0.0: 8888 0.0.0.0 :*
UDP 0 0 0.0.0.0: 111 0.0.0.0 :*
UDP 0 0 0.0.0.0: 882 0.0.0.0 :*
We can see that UDP contains "0.0.0.0: 8888", indicating that the service program is running properly and can receive data from any IP address on the host and the port is 8888.
If you execute the./udpserv & command again, the following information is displayed:
BIND error: address already in use
It indicates that a service program is running.
3. Run the UDP client program
Run the./udpclient 127.0.0.1 command to start the customer program and use 127.0.0.1 to connect to the service program. The execution result is as follows:
Hello, world!
Hello, world!
This is a test
This is a test
^ D
The entered data is returned from the service program correctly. Press Ctrl + D to end the input and exit the program.
If the service program is not started and the client program is executed, the following information is displayed:
$./Udpclient 127.0.0.1
Test
Read error: Connection refused
This indicates that no service program is bound to the specified IP address and port, and the client program exits. This is the benefit of using connect (). Note that the error message here is received after the data is sent to the service program, rather than when you call connect. If you use the tcpdump program to capture packets, you will find that the ICMP error message is received.