UNIX Network Programming volume 1 echo client UDP timeout settings

Source: Internet
Author: User

This article is senlie original, reproduced Please retain this address: http://blog.csdn.net/zhengsenlie


Initial code:

# Include "unp. H" intmain (INT argc, char ** argv) {intsockfd; struct sockaddr_inservaddr; If (argc! = 2) err_quit ("Usage: udpcli <IPaddress>"); // 1. specify the Server IP address and port bzero (& servaddr, sizeof (servaddr); servaddr. sin_family = af_inet; servaddr. sin_port = htons (serv_port); inet_ton (af_inet, argv [1], & servaddr. sin_addr); // 2. create a UDP socket sockfd = socket (af_inet, sock_dgram, 0); // 3. pass the UDP socket and server socket address structure to the dg_cli function dg_cli (stdin, sockfd, (Sa *) & servaddr, sizeof (servaddr); exit (0 );} # include "unp. H "voiddg_cli (F Ile * FP, int sockfd, const Sa * pservaddr, socklen_t servlen) {INTN; charsendline [maxline], recvline [maxline + 1]; // 1. fgets reads a text line from the standard input while (fgets (sendline, maxline, FP )! = NULL) {// 2. use sendto to send text lines from the sockfd socket to the server sendto (sockfd, sendline, strlen (sendline), 0, pservaddr, servlen) specified by pservaddr; // 3. use recvfrom to read the server's echo n = recvfrom (sockfd, recvline, maxline, 0, null, null) from the sockfd socket; // 4. use fputs to display the echo text to the standard output recvline [N] = 0;/* null terminate */fputs (recvline, stdout );}}




Problem: the fifth and sixth parameters specified by recvfrom are null, so that any process is on the same host as the customer process.
You can send a datagram to the customer's IP address and port on different hosts.
1. Verify the received response, retain the response from the datagram sent to the server, and ignore any other datagram.
/*** UDP authentication server address ***/# include "unp. H "voiddg_cli (File * FP, int sockfd, const Sa * pservaddr, socklen_t servlen) {INTN; charsendline [maxline], recvline [maxline + 1]; socklen_tlen; struct sockaddr * preply_addr; // 1. allocate another socket address structure preply_addr = malloc (servlen); While (fgets (sendline, maxline, FP )! = NULL) {sendto (sockfd, sendline, strlen (sendline), 0, pservaddr, servlen); Len = servlen; n = recvfrom (sockfd, recvline, maxline, 0, preply_addr, & Len); // 2. compare the returned address if (Len! = Servlen | memcmp (pservaddr, preply_addr, Len )! = 0) {printf ("reply from % s (ignored) \ n", sock_ntop (preply_addr, Len); continue;} recvline [N] = 0; /* null terminate */fputs (recvline, stdout );}}



Improvement 1 problem: if the server does not receive the response, it will be blocked in recvfrom.
2.1 improvement: Use sigalrm to set timeout for recvfrom


# Include "unp. H "static voidsig_alrm (INT); voiddg_cli (File * FP, int sockfd, const Sa * pservaddr, socklen_t servlen) {INTN; charsendline [maxline], recvline [maxline + 1]; // 1. set the processing function signal (sigalrm, sig_alrm) for the time-out signal sigalrm; while (fgets (sendline, maxline, FP )! = NULL) {sendto (sockfd, sendline, strlen (sendline), 0, pservaddr, servlen); // 2. before each call to recvfrom, call alarm to set a 5-second timeout alarm (5); If (n = recvfrom (sockfd, recvline, maxline, 0, null, null )) <0) {// 3. if errno is eintr, that is, recvfrom interrupts if (errno = eintr) fprintf (stderr, "socket timeout \ n"); elseerr_sys ("recvfrom error") due to timeout ");} // 4. if you read a line of text from the server, turn off the alarm clock and output the server's response else {ALARM (0); recvline [N] = 0; /* null terminate */fputs (recvline, stdout) ;}}// sigalrm signal processing function static voidsig_alrm (INT signo) {return;/* just interrupt the recvfrom () */}



Improved by 2.2: Use select to set timeout for recvfrom
/* Include readable_timeo */# include "unp. H "// wait for a descriptor to change to readable intreadable_timeo (int fd, int Sec) {fd_setrset; struct timevaltv; // 1. set the descriptor set fd_zero (& rset); fd_set (FD, & rset); // 2. set the number of seconds to wait TV. TV _sec = sec; TV. TV _usec = 0; // 3. blocking return (select (FD + 1, & rset, null, null, & TV) on select )); /* 4> 0 if descriptor is readable */}/* end readable_timeo */intreadable_timeo (int fd, int Sec) {INTN; If (n = readable_timeo (FD, Sec) <0) err_sys ("readable_timeo error"); Return (n) ;}# include "unp. H "voiddg_cli (File * FP, int sockfd, const Sa * pservaddr, socklen_t servlen) {INTN; charsendline [maxline], recvline [maxline + 1]; while (fgets (sendline, maxline, FP )! = NULL) {sendto (sockfd, sendline, strlen (sendline), 0, pservaddr, servlen); // 1. recvfrom is called only when readable_timeo tells the concerned descriptor to be readable. This ensures that recvfrom does not block if (readable_timeo (sockfd, 5) = 0) {fprintf (stderr, "socket timeout \ n");} else {// 2. receive and output data to stdoutn = recvfrom (sockfd, recvline, maxline, 0, null, null); recvline [N] = 0;/* null terminate */fputs (recvline, stdout );}}}





2.3 Improvement: Use so_rcvtimeo socket option to set timeout for recvfrom
# Include "unp. H "voiddg_cli (File * FP, int sockfd, const Sa * pservaddr, socklen_t servlen) {INTN; charsendline [maxline], recvline [maxline + 1]; struct timevaltv; // 1. set timeout TV on socket. TV _sec = 5; TV. TV _usec = 0; setsockopt (sockfd, sol_socket, so_rcvtimeo, & TV, sizeof (TV); While (fgets (sendline, maxline, FP )! = NULL) {sendto (sockfd, sendline, strlen (sendline), 0, pservaddr, servlen); 2. receive data. If timeout occurs, recvfrom returns the ewouldblock error n = recvfrom (sockfd, recvline, maxline, 0, null, null); If (n <0) {If (errno = ewouldblock) {fprintf (stderr, "socket timeout \ n"); continue;} elseerr_sys ("recvfrom error");} recvline [N] = 0; /* null terminate */fputs (recvline, stdout );}}


UNIX Network Programming volume 1 echo client UDP timeout settings

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.