请教大家一个问题,关于UNIX网络编程第16章非阻塞I/O中的一段代码

xgbc2046 2010-06-24 09:45:50
#include	"web.h"

int
main(int argc, char **argv)
{
int i, fd, n, maxnconn, flags, error;
char buf[MAXLINE];
fd_set rs, ws;

if (argc < 5)
err_quit("usage: web <#conns> <hostname> <homepage> <file1> ...");
maxnconn = atoi(argv[1]);

nfiles = min(argc - 4, MAXFILES);
for (i = 0; i < nfiles; i++) {
file[i].f_name = argv[i + 4];
file[i].f_host = argv[2];
file[i].f_flags = 0;
}
printf("nfiles = %d\n", nfiles);

home_page(argv[2], argv[3]);

FD_ZERO(&rset);
FD_ZERO(&wset);
maxfd = -1;
nlefttoread = nlefttoconn = nfiles;
nconn = 0;
/* end web1 */
/* include web2 */
while (nlefttoread > 0) {
while (nconn < maxnconn && nlefttoconn > 0) {
/* 4find a file to read */
for (i = 0 ; i < nfiles; i++)
if (file[i].f_flags == 0)
break;
if (i == nfiles)
err_quit("nlefttoconn = %d but nothing found", nlefttoconn);
start_connect(&file[i]);
nconn++;
nlefttoconn--;
}

rs = rset;
ws = wset;
n = Select(maxfd+1, &rs, &ws, NULL, NULL);

for (i = 0; i < nfiles; i++) {
flags = file[i].f_flags;
if (flags == 0 || flags & F_DONE)
continue;
fd = file[i].f_fd;
if (flags & F_CONNECTING &&
(FD_ISSET(fd, &rs) || FD_ISSET(fd, &ws))) {
n = sizeof(error);
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &n) < 0 ||
error != 0) {
err_ret("nonblocking connect failed for %s",
file[i].f_name);
}
/* 4connection established */
printf("connection established for %s\n", file[i].f_name);
FD_CLR(fd, &wset); /* no more writeability test */
write_get_cmd(&file[i]);/* write() the GET command */

} else if (flags & F_READING && FD_ISSET(fd, &rs)) {
if ( (n = Read(fd, buf, sizeof(buf))) == 0) {
printf("end-of-file on %s\n", file[i].f_name);
Close(fd);
file[i].f_flags = F_DONE; /* clears F_READING */
FD_CLR(fd, &rset);
nconn--;
nlefttoread--;
} else {
printf("read %d bytes from %s\n", n, file[i].f_name);
}
}
}
}
exit(0);

#include	"web.h"

void
start_connect(struct file *fptr)
{
int fd, flags, n;
struct addrinfo *ai;

ai = Host_serv(fptr->f_host, SERV, 0, SOCK_STREAM);

fd = Socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
fptr->f_fd = fd;
printf("start_connect for %s, fd %d\n", fptr->f_name, fd);

/* 4Set socket nonblocking */
flags = Fcntl(fd, F_GETFL, 0);
Fcntl(fd, F_SETFL, flags | O_NONBLOCK);

/* 4Initiate nonblocking connect to the server. */
if ( (n = connect(fd, ai->ai_addr, ai->ai_addrlen)) < 0) {
if (errno != EINPROGRESS)
err_sys("nonblocking connect error");
fptr->f_flags = F_CONNECTING;
FD_SET(fd, &rset); /* select for reading and writing */
FD_SET(fd, &wset);
if (fd > maxfd)
maxfd = fd;

} else if (n >= 0) /* connect is already done */
write_get_cmd(fptr); /* write() the GET command */
}

#include	"web.h"

void
write_get_cmd(struct file *fptr)
{
int n;
char line[MAXLINE];

n = snprintf(line, sizeof(line), GET_CMD, fptr->f_name);
Writen(fptr->f_fd, line, n);
printf("wrote %d bytes for %s\n", n, fptr->f_name);

fptr->f_flags = F_READING; /* clears F_CONNECTING */

FD_SET(fptr->f_fd, &rset); /* will read server's reply */
if (fptr->f_fd > maxfd)
maxfd = fptr->f_fd;
}
...全文
167 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
xgbc2046 2010-06-30
  • 打赏
  • 举报
回复
十分感谢ls的回答
wqkjj 2010-06-24
  • 打赏
  • 举报
回复
是的,使flags & F_CONNECTING为假。
两种状态,前者表示socket正处于链接过程中,后者表示socket处于读写过程中。
xgbc2046 2010-06-24
  • 打赏
  • 举报
回复
start_connect(struct file *fptr)这个函数最后调用了write_get_cmd(struct file *fptr),在write_get_cmd(struct file *fptr)这个函数里把start_connect这个函数里的fptr->f_flags = F_CONNECTING改成了fptr->f_flags = F_READING,而在第一个函数里的if (flags & F_CONNECTING &&(FD_ISSET(fd, &rs) ||FD_ISSET(fd, &ws)的这个条件就没什么用了?多谢各位执教了
精通Windows Sockets网络开发——基于Visual C++实现 目 录 第1篇网络开发基础篇 第1准备开发环境 1.1windows sockets开发概述 1.1.1网络程序开发应用 1.1.2网络程序结构——c/s、b/s 1.1.3网络程序通信基础——网络协议 1.1.4网络程序通信技术——windows sockets介绍 1.2连接网络 1.2.1tcp/ip设置 1.2.2tcp/ip是否工作正常 1.2.3系统与网络适配器间的通信 1.2.4默认网关 1.2.5ping其他计算机ip地址 1.3创建应用程序 1.3.1控制台程序 1.3.2mfc应用程序 1.4调试两个应用程序 1.4.1启动两个工程 1.4.2将一个工程加入到另一个工程空间 1.5配置开发环境 1.6小结 第2tcp/ip简介 2.1开放系统互连参考模型 2.2tcp/ip协议概述 2.2.1tcp/ip模型 2.2.2udp 2.2.3tcp 2.2.4端口 2.3小结 第3windows sockets基础 3.1windows sockets 3.1.1应用程序与windows sockets的关系 3.1.2套接字 3.2协议特征 3.2.1面向连接与面向无连接 3.2.2可靠性与次序性 3.2.3面向消息 3.2.4部分消息 3.2.5从容关闭 3.2.6路由选择 3.2.7广播数据 3.3ip定址 3.3.1ip定址 3.3.2字节顺序问题 3.4基本tcp套接字编程 3.4.1wsastartup()函数 3.4.2socket()函数 3.4.3bind()函数 3.4.4listen()函数 3.4.5accept()函数 3.4.6recv()函数 3.4.7send()函数 3.4.8closesocket()函数 3.4.9shutdown()函数 3.4.10connect()函数 3.5tcp示例程序 3.5.1服务器实现 3.5.2客户端实现 3.6基本udp套接字编程 3.6.1recvfrom()函数 3.6.2sendto()函数 3.7udp示例程序 3.7.1服务器实现 3.7.2客户端实现 3.8套接字选项41 3.8.1getsockopt()函数 3.8.2setsockopt()函数 3.8.3sol_socket选项级别 3.9小结 第2篇visual c++网络模式开发篇 第4阻塞模式开发 第5非阻塞模式开发 第6select模型开发 第7wsaasyncselect模型开发 第8wsaeventselect模型开发 第9重叠i/o模型开发 第10完成端口模型开发

23,110

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧