今天实验了下 异步连接 是不是可行 答案是肯定的 顺便看了下 epoll 的使用 。。和 windows 上的 IOCP 不一样的时候 一旦数据可读了 那么你就要一直 read 到不可读为止 ,。。。
#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> #include <string.h> #include <netinet/in.h> #include <arpa/nameser.h> #include <resolv.h> #include <stdlib.h> #include <sys/stat.h> #include <sys/fcntl.h> #include <sys/epoll.h> #include <pthread.h> #include <sys/ioctl.h> char *msg = "GET / http/1.1\r\n\r\n"; uint32_t DNS(const char *hostname) { uint32_t ret = -1; u_char answer[256]; int len = 0; ns_msg msg; ns_rr rr; res_init(); if ((len = res_query(hostname, ns_c_in, ns_t_a, &answer[0], sizeof(answer)))) { int j ; ns_initparse (answer, len, &msg); len = ns_msg_count (msg, ns_s_an); for (j = 0; j < len; j++) { //char dispbuf[256]; ns_parserr (&msg, ns_s_an, j, &rr); //ns_sprintrr (&msg, &rr, NULL, NULL, dispbuf, sizeof (dispbuf)); //printf ("%s\n", dispbuf); if (ns_t_a == ns_rr_type(rr)) { struct in_addr in; printf("name:%s\n", ns_rr_name(rr)); in.s_addr = htonl(ns_get32(ns_rr_rdata(rr))); printf("ip:%s\n", inet_ntoa(in)); ret = in.s_addr; } } } return ret; } int add2epoll(int fd, int epoll_fd) { struct epoll_event ev; ev.data.fd = fd; //ev.data.ptr = "i am sincoder";// ev.events = EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLET ; return epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev); } int del_from_epoll(int fd, int epoll_fd) { return epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, NULL); } static int isconnect = 1; int main(int argc, char **argv) { int epoll_fd; struct sockaddr_in addr; int sock = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK , IPPROTO_TCP); if (-1 == sock) { fprintf(stderr, "create socket failed \n" ); return -1; } epoll_fd = epoll_create(100); if (epoll_fd == -1) { close(sock); perror("epoll_create:"); return -1; } if (-1 != add2epoll(sock, epoll_fd)) { addr.sin_addr.s_addr = DNS("www.baidu.com"); addr.sin_port = htons(80); addr.sin_family = AF_INET; if (-1 != connect(sock, (const struct sockaddr *)&addr, sizeof(struct sockaddr)) || errno == EINPROGRESS) { int nr_events; struct epoll_event *events = NULL; events = malloc (sizeof (struct epoll_event) * 64); if (!events) { perror ("malloc():"); return 0; } while (1) { int i = 0; printf("enter wait !\n"); nr_events = epoll_wait (epoll_fd, events, 64, -1); printf("out wait %d\n", nr_events); if (nr_events < 0) { perror("epoll_wait"); } for (i = 0; i < nr_events; i++) { if (events[i].events & EPOLLERR) { printf("EPOLLERR "); printf("remote close ?? \n"); if (-1 == del_from_epoll(events[i].data.fd, epoll_fd)) { perror("epoll_ctrl():"); } close(events[i].data.fd); events[i].events &= ~EPOLLERR; } if (events[i].events & EPOLLIN) { int len = 0; char buff[1024]; printf("EPOLLIN "); while (1) { len = read(events[i].data.fd, buff, 1000); if (len > 0) { buff[len] = 0; printf("recv %d bytes : %s \n", len, buff ); } else { if(errno == EAGAIN || errno == EWOULDBLOCK) break; perror("recv():"); printf("socket close ???\n"); break; } } events[i].events &= ~EPOLLIN; } if (events[i].events & EPOLLOUT) { printf("EPOLLOUT "); if (isconnect) { write(sock, msg, strlen(msg)); isconnect = 0; } events[i].events &= ~EPOLLOUT; } if (0 != events[i].events) { printf("there is a unknown msg : %d \n", events[i].events); } } } } else { printf("connect failed %d %s\n", errno, strerror(errno)); } } else perror("epoll():"); close(sock); close(epoll_fd); return 0; }