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 */ }
void *do_get_read(void *vptr) { int fd,n; char line[MAXLINE]; struct file *fptr; fptr = (struct file *) vptr; fd = tcp_connect(fptr->f_host,SERV); fptr->f_fd = fd; printf("do_get_read for %s, fd %d, thread %d\n",fptr->f_name,fd,fptr->f_tid); write_get_cmd(fptr); // write() the GET command // read server's reply for (;;) { if ((n=read(fd,line,MAXLINE))==0) break; // server closed connection printf("read %d bytes for %s\n",n,fptr->f_name); } printf("end-of-file on %s\n",fptr->f_name); close(fd); pthread_mutex_lock(&ndone_mutex); fptr->f_flags = F_DONE; // clear F_READING ndone++; pthread_cond_signal(&ndone_cond); // 叫醒所有在等待ndone_cond的thread pthread_mutex_unlock(&ndone_mutex); // 釋放ndone_mutex資源 return (fptr); }
void * do_get_read(void *vptr) { int fd, n; char line[MAXLINE]; struct file *fptr; fptr = (struct file *) vptr; fd = Tcp_connect(fptr->f_host, SERV); fptr->f_fd = fd; printf("do_get_read for %s, fd %d, thread %d\n", fptr->f_name, fd, fptr->f_tid); write_get_cmd(fptr); /* write() the GET command */ /* 4Read server's reply */ for ( ; ; ) { if ( (n = Read(fd, line, MAXLINE)) == 0) break; /* server closed connection */ printf("read %d bytes from %s\n", n, fptr->f_name); } printf("end-of-file on %s\n", fptr->f_name); Close(fd); fptr->f_flags = F_DONE; /* clears F_READING */ Pthread_mutex_lock(&ndone_mutex); ndone++; Pthread_cond_signal(&ndone_cond); Pthread_mutex_unlock(&ndone_mutex); return(fptr); /* terminate thread */ }
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); flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); 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); FD_SET(fd, &wset); maxfd = max(maxfd, fd); } else write_get_cmd(fptr); }
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 ); flags = _Fcntl(fd, F_GETFL, 0); _Fcntl(fd, F_SETFL, flags | O_NONBLOCK); n = connect(fd, ai->ai_addr, ai->ai_addrlen); if(n < 0){ if(errno != EINPROGRESS) error("Nonblocking connect error"); fptr->f_flags = F_CONNECTING; FD_SET(fd, &rset); FD_SET(fd, &wset); if(fd > max_fd) max_fd = fd; }else if(n >= 0) write_get_cmd(fptr); }
void start_connect(const file *fptr){ int n,fd,flags; struct addrinfo hint,*res,*ressave; bzero(&hint); hint.ai_flags = AI_CANONNAME; hint.ai_family = AF_UNSPEC; hint.ai_socktype = SOCK_STREAM; if((n = getaddrinfo(fptr->f_host,SERV,&hint,&res)) != 0) err_quit("start connect error for %s %s :%s\n",fptr->f_name,SERV,gai_strerror(n)); fd = Socket(res->ai_family,res->ai_socktype,res->ai_protocol); fptr->f_fd = fd; flags = Fctnl(fd,F_GETFL,0); Fctnl(fd,F_SETFL,flags | O_NONBLOCK); if((n = Connect(fd,ai_addr,ai_addrlen)) < 0){ if(errno != EINPROGRESS) err_sys("nonblocking connection error!"); fptr->flags = F_CONNECTING; FD_SET(fd,&rset); FD_SET(fd,&wset); if(fd > maxfd) maxfd = fd; }else{ write_get_cmd(fptr); } }
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; //register int ret = 0; struct kevent changes[1]; EV_SET(&changes[0], fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL); ret = kevent(kq, changes, 1, NULL, 0, NULL); if (ret < 0) { err_sys("kevent()"); } EV_SET(&changes[0], fd, EVFILT_READ, EV_ADD, 0, 0, NULL); ret = kevent(kq, changes, 1, NULL, 0, NULL); if (fd > maxfd) maxfd = fd; } else if (n >= 0) /* connect is already done */ { write_get_cmd(fptr); /* write() the GET command */ } }
void *do_get_read(void *vptr) { int fd, n; char line[MAXLINE]; struct file *fptr; rio_t rio; fptr = (struct file *) vptr; fd = tcpConnect(fptr->f_host, SERV); fptr->f_fd = fd; printf("do_get_read for name:%s host:%s, fd %d, thread %d\n", fptr->f_name,fptr->f_host, fd, fptr->f_tid); write_get_cmd(fptr); /* write() the GET command */ rio_readinitb(&rio,fd); while((n = rio_readlineb(&rio,line,sizeof(line))) > 1) { printf("read %d bytes from name:%s host:%s\n", n, fptr->f_name,fptr->f_host); if (strcmp(line, END_OF_HTML) == 0) { break; } parseUrl(line,fptr->f_host); } printf("end-of-file on name:%s host:%s\n", fptr->f_name,fptr->f_host); close(fd); fptr->f_flags = F_DONE; /* clears F_READING */ pthread_mutex_lock(&ndone_mutex); ndone++; pthread_cond_signal(&ndone_cond); pthread_mutex_unlock(&ndone_mutex); return(fptr); /* terminate thread */ }
void start_connect(struct file *fptr) { int fd, flags, n; struct addrinfo *ai; if ((ai = host_serv(fptr->f_host, SERV, 0, SOCK_STREAM)) < 0) { err_sys("host_serv error"); } if ((fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0) { err_sys("socket error"); } fptr->f_fd = fd; printf("start_connect for %s, fd %d\n", fptr->f_name, fd); // set socket nonblocking if ((flags = fcntl(fd, F_GETFL, 0)) < 0) { err_sys("fcntl error"); } if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) { err_sys("fcntl error"); } // initiate 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 } }
int main(int argc, char **argv) { int i, fd, n, maxnconn, flags, error, ret, index; 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]); kq = kqueue(); 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--; } struct kevent events[2]; ret = kevent(kq, NULL, 0, events, nfiles, NULL); for (i = 0; i < ret; i++) { //fd = file[i].f_fd; struct kevent event = events[i]; //kqueue返回的events list事件是不按照顺序的。所以要根据event找到file index。这一点跟select有很大的不同,因为select是按照顺序的 index = find_file_index_by_event(event); flags = file[index].f_flags; if (flags == 0 || flags & F_DONE) continue; int fd = event.ident; int avail_bytes = event.data; if (flags & F_CONNECTING && event.filter == EVFILT_WRITE) { n = sizeof(error); //todo 这里不加socklen_t就编译不通过! ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&n); if ( ret < 0 || error != 0) { err_ret("nonblocking connect failed for %s", file[index].f_name); } /* 4connection established */ printf("connection established for %s\n", file[index].f_name); write_get_cmd(&file[index]);/* write() the GET command */ } else if (flags & F_READING && event.filter == EVFILT_READ) { memset(buf, 0, sizeof(buf)); if ( (n = Read(fd, buf, sizeof(buf)-1)) == 0) { printf("end-of-file on %s\n", file[index].f_name); Close(fd); file[index].f_flags = F_DONE; /* clears F_READING */ struct kevent changes[1]; EV_SET(&changes[0], fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); ret = kevent(kq, changes, 1, NULL, 0, NULL); nconn--; nlefttoread--; } else { buf[n]= '\0'; printf("read %d bytes from %s\n", n, file[index].f_name); printf("buf = %s\n", buf); } } } } exit(0); }
int main(int argc, char **argv) { int i, fd, n, maxnconn, flags, error; char buf[MAXLINE]; fd_set rs, ws; if (argc < 5) { fprintf(stderr, "usage: web <#conns> <hostname> <homepage> <file1> ...\n"); exit(1); } 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) { fprintf(stderr, "nlefttoconn = %d but nothing found\n", nlefttoconn); exit(1); } start_connect(&file[i]); nconn++; nlefttoconn--; } rs = rset; ws = wset; if ((n = select(maxfd+1, &rs, &ws, NULL, NULL)) < 0) { perror("select error"); exit(1); } 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) { fprintf(stderr, "nonblocking connect failed for %s: %s\n", file[i].f_name, strerror(errno)); } /* 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) { perror("read error"); exit(1); } else if (n == 0) { printf("end-of-file on %s\n", file[i].f_name); if (close(fd) == -1) { perror("close error"); exit(1); } 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); }
/**Test for connect delay**/ int main(int argc, char *argv[]) { int i, fd, maxnconn, flags, error; socklen_t n; 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; nconn = 0; nlefttoread = nlefttoconn = nfiles; while(nlefttoread > 0) { while(nconn < maxnconn && nlefttoconn > 0) { 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); } printf("connection established for %s\n", file[i].f_name); FD_CLR(fd, &wset); write_get_cmd(&file[i]); } 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; FD_CLR(fd, &rset); nconn--; nlefttoread--; } else printf("read %d bytes from %s\n", n, file[i].f_name); } } } exit(0); }