- 论坛徽章:
- 0
|
本帖最后由 ohyeahbbs 于 2011-07-13 15:38 编辑
小弟跟着老师在弄一个HTTP代理系统;捣鼓了一个星期终于容易可以代理成功了,却发现html的页面只能打开一两个,然后用top查看Linux系统资源发现代理占据资源达到了七八十%。
哪位大虾帮忙看看,优化一下。。。
采用线程绑定文件描述字的方法。。。。
代码如下:- 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添加到内存中
- boost::threadpool::pool threadPool; //利用线程池创建线程并设线程大小为66
- /* 关闭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重点向为本地端口9997 */
- system("iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 9997");
- cout<<"iptables prerouting success"<<endl;
- /* 创立并监听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上监听连接 */
- 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);
- /* 循环接受TCP连接 */
- for( ; gIsRunning == 1 ; )
- //while(gIsRunning)
- {
- client = sizeof(cliaddr);
- connfd = (int*)malloc(sizeof(int));
- /* accept所返回的文件描述符是新的套接字描述符和原始套接字listenfd具有相同的套接字类型和地址簇
- * 传给accept的原始套接字没有关联到这个连接,而是继续保持可用状态并接受其他连接请求 */
- if((*connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &client))<0)
- {
-
- /*accetp()是慢系统调用,在信号产生时会中断其调用并将
- errno变量设置为EINTR,此时应重新调用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;
- /* 把accept返回的套接字描述符与线程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;
- /* 创建到服务器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的数据交换 */
- forwarddata(connfd, remotefd);
- }
- return 0;
- }
- int forwarddata(int connfd, int remotefd)
- {
- int maxfdp1;
- int ret, n;
- char buff[MAXLINE];
- fd_set rset; //分配一个状态描述符类型的变量
- struct timeval val;
- val.tv_sec = 10;
- val.tv_usec = 0;
- FD_ZERO(&rset); //将一个指定的fd_set变量的所有位设置为0.
- ret = 0;
-
- /* 循环地从客户端读,向服务端写;从服务器端读,向客户端写 */
- for( ; gIsRunning==1 ; )
- //printf("test3=%d\n", gIsRunning);
- //while(gIsRunning)
- {
- /* 调用FD_SET设置一个fd_set变量的指定位。添加描述符到描述符集合*/
- FD_SET(connfd, &rset);
- FD_SET(remotefd, &rset);
-
- /* 因为描述符编号从0开始,所以要在最大描述符编号值上加1 */
- maxfdp1 = max(connfd, remotefd) + 1;
-
- /* 返还值-1表示出错 */
- if((n = select(maxfdp1, &rset, NULL, NULL, &val))<0)
- {
- cout<<"Select serror!"<<endl;
- break;
- }
- /* 判断是否为超时返回 */
- if( n == 0 )
- continue;
- /* 从客户端读recv(client) */
- if(FD_ISSET(connfd, &rset)) //测试一指定位是否设置,检查FD集合中FD是否准备好
- {
- memset(buff, 0x00, sizeof(buff));
- ret = recv(connfd, buff, MAXLINE, 0);
- if(ret > 0)
- {
- cout<<"Client to server..."<<endl;
- /* 向服务器端写send(server) */
- ret = send(remotefd, buff, ret, 0);
- if(ret == -1)
- {
- cout<<"Send data to real server error"<<endl;
- break;
- }
- }
- /* 没读到数据关闭连接 */
- else if(ret == 0)
- {
- break;
- }
- /* 从客户端接受数据错误 */
- else
- {
- break;
- }
- }
- /* 从服务器端读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;
- /* 向客户端写send(client) */
- ret = send(connfd, buff, ret, 0);
- if(ret == -1)
- {
- cout<<"Send data to client error"<<endl;
- break;
- }
- }
- /* 没读到数据关闭连接 */
- else if(ret == 0)
- {
- break;
- }
- /* 从客户端接受数据错误 */
- else
- {
- break;
- }
- }
- }
- return 0;
- }
复制代码 |
|