下面用一个例子来测试一下(根据UNP的例子改编)。
1. daytimecli.c
#include "unp.h"
#include <sys/select.h>
int
main(int argc, char **argv)
{
int sockfd, n;
char recvline[MAXLINE + 1];
struct sockaddr_in servaddr;
if (argc != 2)
err_quit("usage: a.out <IPaddress>");
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
err_sys("socket error");
fd_set writeFd, readFd;
FD_ZERO(&writeFd);
FD_ZERO(&readFd);
FD_SET(sockfd, &writeFd);
FD_SET(sockfd, &readFd);
if(select(sockfd + 1, &readFd, &writeFd, NULL, NULL) == -1)
{
printf("select fails at line %d\n", __LINE__);
}
else
{
if(FD_ISSET(sockfd, &readFd))
{
printf("[client] After creation, socket is readable\n");
}
if(FD_ISSET(sockfd, &writeFd))
{
printf("[client] After creation, socket is writable\n");
}
}
FD_ZERO(&writeFd);
FD_ZERO(&readFd);
FD_SET(sockfd, &writeFd);
FD_SET(sockfd, &readFd);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(13); /* daytime server */
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
err_quit("inet_pton error for %s", argv[1]);
printf("[client]: connect to server\n");
if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0)
err_sys("connect error");
if(select(sockfd + 1, &readFd, &writeFd, NULL, NULL) > 0)
{
if(FD_ISSET(sockfd, &readFd))
{
printf("[client] After connect, socket is readable\n");
}
if(FD_ISSET(sockfd, &writeFd))
{
printf("[client] After connect, socket is writable\n");
}
}
FD_ZERO(&readFd);
FD_SET(sockfd, &readFd);
if(select(sockfd + 1, &readFd, NULL, NULL, NULL) > 0)
{
if(FD_ISSET(sockfd, &readFd))
{
printf("[client] now sockfd is readable again\n");
}
}
#if 0
while ( (n = read(sockfd, recvline, MAXLINE)) > 0) {
recvline[n] = 0; /* null terminate */
if (fputs(recvline, stdout) == EOF)
err_sys("fputs error");
}
if (n < 0)
err_sys("read error");
#endif
n = recv(sockfd, recvline, MAXLINE, MSG_DONTWAIT | MSG_NOSIGNAL);
if(n > 0)
{
printf("[client] receive %d bytes\n", n);
int nread = ioctl(sockfd, FIONREAD, &nread);
printf("[client] ioctl return: nread = %d\n", nread);
if(nread > 0)
{
//printf("still there is data %d bytes\n", nread);
}
else
{
n = recv(sockfd, recvline, 1, MSG_PEEK | MSG_DONTWAIT);
int local_errno = errno;
if(local_errno != EAGAIN || n == 0)
{
printf("[client] server is closed\n");
}
else
{
printf("[client] errno: %d peek data is %d bytes\n", local_errno, n);
}
}
}
exit(0);
}
2. daytimesrv.c
#include "unp.h"
#include <time.h>
#include <sys/select.h>
int
main(int argc, char **argv)
{
int listenfd, connfd;
struct sockaddr_in servaddr;
char buff[MAXLINE];
time_t ticks;
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(13); /* daytime server */
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
fd_set readFd, writeFd;
FD_ZERO(&writeFd);
FD_ZERO(&readFd);
FD_SET(listenfd, &writeFd);
FD_SET(listenfd, &readFd);
if(select(listenfd + 1, &readFd, &writeFd, NULL, NULL) > 0)
{
if(FD_ISSET(listenfd, &readFd))
{
printf("[server] listen fd is readable\n");
}
if(FD_ISSET(listenfd, &writeFd))
{
printf("[server] listen fd is writable\n");
}
}
for ( ; ; ) {
printf("[server]: call accept\n");
connfd = Accept(listenfd, (SA *) NULL, NULL);
FD_ZERO(&writeFd);
FD_ZERO(&readFd);
FD_SET(connfd, &writeFd);
FD_SET(connfd, &readFd);
if(select(connfd + 1, &readFd, &writeFd, NULL, NULL) > 0)
{
if(FD_ISSET(connfd, &readFd))
{
printf("[server]: connected fd is readable\n");
}
if(FD_ISSET(connfd, &writeFd))
{
printf("[server] connected fd is writable\n");
}
}
// printf("server accept connection\n");
// close(connfd);
// continue;
ticks = time(NULL);
snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
printf("[server] write data to client\n");
Write(connfd, buff, strlen(buff));
printf("[server]: server-side socket closed\n");
Close(connfd);
//printf("server-side socket closed\n");
}
}
运行结果如下:
@taotao:~/code/unpv13e/intro$ sudo sh -c "./daytimetcpsrv &"
charles@taotao:~/code/unpv13e/intro$ sudo ./daytimetcpcli 192.168.2.12
[client] After creation, socket is readable
[client] After creation, socket is writable
[client]: connect to server
[client] After connect, socket is writable
[server] listen fd is readable
[server]: call accept
[server] connected fd is writable
[server] write data to client
[client] now sockfd is readable again
[server]: server-side socket closed
[server]: call accept
[client] receive 26 bytes
[client] ioctl return: nread = 0
[client] server is closed