Nonblocking ‘accept’
#inlcude "web.h"

int main(int argc, char **argv)
{
    int sockfd;
    struct linger ling;
    struct sockaddr_in servaddr;

    if(argc!=2)
        err_quit("usage: tcpcli <IPaddress>");

    sockfd=Socket(AF_INET, SOCK_STREAM, 0);

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family=AF_INET;
    servaddr.sin_port=htons(SERV_PORT);
    Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

    Connect(sockfd, (SA*) &servaddr, sizeof(servaddr));

    ling.l_onoff=1;
    ling.l_linger=0;

    Setscokopt(sockfd, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));

    Close(sockfd);
    return 0;
}

TCP echo client that creates connection and sends an RST

We noted that when the client aborts the connection before the server calls accept, Berkeley-derived implementations do not return the aborted connection to the server, while other implementations should return ECONNABORTED but often return EPROTO instead. Consider the following example of a Berkeley-derived implementation:

  • The client establishes the connection and then aborts it as in Figure 16.21.
  • select returns readable to the server process, but it takes the server a short time to call accept.
  • Between the server’s return from select and its calling accept, the RST is received from the client.
  • The completed connection is removed from the queue and we assume that no other completed connections exist.
  • The server calls accept, but since there are no completed connections, it blocks.

The server will remain blocked in the call to accept until some other client establishes a connection. But in the meantime, assuming a server like Figure 6.22(See 8.4.8), the server is blocked in the call to accept and will not handle any other ready descriptors.

The fix for this problem is as follows:

1.Always set a listening socket to nonblocking when you use select to indicate when a connection is ready to be accepted.
2.Ignore the following errors on the subsequent call to accept: EWOULDBLOCK (for Berkeley-derived implementations, when the client aborts the connection), ECONNABORTED (for POSIX implementations, when the client aborts the connection), EPROTO (for SVR4 implementations, when the client aborts the connection), and EINTR (if signals are being caught).

‘ioctl’ Operations

Introduction

The ioctl function has traditionally been the system interface used for everything that didn’t fit into some other nicely defined category. POSIX is getting rid of ioctl for certain functionality by creating specific wrapper functions to replace ioctls whose functionality is being standardized by POSIX. For example, the Unix terminal interface was traditionally accessed using ioctl, but POSIX created 12 new functions for terminals: tcgetattr to get the terminal attributes, tcflush to flush pending input or output, and so on. In a similar vein, POSIX has replaced one network ioctl: the new sockatmark function (Section 24.3(See 9.13.3)) replaces the SIOCATMARK ioctl. Nevertheless, numerous ioctls remain for implementation-dependent features related to network programming: obtaining interface information and accessing the routing table and ARP cache, for example.

This chapter provides an overview of the ioctl requests related to network programming, but many of these are implementation-dependent. Additionally, some implementations, including 4.4BSD-derived systems and Solaris 2.6 and later, use sockets in the AF_ROUTE domain (routing sockets) to accomplish many of these operations. We will cover routing sockets in Chapter 18(See 9.7).

A common use of ioctl by network programs (typically servers) is to obtain information on all the host’s interfaces when the program starts: the interface addresses, whether the interface supports broadcasting, whether the interface supports multicasting, and so on.

‘ioctl’ Function

This function affects an open file referenced by the fd argument.

#include <unistd.h>
int ioctl(int fd, int request, ... /* void *arg */ );

4.4BSD defines the second argument to be an unsigned long instead of an int, but that is not a problem since header files define the constants that are used for this argument. As long as the prototype is in scope (i.e., the program using ioctl has included <unistd.h>), the correct type for the system will be used.

Some implementations specify the third argument as a void * pointer instead of the ANSI C ellipsis notation.

There is no standard for the header to include to define the function prototype for ioctl since it is not standardized by POSIX. Many systems define it in <unistd.h>, as we show, but traditional BSD systems define it in <sys/ioctl.h>.

We can divide the requests related to networking into six categories:

  • Socket operations
  • File operations
  • Interface operations
  • ARP cache operations
  • Routing table operations
  • STREAMS system (Chapter 31(See 9.20))
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐