Go的50度灰补充--http response只能读一次

问题 还是从代码开始吧 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 func fetch(url string) { tlsConfig := &tls.Config{ InsecureSkipVerify: true, } transport := &http.Transport{ TLSClientConfig: tlsConfig, } client := http.Client{Transport: transport} resp, err := client.Get(url) if err != nil { fmt.Println(err) <-time.After(300 * time.Second) go fetch(url) return } buf, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("fetchyh:", err) return } save(buf) //保存html到文件 defer resp.Body.Close() // http to doc doc, err := goquery.NewDocumentFromResponse(resp) if err != nil { fmt.Println(err, "http resp to doc failed") return } /* <div class="datanowin" id="myCont2"> */ datanowin := doc.Find("div.datanowin") fmt.Println("datanowin:", datanowin.Length()) tables := datanowin.Find("table") tablelen := tables.Length() fmt.Println("tablelen:", tablelen) for i := 0; i < tablelen; i++ { item := tables.Eq(i) tableDo(item) } fmt.Println(doc.Find(".table").Length()) } 调用上面的代码后,html网页上没有找到自己所需要的内容,上面的代码问题在哪里? 假想一下,一般有以下原因选项: ...

February 20, 2017

TCP连接下载文件失败,也许该看看这篇文章

体验一下标题党,现在自媒体横行,容我也放肆一回(多了我也不行,替自己码字能力捉急)! 另起一行,到此为止,进入正题 缘起 最近通过uc浏览器下载apk的时候,偶尔出现下载apk,下载了60%左右卡住,想到以前看到这篇文章:The curious case of slow downloads(PS:毕竟这个问题不是常出现,就算一次下载失败,反正可以重新下载,总能下载成功的) ...

February 16, 2017

互联网在农村-音乐

手机上网就是通过app获取服务,在农村里人们上网喜欢干些什么呢?先从喜欢听什么歌开始? 在家里时间有限,这次就写这么多,待以后回家再观察其他方面。这里仅仅是开一个小引子:农村互联网用户喜欢什么样内容? ...

February 4, 2017

互联网在农村-用户

上一篇从电和物理网络两个方面说明自己所看到的农村互联网基础设施情况。这一篇就看看在农村的互联网用户的一些情况。 根据对app使用情况分为以下几种情况: 基本不使用智能手机 需要引导使用智能手机 自主使用智能手机一些应用 自主使用智能手机大多数应用 基本不使用智能手机 代表人物:大伯父,大伯母 ...

February 3, 2017

互联网在农村-基础设施

说明 老家在安徽省安庆市的一个小山村里,作为一名互联网从业人员,这次回家特地花了一点心思来观察家乡的互联网应用情况。 这是第一篇,先看农村互联网基础设施情况,上网要有电,要有接入网络,所以下面内容分为两个方面: ...

February 2, 2017

不追求完美,追求进步

完美 完美是一个理想的状态,但在现实生活中很难达成。不同的人对完美有不同的理解: 无错误。从客观角度,完美代表一种没有错误、瑕疵和Bug的状态。所有要素都处于最佳状况,没有任何改进的空间。但在复杂系统中要达成这种完美几乎是不可能的。 ...

January 17, 2017

人生有哪些大坑

背景 人生不如意十有八九。生活处处有坑,避免不踩坑不可能,但是还是要努力防止踩大坑。 认知与心理 偏见、妄想等因素导致不能发现与尊重事实和规则 思维定势,错误地执念,拒绝改变,视野与格局打不开 想当然,盲目,盲从,懒惰,不能独立思考与验证 不知道什么是最重要的,没有明确的目标 不知道自己不知道,缺少敬畏 缺少长期心态与长远眼光,没有耐心,不能延迟满足 选择与环境 选择牺牲身体来赚钱 选错专业与行业 关键事件方面选错人来合作如结婚,创业等等 处于烂人的环境当中(如爱抱怨的工作同事,暗规则横行的工作氛围) 缺少对危险因素的洞察与风险控制(君子不立危墙之下) 行为与习惯 不思考,不学习,无进步 恶性循环(如赌博,混自己不喜欢的工作) 不自律,放纵自己 爱与别人比较 跟风与凑热闹 嫉妒 拖延并缺少执行力 只想不做,浅尝辄止,做事不到位 情绪不稳定,波动大,情绪冲动 重复犯相同的错误 拖延症

January 17, 2017

五个问题帮你找到你真正的想要的

问题 1. 你想要什么? 未来自我定义:明确你的未来自我是谁,这对于激发动力和方向至关重要。 2. 你有多想要它? 真正的渴望程度:探讨你对目标的渴望有多强烈,以及你是否愿意为之付出努力。 ...

January 11, 2017

从C语言epoll编程到go net实现分析

说明 go源码版本:1.7 go源码运行环境:Linux epoll在c语言编程示例 先看一下大家比较熟悉的epoll在c语言中应用,代码取自rtmpserver_demo中的文件rtmpepollsrv.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 int RtmpSessionHandle(int iFd, int iEvent, void *pContext) { int iRet; RTMP_SESSION *pSession = (RTMP_SESSION *)pContext; if(iEvent&EPOLLIN ) { if(0 == pSession->handshake) { iRet = RtmpSessionHandshake(pSession); if(0 != iRet) { RtmpSessionHandleFin(pSession); } } else { iRet = RtmpPktHandle(pSession); } } if(iEvent & (EPOLLERR |EPOLLHUP) ) { RtmpSessionHandleFin(pSession); } return iRet; } int ListenHandle(int iFd, int iEvent, void *pContext) { int iNewFd; int iRet = 0; struct sockaddr tmpAddr; memset(&tmpAddr, 0, sizeof(tmpAddr)); int iSocketSize = sizeof(tmpAddr); EPOLL_CTX *pCtx; RTMP_SESSION *pServer; if(iEvent|EPOLLIN) { iNewFd = accept(iFd, &tmpAddr, (socklen_t *)&iSocketSize); if(RTMP_EPOLLSRV_INVALIDFD < iNewFd) { pServer = (RTMP_SESSION *)malloc(sizeof(RTMP_SESSION)); if(NULL == pServer) { return -1; } pServer->handshake = 0; pCtx = (EPOLL_CTX *)malloc(sizeof(EPOLL_CTX)); if(NULL == pCtx) { free(pServer); return -1; } pServer->socket = iNewFd; pCtx->iFd = iNewFd; pCtx->pContext = pServer; pCtx->pfHandle = RtmpSessionHandle; /* 加入epoll */ iRet = epoll_op(g_iEpollFd, EPOLL_CTL_ADD, iNewFd, EPOLLIN|EPOLLERR|EPOLLHUP, pCtx); } else { printf("accept errno:%s",strerror(errno)); } } return iRet; } int epoll_op(int iEpollFd, int iOp, int iFd, int iEvent, EPOLL_CTX *pCtx) { int iRet; struct epoll_event ev; ev.events = iEvent; ev.data.ptr = pCtx; iRet = epoll_ctl(iEpollFd, iOp, iFd, &ev); return iRet; } int epoll_loop(int iEpollFd) { int iNum; struct epoll_event astEpEvent[RTMP_EPOLLSRV_MAXEPOLL]; int i; EpollCallBack_PF pfHandle; EPOLL_CTX *pCtx; for( ; ;) { iNum= epoll_wait(iEpollFd, &astEpEvent[0], RTMP_EPOLLSRV_MAXEPOLL, -1); if( 0 < iNum) { for(i = 0; i < iNum; i++) { pCtx = (EPOLL_CTX *)astEpEvent[i].data.ptr; pfHandle = pCtx->pfHandle; (void)pfHandle(pCtx->iFd, astEpEvent[i].events, pCtx->pContext); } } else { printf("epoll_wait failed\r\n"); } } return 0; } int main(void) { int iFd; struct sockaddr_in addr; printf("in the main\r\n"); /* 初始化epoll */ g_iEpollFd = epoll_create(200); if(RTMP_EPOLLSRV_INVALIDFD >= g_iEpollFd) { printf("create epoll failed\r\n"); return -1; } /* 创建侦听端口 */ iFd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(RTMP_EPOLLSRV_INVALIDFD >= iFd) { printf("create listen socket failed\r\n"); return -1; } addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr(g_cRtmpSrvAddr); addr.sin_port = htons(g_usRtmpSrvPort); if( 0 != bind(iFd, (struct sockaddr *) &addr, sizeof(struct sockaddr_in))) { return -1; } if( 0 != listen(iFd, 200)) { return -1; } EPOLL_CTX *pEpollCtx = (EPOLL_CTX *)malloc(sizeof(EPOLL_CTX)); if(NULL == pEpollCtx) { return -1; } pEpollCtx->iFd = iFd; pEpollCtx->pfHandle = ListenHandle; pEpollCtx->pContext = NULL; /* 加入epoll */ if(0 != epoll_op(g_iEpollFd, EPOLL_CTL_ADD, iFd, EPOLLIN|EPOLLERR|EPOLLHUP, pEpollCtx)) { return -1; } g_iListenFd = iFd; epoll_loop(g_iEpollFd); return 0; } 功能 上述代码代码主要通过epoll实现一个最基本的网络服务器(侦听一个端口,处理这个端口上连接) ...

September 10, 2016

Go channel 编程篇

本篇以ChanBroker版本迭代过程,总结常见Channel编程问题 简介 ChanBroker设计主要参考Kafka模型,主要提供进程内goroutine之间通信,实现以下功能: 支持多个Publisher发布内容 支持Subscriber注册与去注册订阅 发布内容可以是任何形式 ChanBroker根据订阅情况完成内容推送 版本1 具体代码如下: ...

August 20, 2016