Advanced I/O Functions
Introduction
This chapter covers a variety of functions and techniques that we lump into the category of “advanced I/O.” First is setting a timeout on an I/O operation, which can be done in three different ways. Next are three more variations on the read and write functions: recv and send, which allow a fourth argument that contains flags from the process to the kernel, readv and writev, which let us specify a vector of buffers to input into or output from, and recvmsg and sendmsg, which combine all the features from the other I/O functions along with the new capability of receiving and sending ancillary data.
Socket Timeouts
There are three ways to place a timeout on an I/O operation involving a socket:
1.Call alarm, which generates the SIGALRM signal when the specified time has expired. This involves signal handling, which can differ from one implementation to the next, and it may interfere with other existing calls to alarm in the process.
2.Block waiting for I/O in select, which has a time limit built-in, instead of blocking in a call to read or write.
3.Use the newer SO_RCVTIMEO and SO_SNDTIMEO socket options. The problem with this approach is that not all implementations support these two socket options.
#include "unp.h"
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, saptr, salen))<0)
{
close(sockfd);
if(errno==EINTR)
errno=ETIMEDOUT;
}
alarm(0);
Signal(SIGALRM, sigfunc);
return n;
}
static void connect_alarm(int signo)
{
return;
}
connect with a timeout
#include "unp.h"
static void sig_alarm(int);
int dg_client(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;
Fputs(recvline, stdout);
}
}
}
static void sig_alrm(int signo)
{
return;
}
dg_cli function with alarm to timeout recvfrom