- 論壇徽章:
- 0
|
本帖最后由 ohyeahbbs 于 2011-07-13 15:38 編輯
小弟跟著老師在弄一個(gè)HTTP代理系統(tǒng);搗鼓了一個(gè)星期終于容易可以代理成功了,卻發(fā)現(xiàn)html的頁(yè)面只能打開(kāi)一兩個(gè),然后用top查看Linux系統(tǒng)資源發(fā)現(xiàn)代理占據(jù)資源達(dá)到了七八十%。
哪位大蝦幫忙看看,優(yōu)化一下。。。
采用線程綁定文件描述字的方法。。。。
代碼如下:- 1,proxy:
- #include "threadpool/include/threadpool.hpp"
- #include<iostream>
- #include<string.h>// char *strerror(int errnum);errnum(通常就是errno)
- #include<sys/socket.h>
- #include<errno.h>
- #include<arpa/inet.h>
- #include<unistd.h>
- #include<signal.h>
- #include<stdlib.h>
- #define BACKLOG 128
- using namespace std;
- int httpproxy(void *fd);
- int listenfd; //文件(套接字socket)描述符
- volatile bool gIsRunning; //volatile表示把gIsRunning添加到內(nèi)存中
- boost::threadpool::pool threadPool; //利用線程池創(chuàng)建線程并設(shè)線程大小為66
- /* 關(guān)閉proxy */
- void sysclosed(int signal)
- {
- gIsRunning = false;
- cout<<"Waiting for proxy threads..."<<endl;
- threadPool.wait();
- close(listenfd);
- cout<<"proxy is closed"<<endl;
- }
- int main()
- {
- int *connfd; //accept所返回的文件(套接字)描述符
- socklen_t client;
- struct sockaddr_in cliaddr,servaddr;
- gIsRunning = true;
- system("service iptables restart");
- sleep(3);
- /* 端口80重點(diǎn)向?yàn)楸镜囟丝?997 */
- system("iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 9997");
- cout<<"iptables prerouting success"<<endl;
- /* 創(chuàng)立并監(jiān)聽(tīng)socket */
- cout<<"Start the server..."<<endl;
- if((listenfd = socket(AF_INET, SOCK_STREAM, 0))<0 )
- {
- cout<<"Creat the socket error!"<<endl;
- exit(-1);
- }
- else cout<<"Creat the socket success"<<endl;
-
- memset(&servaddr,0,sizeof(servaddr));
- servaddr.sin_addr.s_addr = INADDR_ANY;
- servaddr.sin_family = AF_INET;
- servaddr.sin_port = htons(9997);
-
- /* 綁定任意IP及特定端口 */
- if(bind(listenfd,(struct sockaddr *)&servaddr, sizeof(servaddr)) <0 )
- {
- cout<<"Bind error"<<strerror(errno)<<endl;
- }
- else cout<<"Bind the port success"<<endl;
- /* 在socket上監(jiān)聽(tīng)連接 */
- if(listen(listenfd, BACKLOG) != 0 )
- {
- cout<<"Listen error"<<strerror(errno)<<endl;
- }
- else cout<<"Listen is running..."<<endl;
-
- threadPool.size_controller().resize(66);
-
- signal(SIGINT, sysclosed);
- /* 循環(huán)接受TCP連接 */
- for( ; gIsRunning == 1 ; )
- //while(gIsRunning)
- {
- client = sizeof(cliaddr);
- connfd = (int*)malloc(sizeof(int));
- /* accept所返回的文件描述符是新的套接字描述符和原始套接字listenfd具有相同的套接字類(lèi)型和地址簇
- * 傳給accept的原始套接字沒(méi)有關(guān)聯(lián)到這個(gè)連接,而是繼續(xù)保持可用狀態(tài)并接受其他連接請(qǐng)求 */
- if((*connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &client))<0)
- {
-
- /*accetp()是慢系統(tǒng)調(diào)用,在信號(hào)產(chǎn)生時(shí)會(huì)中斷其調(diào)用并將
- errno變量設(shè)置為EINTR,此時(shí)應(yīng)重新調(diào)用accept()。*/
- if( errno == EINTR )
- {
- cout<<"Accept error (EINTR):"<<strerror(errno)<<endl;
- continue;
- }
- else
- {
- cout<<"Accept error:"<<strerror(errno)<<endl;
- exit(1);
- }
- }
- else cout<<"Start the http connect!"<<endl;
- /* 把a(bǔ)ccept返回的套接字描述符與線程httpproxy綁定 */
- threadPool.schedule(boost::bind(&httpproxy, (void *)connfd));
- }
- }
- 2,forwarddata:
- #include<sys/select.h>
- #include<iostream>
- #include<string.h>
- #include<sys/socket.h>
- #include<errno.h>
- #include<arpa/inet.h>
- #include <linux/kernel.h>
- #include <linux/netfilter_ipv4.h>
- #define MAXLINE 4096
- /* 聲明外部變量gIsRunning */
- extern volatile bool gIsRunning;
- using namespace std;
- int forwarddata(int connfd, int remotefd);
- int max(int a, int b)
- {
- return a>b?a:b;
- }
- int httpproxy(void *fd)
- {
- int connfd,remotefd,port;
- socklen_t len;
- char buff[100+1];
- const char * ipaddr;
- struct sockaddr_in remoteserv;
- struct sockaddr_in dest;
- connfd = *((int *)fd);
- free(fd);
- /* 獲取連接的目的IP和PORT */
- memset(buff, 0x00, sizeof(buff));
- len =sizeof(dest);
- memset(&dest, 0, len);
- if(getsockopt(connfd, SOL_IP, SO_ORIGINAL_DST, &dest, &len)< 0)
- {
- cout<<"Getsockopt error:"<<strerror(errno)<<endl;
- return -1;
- }
- else
- {
- ipaddr = inet_ntop(AF_INET, &dest.sin_addr, buff, sizeof(buff));
- port = ntohs(dest.sin_port);
- cout<<"Iptables transparent destination:"<<ipaddr<<":"<<port<<endl;
- }
- cout<<"buff="<<buff<<" "<<"port="<<port<<endl;
- /* 創(chuàng)建到服務(wù)器socket */
- if((remotefd = socket(AF_INET, SOCK_STREAM, 0))<0)
- {
- cout<<"Remote error:"<<strerror(errno)<<endl;
- return -1;
- }
- memset(&remoteserv, 0x00, sizeof(remoteserv));
- remoteserv.sin_family = AF_INET;
- remoteserv.sin_port = htons(ntohs(dest.sin_port));
- inet_pton(AF_INET, buff, &remoteserv.sin_addr);
-
- /* 按目的地址建立連接 */
- if(connect(remotefd, (struct sockaddr *)&remoteserv, sizeof(remoteserv))<0)
- {
- cout<<"Connect remote server error:"<<strerror(errno)<<endl;
- //goto STOP_THREAD;
- return -1;
- }
- else
- {
- /* 處理connfd和remotefd的數(shù)據(jù)交換 */
- forwarddata(connfd, remotefd);
- }
- return 0;
- }
- int forwarddata(int connfd, int remotefd)
- {
- int maxfdp1;
- int ret, n;
- char buff[MAXLINE];
- fd_set rset; //分配一個(gè)狀態(tài)描述符類(lèi)型的變量
- struct timeval val;
- val.tv_sec = 10;
- val.tv_usec = 0;
- FD_ZERO(&rset); //將一個(gè)指定的fd_set變量的所有位設(shè)置為0.
- ret = 0;
-
- /* 循環(huán)地從客戶端讀,向服務(wù)端寫(xiě);從服務(wù)器端讀,向客戶端寫(xiě) */
- for( ; gIsRunning==1 ; )
- //printf("test3=%d\n", gIsRunning);
- //while(gIsRunning)
- {
- /* 調(diào)用FD_SET設(shè)置一個(gè)fd_set變量的指定位。添加描述符到描述符集合*/
- FD_SET(connfd, &rset);
- FD_SET(remotefd, &rset);
-
- /* 因?yàn)槊枋龇幪?hào)從0開(kāi)始,所以要在最大描述符編號(hào)值上加1 */
- maxfdp1 = max(connfd, remotefd) + 1;
-
- /* 返還值-1表示出錯(cuò) */
- if((n = select(maxfdp1, &rset, NULL, NULL, &val))<0)
- {
- cout<<"Select serror!"<<endl;
- break;
- }
- /* 判斷是否為超時(shí)返回 */
- if( n == 0 )
- continue;
- /* 從客戶端讀recv(client) */
- if(FD_ISSET(connfd, &rset)) //測(cè)試一指定位是否設(shè)置,檢查FD集合中FD是否準(zhǔn)備好
- {
- memset(buff, 0x00, sizeof(buff));
- ret = recv(connfd, buff, MAXLINE, 0);
- if(ret > 0)
- {
- cout<<"Client to server..."<<endl;
- /* 向服務(wù)器端寫(xiě)send(server) */
- ret = send(remotefd, buff, ret, 0);
- if(ret == -1)
- {
- cout<<"Send data to real server error"<<endl;
- break;
- }
- }
- /* 沒(méi)讀到數(shù)據(jù)關(guān)閉連接 */
- else if(ret == 0)
- {
- break;
- }
- /* 從客戶端接受數(shù)據(jù)錯(cuò)誤 */
- else
- {
- break;
- }
- }
- /* 從服務(wù)器端讀recv(server) */
- if(FD_ISSET(remotefd, &rset))
- {
- memset(buff, 0x00, sizeof(buff));
- ret = recv(remotefd, buff, MAXLINE, 0);
- if(ret > 0)
- {
- cout<<"Remote to client..."<<endl;
- /* 向客戶端寫(xiě)send(client) */
- ret = send(connfd, buff, ret, 0);
- if(ret == -1)
- {
- cout<<"Send data to client error"<<endl;
- break;
- }
- }
- /* 沒(méi)讀到數(shù)據(jù)關(guān)閉連接 */
- else if(ret == 0)
- {
- break;
- }
- /* 從客戶端接受數(shù)據(jù)錯(cuò)誤 */
- else
- {
- break;
- }
- }
- }
- return 0;
- }
復(fù)制代碼 |
|