一、web.h

#include    <stdio.h>
#include <netdb.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <sys/select.h>
#include <sys/socket.h> #define MAXFILES 20
#define SERV "80" /* port number or service name */
#define MAXLINE 4096 struct file {
char *f_name; /* filename */
char *f_host; /* hostname or IPv4/IPv6 address */
int f_fd; /* descriptor */
int f_flags; /* F_xxx below */
} file[MAXFILES]; #define F_CONNECTING 1 /* connect() in progress */
#define F_READING 2 /* connect() complete; now reading */
#define F_DONE 4 /* all done */ #define GET_CMD "GET %s HTTP/1.0\r\n\r\n" /* globals */
int nconn, nfiles;
int nlefttoconn, nlefttoread;
int maxfd;
fd_set rset, wset; /* function prototypes */
int min(const int, const int);
int tcp_connect(const char *, const char *);
void err_ret(const char *, ...);
void err_sys(const char *, ...);
void err_quit(const char *, ...);
void home_page(const char *, const char *);
void start_connect(struct file *);
void write_get_cmd(struct file *);
ssize_t writen(int, const void *, size_t);
struct addrinfo * host_serv(const char *, const char *, int, int);

二、web.c

#include    "web.h"

int main(int argc, char **argv)
{
int i, fd, maxnconn;
int flags, error;
char buf[MAXLINE];
fd_set rs, ws;
socklen_t n; if (argc < ) {
err_quit("usage: web <conns> <hostname> <homepage> <file1> ...");
}
maxnconn = atoi(argv[]); nfiles = min(argc - , MAXFILES);
for (i = ; i < nfiles; i++) {
file[i].f_name = argv[i + ];
file[i].f_host = argv[];
file[i].f_flags = ;
}
printf("nfiles = %d\n", nfiles); home_page(argv[], argv[]); FD_ZERO(&rset);
FD_ZERO(&wset);
maxfd = -;
nlefttoread = nfiles;
nlefttoconn = nfiles;
nconn = ; while (nlefttoread > ) {
while (nconn < maxnconn && nlefttoconn > ) {
/* find a file to read */
for (i = ; i < nfiles; i++) {
if (file[i].f_flags == ) {
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+, &rs, &ws, NULL, NULL); for (i = ; i < nfiles; i++) {
flags = file[i].f_flags;
if (flags == || 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) < ||
error != ) {
err_ret("nonblocking connect failed for %s",
file[i].f_name);
}
/* connection 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))) == ) {
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();
}

三、home_page.c

#include    "web.h"

void home_page(const char *host, const char *fname)
{
int fd, n;
char line[MAXLINE]; fd = tcp_connect(host, SERV); /* blocking connect() */ n = snprintf(line, sizeof(line), GET_CMD, fname);
if (writen(fd, line, n) == -) {
err_sys("write error");
} for ( ; ; ) {
if ( (n = read(fd, line, MAXLINE)) == ) {
break; /* server closed connection */
}
printf("read %d bytes of home page\n", n);
/* do whatever with data */
}
printf("end-of-file on home page\n");
close(fd);
}

四、start_connect.c

#include    "web.h"

void start_connect(struct file *fptr)
{
int fd, flags, n;
struct addrinfo *ai; ai = host_serv(fptr->f_host, SERV, , 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); /* Set socket nonblocking */
flags = fcntl(fd, F_GETFL, );
fcntl(fd, F_SETFL, flags | O_NONBLOCK); /* Initiate nonblocking connect to the server. */
if ( (n = connect(fd, ai->ai_addr, ai->ai_addrlen)) < ) {
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 >= ) { /* connect is already done */
write_get_cmd(fptr); /* write() the GET command */
}
}

五、tcp_connect.c

#include    "web.h"

int tcp_connect(const char *host, const char *serv)
{
int sockfd, n;
struct addrinfo hints;
struct addrinfo *res, *ressave; bzero(&hints, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM; if ( (n = getaddrinfo(host, serv, &hints, &res)) != ) {
err_quit("tcp_connect error for %s, %s: %s",
host, serv, gai_strerror(n));
}
ressave = res; do {
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sockfd < ) {
continue; /* ignore this one */
}
if (connect(sockfd, res->ai_addr, res->ai_addrlen) == ) {
break; /* success */
}
close(sockfd); /* ignore this one */
} while ( (res = res->ai_next) != NULL); if (res == NULL) { /* errno set from final connect() */
err_sys("tcp_connect error for %s, %s", host, serv);
} freeaddrinfo(ressave); return (sockfd);
}

六、host_serv.c

#include    <stddef.h>
#include <netdb.h>
#include <strings.h> struct addrinfo *host_serv(const char *host,
const char *serv, int family, int socktype)
{
int n;
struct addrinfo hints, *res; bzero(&hints, sizeof(struct addrinfo));
hints.ai_flags = AI_CANONNAME; /* always return canonical name */
hints.ai_family = family; /* AF_UNSPEC, AF_INET, AF_INET6, etc. */
hints.ai_socktype = socktype; /* 0, SOCK_STREAM, SOCK_DGRAM, etc. */ if ( (n = getaddrinfo(host, serv, &hints, &res)) != ) {
return(NULL);
} return (res); /* return pointer to first on linked list */
}

七、write_get_cmd.c

#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;
}
}

八、writen.c

#include <unistd.h>
#include <errno.h> ssize_t writen(int fd, const void *vptr, size_t n) {
size_t nleft;
ssize_t nwriten;
const char *ptr; ptr = vptr;
nleft = n;
while (nleft > ) {
if ( (nwriten = write(fd, ptr, nleft)) <= ) {
if (nwriten < && errno == EINTR) {
nwriten = ; /* call write() again */
} else {
return (-);
}
}
nleft -= nwriten;
ptr += nwriten;
}
return (n - nwriten);
}

九、others.c

int min(int num1, int num2) {
return (num1<num2?num1:num2);
}

十、error.c

#include    <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h> /* ANSI C header file */
#include <syslog.h> /* for syslog() */ #define MAXLINE 4096 int daemon_proc; /* set nonzero by daemon_init() */ static void err_doit(int, int, const char *, va_list); /* Nonfatal error related to system call
* Print message and return */ void err_ret(const char *fmt, ...) { va_list ap; va_start(ap, fmt);
err_doit(, LOG_INFO, fmt, ap);
va_end(ap);
return;
} /* Fatal error related to system call
* Print message and terminate */ void err_sys(const char *fmt, ...) { va_list ap; va_start(ap, fmt);
err_doit(, LOG_ERR, fmt, ap);
va_end(ap);
exit();
} /* Fatal error related to system call
* Print message, dump core, and terminate */ void err_dump(const char *fmt, ...) {
va_list ap; va_start(ap, fmt);
err_doit(, LOG_ERR, fmt, ap);
va_end(ap);
abort(); /* dump core and terminate */
exit(); /* shouldn't get here */
} /* Nonfatal error unrelated to system call
* Print message and return */ void err_msg(const char *fmt, ...) { va_list ap; va_start(ap, fmt);
err_doit(, LOG_INFO, fmt, ap);
va_end(ap);
return;
} /* Fatal error unrelated to system call
* Print message and terminate */ void err_quit(const char *fmt, ...) { va_list ap; va_start(ap, fmt);
err_doit(, LOG_ERR, fmt, ap);
va_end(ap);
exit();
} /* Print message and return to caller
* Caller specifies "errnoflag" and "level" */ static void err_doit(int errnoflag, int level, const char *fmt, va_list ap) { int errno_save, n;
char buf[MAXLINE + ]; errno_save = errno; /* value caller might want printed */
#ifdef HAVE_VSNPRINTF
vsnprintf(buf, MAXLINE, fmt, ap); /* safe */
#else
vsprintf(buf, fmt, ap); /* not safe */
#endif
n = strlen(buf);
if (errnoflag)
snprintf(buf + n, MAXLINE - n, ": %s", strerror(errno_save));
strcat(buf, "\n"); if (daemon_proc) {
syslog(level, buf, NULL);
} else {
fflush(stdout); /* in case stdout and stderr are the same */
fputs(buf, stderr);
fflush(stderr);
}
return;
}

十一、Makefile

cccc = gcc
prom = web
deps = web.h
objs = web.o home_page.o tcp_connect.o start_connect.o write_get_cmd.o writen.o others.o error.o host_serv.o $(prom): $(objs)
$(cccc) -o $(prom) $(objs) %.o: %.c $(deps)
$(cccc) -c $< -o $@ clean:
rm -rf $(objs) $(prom)

非阻塞connect:Web客户程序的更多相关文章

  1. UNIX网络编程——非阻塞connect: Web客户程序

    非阻塞的connect的实现例子出自Netscape的Web客户程序.客户先建立一个与某个Web服务器的HTTP连接,再获取一个主页.该主页往往含有多个对于其他网页的引用.客户可以使用非阻塞conne ...

  2. UNIX网络编程——非阻塞connect:时间获取客户程序

    #include "unp.h" int connect_nonb(int sockfd, const SA *saptr, socklen_t salen, int nsec) ...

  3. TCP非阻塞accept和非阻塞connect

    http://blog.chinaunix.net/uid-20751538-id-238260.html 非阻塞accept     当一个已完成的连接准备好被accept的时候,select会把监 ...

  4. 面向连接的socket数据处理过程以及非阻塞connect问题

    对于面向连接的socket类型(SOCK_STREAM,SOCK_SEQPACKET)在读写数据之前必须建立连接,首先服务器端socket必须在一个客户端知道的地址进行监听,也就是创建socket之后 ...

  5. (转)非阻塞Connect对于select时应注意问题

    对于面向连接的socket类型(SOCK_STREAM,SOCK_SEQPACKET)在读写数据之前必须建立连接,首先服务器端socket必须在一个客户端知道的地址进行监听,也就是创建socket之后 ...

  6. linux 客户端 Socket 非阻塞connect编程

    开发测试环境:虚拟机CentOS,windows网络调试助手        非阻塞模式有3种用途        1.三次握手同时做其他的处理.connect要花一个往返时间完成,从几毫秒的局域网到几百 ...

  7. UNIX网络编程——非阻塞connect

    当在一个非阻塞的TCP套接字上调用connect时,connect将立即返回一个EINPROGRESS错误,不过已经发起的TCP三次握手继续进行.我们接着使用select检测这个连接或成功或失败的已建 ...

  8. 网络编程之非阻塞connect编写

    一.connect非阻塞编写 TCP连接的建立涉及到一个三次握手的过程,且socket中connect函数需要一直等到客户接收到对于自己的SYN的ACK为止才返回, 这意味着每 个connect函数总 ...

  9. TCP之非阻塞connect和accept

    套接字的默认状态是阻塞的,这就意味着当发出一个不能立即完成的套接字调用时,其进程将被投入睡眠,等待响应操作完成,可能阻塞的套接字调用可分为以下四类: (1) 输入操作,包括read,readv,rec ...

  10. UNIX网络编程-非阻塞connect和非阻塞accept

    1.非阻塞connect 在看了很多资料之后,我自己的理解是:在socket发起一次连接的时候,这个过程需要一段时间来将三次握手的过程走完,如果在网络状况不好或者是其他的一些情况下,这个过程需要比较长 ...

随机推荐

  1. FPGA设计千兆以太网MAC(2)——以太网协议及设计规划

    上篇该系列博文中通过MDIO接口实现了PHY芯片的状态检测,验证其已处于1000M 全双工工作模式.在设计MAC逻辑之前,要先清楚MAC与PHY之间的接口以及以太网协议细节,这样才能保证网络的兼容性. ...

  2. lua os.date函数定义和示例

    os.date函数定义 原型:os.date ([format [, time]]) 解释:返回一个按format格式化日期.时间的字串或表. lua源码中os.date的注释如下: --- --- ...

  3. 记录Javascript的数据方法参考

    concat >>连接2个或更多数组,并返回结果 var arr1 = [1,2,3]; var arr2 = [-1,-2,-3]; console.log(arr1.concat(ar ...

  4. 是时候选择一款富文本编辑器了(wangEditor)

    需要一款富文本编辑器,当然不能自己造轮子.本来想使用cnblog也在用的TinyMCE,名气大,功能全.但是发现TinyMCE从4.0开始,不再支持直接下载.所以还是决定选用wangEditor.遗憾 ...

  5. Core官方DI剖析(1)--ServiceProvider类和ServiceCollection类

    前段时间看了蒋老师的Core文章,对于DI那一块感觉挺有意思,然后就看了一下Core官方DI的源码,这也算是第一个看得懂大部分源码的框架,虽然官方DI相对来说特别简单, 官方DI相对于其它框架(例如 ...

  6. ABP之session

    ABP提供了一个IAbpSession接口,可以在不使用ASPNET的session的情况下获取当前用户和租户.IAbpSession还被ABP中的其他结构(如设置和授权系统)完全集成和使用. 注入s ...

  7. 关于map的初级应用

    map实际采用了红黑树的实现,在此,我们先不讨论map的底层实现结构原理,先来看看map究竟是怎么用,以及我是怎么看待map的. 先上代码: #include <map> #include ...

  8. CSS3旋转缩放移动倾斜等效果——transform

    1.transform浏览器支持情况 也就是说目前不考虑老浏览器的话是不用加前缀的,感谢菜鸟教程:https://www.runoob.com/cssref/css3-pr-transform.htm ...

  9. Element类型和HTML元素获取

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  10. C语言博客作业03--函数

    1.本章学习总结 1.1 思维导图 1.2 本章学习体会及代码量学习体会 1.2.1 学习体会 这周最大的收获就是学习函数,并且通过对函数的封装来做成一个简单的小程序,这周做的最有意义的事情就是做了老 ...