1 / 22

Advanced I/O Functions

Advanced I/O Functions. Outline. Socket Timeouts recv and send Functions readv and writev Functions recvmsg and sendmsg Function Ancillary Data How much Data is Queued? Sockets and Standard I/O. Socket Timeouts. Three ways to place a timeout on an I/O operation involving a socket

kirima
Télécharger la présentation

Advanced I/O Functions

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Advanced I/O Functions

  2. Outline Socket Timeouts recv and send Functions readv and writev Functions recvmsg and sendmsg Function Ancillary Data How much Data is Queued? Sockets and Standard I/O

  3. Socket Timeouts Three ways to place a timeout on an I/O operation involving a socket Call alarm, which generates the SIGALRM signal when the specified time has expired. Block waiting for I/O in select, which has a time limit built in, instead of blocking in a call to read or write. Use the newer SO_RCVTIMEO and SO_SNDTIMEO socket options.

  4. Connect with a Timeout Using SIGALRM static void connect_alarm(int); int connect_timeo(int sockfd, const SA *saptr, socklen_t salen, int nsec) { Sigfunc *sigfunc; int n; sigfunc = Signal(SIGALRM, connect_alarm); if (alarm(nsec) != 0) err_msg("connect_timeo: alarm was already set"); if ( (n = connect(sockfd, (struct sockaddr *) saptr, salen)) < 0) { close(sockfd); if (errno == EINTR) errno = ETIMEDOUT; } alarm(0); /* turn off the alarm */ return(n); } static void connect_alarm(int signo) { return; /* just interrupt the connect() */ }

  5. recvfrom with a Timeout Using SIGALRM static void sig_alrm(int); void dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen) { int n; char sendline[MAXLINE], recvline[MAXLINE + 1]; Signal(SIGALRM, sig_alrm); while (Fgets(sendline, MAXLINE, fp) != NULL) { Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen); alarm(5); if ( (n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL)) < 0) { if (errno == EINTR) fprintf(stderr, "socket timeout\n"); else err_sys("recvfrom error"); } else { alarm(0); recvline[n] = 0; /* null terminate */ Fputs(recvline, stdout); } } } static void sig_alrm(int signo) { return; /* just interrupt the recvfrom() */ }

  6. recvfrom with a Timeout Using select int readable_timeo(int fd, int sec) { fd_set rset; struct timeval tv; FD_ZERO(&rset); FD_SET(fd, &rset); tv.tv_sec = sec; tv.tv_usec = 0; return(select(fd+1, &rset, NULL, NULL, &tv)); /* > 0 if descriptor is readable */ }

  7. Timeout Using the SO_RCVTIMEO SO_SNDTIMEO Socket Option • We set this option once for a descriptor, specifying the timeout value, and this timeout then applies to all read operations on that descriptor. • we set the option only once, compared to the previous two methods, which required doing something before every operation on which we wanted to place a time limit. • neither socket option can be used to set a timeout for a connect.

  8. recvfrom with a Timeout Using the SO_RCVTIMEO Socket Option int n; char sendline[MAXLINE], recvline[MAXLINE + 1]; struct timeval tv; tv.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); n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL); if (n < 0) { if (errno == EWOULDBLOCK) { fprintf(stderr, "socket timeout\n"); continue; } else err_sys("recvfrom error"); } recvline[n] = 0; /* null terminate */ Fputs(recvline, stdout); }

  9. recv and send Functions #include <sys/socket.h> ssize_t recv (int sockfd, void *buff, size_t nbytes, int flags); ssize_t send (int sockfd, const void *buff, size_t nbytes, int flags);

  10. readv and writev Functions readv and writev let us read into or write from one or more buffers with a single function call. are called scatter read and gather write. #include <sys/uio.h> ssize_t readv (int filedes, const struct iovec *iov, int iovcnt); ssize_t writev (int filedes, const struct iovec *iov, int iovcnt); Struct iovec { void *iov_base; /* starting address of buffer */ size_t iov_len; /* size of buffer */ };

  11. readv and writev Functions The readv and writev functions can be used with any descriptor, not just sockets. writev is an atomic operation. For a record-based protocol such as UDP, one call to writev generates a single UDP datagram. One use of writev with the TCP_NODELAY socket option. //modify a write of 4 bytes followed by a write of 396 bytes could invoke the Nagle algorithm and a preferred solution is to call writev for the two buffers.

  12. Nagle’s Algorithm if there is new data to send if the window size >= MSS and available data is >= MSS send complete MSS segment now else if there is unconfirmed data still in the pipe enqueue data in the buffer until an acknowledge is received else send data immediately end if end if end if

  13. recvmsg and sendmsg #include <sys/socket.h> ssize_t recvmsg (int sockfd, struct msghdr *msg, int flags); ssize_t sendmsg (int sockfd, struct msghdr *msg, int flags); Struct msghdr { void *msg_name; /* starting address of buffer */ socklen_t msg_namelen; /* size of protocol address */ struct iovec *msg_iov; /* scatter/gather array */ size_t msg_iovlen; /* # elements in msg_iov */ void *msg_control; /* ancillary data; must be aligned for a cmsghdr structure */ socklen_t msg_controllen; /* length of ancillary data */ int msg_flags; /* flags returned by recvmsg() */ };

  14. recvmsg and sendmsg

  15. recvmsg and sendmsg

  16. recvmsg and sendmsg

  17. Ancillary Data Ancillary data can be sent and received using the msg_control and msg_controllen members of the msghdr structure with sendmsg and recvmsg functions.

  18. Ancillary Data

  19. Ancillary Data

  20. How Much Data Is Queued? nonblocking I/O MSG_PEEK with MSG_DONTWAIT flag FIONREAD command of ioctl

  21. Sockets and Standard I/O The standard I/O stream can be used with sockets, but there are a few items to consider. A standard I/O stream can be created from any desciptor by calling the fdopen function. Similarly, given a standard I/O stream, we can obtain the corresponding descriptor by calling fileno. fseek, fsetpos, rewind functions is that they all call lseek, which fails on a socket. The easiest way to handle this read-write problem is to open two standard I/O streams for a given socket: one for reading, and one for writing.

  22. Sockets and Standard I/O #include "unp.h" void str_echo(int sockfd) { char line[MAXLINE]; FILE *fpin, *fpout; fpin = Fdopen(sockfd, "r"); fpout = Fdopen(sockfd, "w"); for ( ; ; ) { if (Fgets(line, MAXLINE, fpin) == NULL) return; /* connection closed by other end */ Fputs(line, fpout); } }

More Related