现在的位置: 首页 > 综合 > 正文

Socket的读写状态变化

2013年11月25日 ⁄ 综合 ⁄ 共 4038字 ⁄ 字号 评论关闭

UNP里指出了socket 读写状态变化的条件:

下面用一个例子来测试一下(根据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

抱歉!评论已关闭.