LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 631|回复: 0

为什么浏览器用我的proxy访问网站老是喜欢创建新连接阿?

[复制链接]
发表于 2007-2-1 00:18:47 | 显示全部楼层 |阅读模式
我都在对server的request里和 对client的response里添加了Connection: Keep-Alive,但是浏览器仍然请求一个页面里的图片和其他资源,都重新和我的proxy创建新的连接来请求,导致proxy对网站的资源也不断的创建新的连接来请求资源,而大部分网站发现这样浪费资源的创建新连接请求资源的方式很快就拒绝连接;怎么解决这个问题呢?
下面是proxy的代码

kitty.c

  1. #include <unistd.h>
  2. #include <sys/socket.h>
  3. #include <arpa/inet.h>
  4. #include <netinet/in.h>
  5. #include <netdb.h>
  6. #include <string.h>
  7. #include <stdio.h>
  8. #include <errno.h>
  9. #include <stdlib.h>
  10. #include <sys/stat.h>
  11. #include <sys/mman.h>
  12. #include <sys/types.h>
  13. #include <fcntl.h>
  14. #include <sys/wait.h>
  15. #include <signal.h>
  16. #include <sys/select.h>
  17. #include "unp.h"

  18. typedef enum {RESPONSE,REQUEST} msg_t;
  19. #define MAXBUF 4096
  20. #define MAXURI 400
  21. #define MIN(a,b) ((a) > (b)?(b):(a))

  22. void process(int fd,int id);
  23. void clienterror(int fd,char *errnum,char *shortmsg,char *longmsg);
  24. ssize_t extract_host(const char *uri,char *buf,int len);
  25. ssize_t extract_fieldname(const char *line,char *buf,int len);
  26. ssize_t extract_fieldvalue(const char *line,char *buf,int len);
  27. ssize_t extract_field(int id,int sockfd,char *headerline,char *fieldname_ptr,int namelen,char *fieldvalue_ptr,int valuelen,msg_t type);
  28. int read_first_headerline(int id,int sockfd,char *headerline,int len,msg_t type);

  29. void debug(const char *fmt,...) {
  30.         va_list ap;
  31.         va_start(ap,fmt);
  32.         vprintf(fmt,ap);
  33.         va_end(ap);
  34. }

  35. int equals(char *c1,char *c2) {
  36.         return strncasecmp(c1,c2,strlen(c2)) == 0;
  37. }

  38. void sigchld_handler(int sig) {
  39.         while(waitpid(-1,0,WNOHANG) > 0);
  40.         return;
  41. }

  42. int id = 0;
  43. int main(int argc,char **argv) {
  44.         int listenfd,connfd,port;
  45.         struct sockaddr_in cliaddr;
  46.         socklen_t addrlen = sizeof(struct sockaddr_in);
  47.         char straddr[50];

  48.         if(argc != 2) {
  49.                 fprintf(stderr,"usage:%s <port>\n",argv[0]);
  50.                 exit(1);
  51.         }

  52.         port = atoi(argv[1]);
  53.         listenfd = open_listenfd(port);
  54.         signal(SIGCHLD,sigchld_handler);

  55.         while(1) {
  56.                 connfd = accept(listenfd,&cliaddr,&addrlen);
  57.                 inet_ntop(AF_INET,&cliaddr.sin_addr.s_addr,straddr,sizeof(straddr));
  58.                 debug("accept remote addr:%s, port:%d, connfd:%d\n",straddr,ntohs(cliaddr.sin_port),connfd);
  59.                 ++id;
  60.                 if(fork() == 0) {
  61.                         //child process
  62.                         close(listenfd);
  63.                         process(connfd,id);
  64.                         close(connfd);
  65.                         exit(0);
  66.                 }
  67.                 close(connfd);
  68.         }
  69. }

  70. void process(int clifd,int id) {
  71.         /* buffer for storing http requests that received from client or http responses that received from server */
  72.         char headerline[MAXLINE];

  73.         /* buffer for being pointed by fieldname_ptr and fieldvalue_ptr or storing data that received from server */
  74.         char databuf[MAXBUF];

  75.         /* buffer for storing http requests that will send to server or will send to client */
  76.         char sendbuf[MAXBUF];

  77.         char uri[MAXURI],method[10],version[10],host[MAXURI],statuscode[3],reason_phrase[20];

  78.         /*the socket descriptor that connected to server */
  79.         int servfd = -1;
  80.         ssize_t size;
  81.         char *ptr = sendbuf;
  82.         int left = MAXBUF;

  83.         char *fieldname_ptr = databuf,*fieldvalue_ptr = databuf + (MAXBUF / 2);

  84.         int client_keep_alive = 1;
  85.         int client_alive_time = 10;/* 10 seconds is default */
  86.         int httprequest_count = 0;/* the count that client use the connection to send httprequests to kitty proxy*/
  87.         int server_keep_alive = 1;

  88.         fd_set rset;
  89.         struct timeval timeout;

  90.         FD_ZERO(&rset);
  91.         while(httprequest_count == 0 || client_keep_alive) {
  92.                 FD_SET(clifd,&rset);

  93.                 timeout.tv_sec = client_alive_time;
  94.                 timeout.tv_usec = 0;

  95.                 //debug("%d: before select\n",clifd);
  96.                 size = select(clifd + 1,&rset,NULL,NULL,&timeout);
  97.                 //debug("%d: the returned value from select method is %d\n",clifd,size);
  98.                 if(size == 0) {/* timeout */
  99.                         break;
  100.                 } else if(size == -1) { /* error */
  101.                         debug("select error\n");
  102.                         break;
  103.                 }

  104.                 size = read_first_headerline(id,clifd,headerline,MAXLINE,REQUEST);
  105.                 if(size < 0) {
  106.                         goto clean;
  107.                 }

  108.                 httprequest_count++;

  109.                 //TODO:how to do if buffer overflow?
  110.                 sscanf(headerline,"%s %s %s\r\n",method,uri,version);
  111.                 debug("\n%d: from client:\n",id);
  112.                 debug("%d: %s %s %s\n",id,method,uri,version);
  113.                 if(equals(method,"GET")) {
  114.                         size = extract_host(uri,host,MAXLINE);
  115.                         if(size < 0) {
  116.                                 clienterror(clifd,"400","Bad Request","Kitty can not extract host from request line");
  117.                                 return;
  118.                         }

  119.                         /* appending the Request-Line that received from client to sendbuf*/
  120.                         size = snprintf(ptr,left,headerline);
  121.                         ptr += size;
  122.                         left -= size;

  123.                         while(1) {
  124.                                 size = extract_field(id,clifd,headerline,fieldname_ptr,MAXLINE / 2,fieldvalue_ptr,MAXLINE / 2,REQUEST);
  125.                                 if(size == 0) {
  126.                                         break;
  127.                                 } else if(size < 0) {
  128.                                         goto clean;
  129.                                 }

  130.                                 debug("%d: %s: %s\n",id,fieldname_ptr,fieldvalue_ptr);

  131.                                 if(equals(fieldname_ptr,"Proxy-Connection") || equals(fieldname_ptr,"Connection")) {
  132.                                         if(equals(fieldvalue_ptr,"Keep-Alive")) {
  133.                                                 client_keep_alive = 1;
  134.                                         } else {
  135.                                                 client_keep_alive = 0;
  136.                                         }
  137.                                         continue;
  138.                                 } else if(equals(fieldname_ptr,"Keep-Alive")) {
  139. //                                        client_alive_time = atoi(fieldvalue_ptr);
  140.                                         continue;
  141.                                 } else if(equals(fieldname_ptr,"Host")) {}
  142.                                 else if(equals(fieldname_ptr,"Cookie")) {}
  143.                                 else if(equals(fieldname_ptr,"Pragma")) {}
  144.                                 else if(equals(fieldname_ptr,"Cache-Control")) {}
  145.                                 else if(equals(fieldname_ptr,"User-Agent")) {}
  146.                                 else if(equals(fieldname_ptr,"Accept-Language")) {}
  147.                                 else if(equals(fieldname_ptr,"Accept-Encoding")) {}
  148.                                 else if(equals(fieldname_ptr,"Accept-Charset")) {}
  149.                                 else if(equals(fieldname_ptr,"Accept")) {}

  150.                                 size = snprintf(ptr,left,headerline);
  151.                                 ptr += size;
  152.                                 left -= size;
  153.                         }

  154.                 } else {/* currently only support GET */
  155.                         clienterror(clifd,"501","Not Implemented","Kitty does not implement this method");
  156.                         goto clean;
  157.                 }
  158.                
  159.                 //tell server keep connection alive
  160.                 size = snprintf(ptr,left,"Connection: Keep-Alive\r\n");
  161.                 ptr += size;
  162.                 left -= size;

  163.                 /* mark the end of http message headers */
  164.                 snprintf(ptr,left,"\r\n");
  165. //debug("\nsend to server:\n%s\n",sendbuf);

  166.                 /* now kitty proxy try to connect to the server */
  167.                 if(servfd == -1 || !server_keep_alive) {
  168.                         if(httprequest_count > 1) {
  169.                                 debug("%d: disconnect to server\n",id);
  170.                                 close(servfd);
  171.                         }
  172.                         debug("%d: connect to %s\n",id,host);
  173.                         servfd = tcp_connect(host,80);
  174.                         if(servfd < 0) {
  175.                                 clienterror(clifd,"504","Gateway Timeout","Kitty can not connect to the server");
  176.                                 goto clean;
  177.                         }
  178.                 }
  179.                 /* send http request headers to server */
  180.                 size = writen(servfd, sendbuf, strlen(sendbuf));
  181.                 if(size < 0) {
  182.                         clienterror(clifd,"500","Internal Server Error","Kitty send request error");
  183.                         goto clean;
  184.                 }

  185.                 ptr = sendbuf;
  186.                 left = MAXBUF;

  187.                 //debug("%d: from server:\n",id);
  188.                 /* read response status line from server */
  189.                 size = read_first_headerline(id,servfd,headerline,MAXLINE,RESPONSE);
  190.                 if(size < 0) {
  191.                         goto clean;
  192.                 }

  193.                 sscanf("%s %s %s",version,statuscode,reason_phrase);
  194.                 //debug("%d: %s %s %s\n",id,version,statuscode,reason_phrase);
  195.                 size = snprintf(ptr,left,headerline);
  196.                 ptr += size;
  197.                 left -= size;

  198.                 while(1) {
  199.                         size = extract_field(id,servfd,headerline,fieldname_ptr,MAXLINE / 2,fieldvalue_ptr,MAXLINE / 2,RESPONSE);
  200.                         if(size == 0) {
  201.                                 break;
  202.                         } else if(size < 0) {
  203.                                 goto clean;
  204.                         }
  205.                         //debug("%d: response:%s: %s\n",id,fieldname_ptr,fieldvalue_ptr);

  206.                         if(equals(fieldname_ptr,"Connection")) {
  207.                                 if(equals(fieldvalue_ptr,"Keep-Alive")) {
  208.                                         server_keep_alive = 1;
  209.                                 } else {
  210.                                         server_keep_alive = 0;
  211.                                 }
  212.                                 debug("%d: server keep alive : %d\n",id,server_keep_alive);
  213.                                 continue;
  214.                         } else if(equals(fieldname_ptr,"Host")) {}
  215.                         else if(equals(fieldname_ptr,"Cookie")) {}
  216.                         else if(equals(fieldname_ptr,"Pragma")) {}
  217.                         else if(equals(fieldname_ptr,"Cache-Control")) {}

  218.                         size = snprintf(ptr,left,headerline);
  219.                         ptr += size;
  220.                         left -= size;
  221.                 }
  222.                
  223.                 //tell client keep connection alive
  224.                 size = snprintf(ptr,left,"Connection: Keep-Alive\r\n");
  225.                 ptr += size;
  226.                 left -= size;

  227.                 snprintf(ptr,left,"\r\n");
  228.                 /* write http response headers to client */
  229.                 debug("%d: to client:\n%s",id,sendbuf);
  230.                 size = writen(clifd, sendbuf, strlen(sendbuf));
  231.                 if(size < 0) {
  232.                         debug("an socket error happened while write to client");
  233.                         goto clean;
  234.                 }

  235.                 /* write response entity to client */
  236.                 debug("%d: write entity to client...\n",id);
  237.                 while(1) {
  238.                         /* read from server */
  239.                         size = read(servfd,databuf,sizeof(databuf));
  240.                         if(size < 0) {
  241.                                 debug("an error happend while read from server:%s\n",strerror(errno));
  242.                                 //error
  243.                                 goto clean;
  244.                         } else if(size > 0) {
  245.                                 /* write to client */
  246.                                 size = writen(clifd,databuf,size);
  247.                                 if(size < 0) {
  248.                                         debug("a error happend while write to client:%s\n",strerror(errno));
  249.                                         goto clean;
  250.                                 }
  251.                         } else {
  252.                                 debug("%d: finished transfer\n",id);
  253.                                 break;
  254.                         }
  255.                 }
  256.         }
  257. clean:
  258.         debug("%d: http request count = %d\n",id,httprequest_count);
  259.         if(servfd != -1) {
  260.                 close(servfd);
  261.         }
  262. }

  263. void clienterror(int fd,char *errnum,char *shortmsg,char *longmsg) {
  264.         char buf[MAXLINE]={0},body[MAXBUF]={0};

  265.         debug("%d: an error occured,error num:%s,longmsg:%s\n",fd,errnum,longmsg);
  266. //        int len = strlen(longmsg);
  267. //        int i;
  268. //        printf("len:%d\n",len);
  269. //        for(i = 0;i < len;i++){
  270. //                printf("%d",*(longmsg + i));
  271. //        }
  272. //        printf("\n\n");
  273.         //build the HTTP response body
  274.         sprintf(body,"<html><title>Error</title>\n");
  275.         sprintf(body,"%s<body bgcolor='ffffff'>\n",body);
  276.         sprintf(body,"%s%s: %s\n",body,errnum,shortmsg);
  277.         sprintf(body,"%s<p>%s\n",body,longmsg);
  278.         sprintf(body,"%s<hr><em>Kitty Proxy</em>\n",body);

  279.         sprintf(buf,"HTTP/1.1 %s %s\r\n",errnum,shortmsg);
  280.         writen(fd,buf,strlen(buf));
  281.         sprintf(buf,"Content-type:text/html\r\n");
  282.         writen(fd,buf,strlen(buf));
  283.         sprintf(buf,"Content-length:%d\r\n\r\n",strlen(body));
  284.         writen(fd,buf,strlen(buf));
  285.         writen(fd,body,strlen(body));
  286. }

  287. /*
  288. * if it is not a absoluteURI or is bad absoluteURI then return -1;
  289. * if the given buffer is not big enough to store host then return -2;
  290. * if done successfully then return the size of host;
  291. */
  292. ssize_t extract_host(const char *uri,char *buf,int len) {
  293.         char *s, *e;
  294.         int host_len;

  295.         if(strncasecmp(uri,"http://",strlen("http://")) == 0) {/* absolute uri */
  296.                 s = uri + strlen("http://");
  297.                 e = strchr(s,'/');
  298.                 if(!e) {
  299.                         return -1;
  300.                 }

  301.                 host_len = e - s;

  302.                 if(len < host_len + 1) {
  303.                         return -2;
  304.                 }

  305.                 strncpy(buf,s,host_len);
  306.                 *(buf + host_len) = 0;
  307.                 return host_len;
  308.         }
  309.         return -1;
  310. }

  311. /*
  312. * if the request-header field is bad then return -1;
  313. * if the given buffer is not big enough to store field name then return -2;
  314. * if done successfully then return the size of field name;
  315. */
  316. ssize_t extract_fieldname(const char *line,char *buf,int len) {
  317.         char *p = line;
  318.         int fieldname_len;

  319.         while(*p != ':' && *p != 0 )
  320.                 p++;

  321.         if(*p == 0) {
  322.                 return -1;
  323.         } else {
  324.                 //TODO:should I remove all heading space and trailing space before calculate fieldname length?
  325.                 fieldname_len = p - line;
  326.                 if(len < fieldname_len + 1) {
  327.                         return -2;
  328.                 }
  329.         }

  330.         strncpy(buf,line,fieldname_len);
  331.         *(buf + fieldname_len) = 0;
  332.         return fieldname_len;
  333. }

  334. /*
  335. * if the request-header field is bad then return -1;
  336. * if the given buffer is not big enough to store field value then return -2;
  337. * if done successfully then return the size of field value;
  338. */
  339. ssize_t extract_fieldvalue(const char *line,char *buf,int len) {
  340.         char *p = strchr(line,':');
  341.         int fieldvalue_len;

  342.         if(!p) {
  343.                 return -1;
  344.         }

  345.         p++;
  346.         while(*p == ' ')
  347.                 p++;

  348.         fieldvalue_len = strlen(p) - 2;/* exclude last CRLF */

  349.         if(len < fieldvalue_len + 1) {
  350.                 return -2;
  351.         }
  352.         strncpy(buf,p,fieldvalue_len);
  353.         *(buf + fieldvalue_len) = 0;
  354.         return fieldvalue_len;
  355. }

  356. /*
  357. * return -2 when read error
  358. * return -1 when the request is bad
  359. * return 0 when encounter CRLF
  360. * return 1 if anything is OK
  361. */
  362. ssize_t extract_field(int id,int sockfd,char *headerline,char *fieldname_ptr,int namelen,char *fieldvalue_ptr,int valuelen,msg_t type) {
  363.         int size = readline(sockfd,headerline,MAXLINE);
  364.         char *s = (type == REQUEST) ? "request":"response";
  365.         if(size == 0) {/* encounter EOF */
  366.                 debug("%d: readline encounter EOF when extracting field from %s\n",id,s);
  367.                 return -2;
  368.         } else if(size == -1) { /* error */
  369.                 debug("%d: readline error when extracting field from %s : %s\n",id,s,strerror(errno));
  370.                 return -2;
  371.         }

  372.         if(equals(headerline,"\r\n")) {
  373.                 debug("%d: reach end in %s\n",id,s);
  374.                 return 0;
  375.         }

  376.         size = extract_fieldname(headerline, fieldname_ptr, namelen);
  377.         if(size < 0) {
  378.                 if(type == REQUEST) {
  379.                         clienterror(sockfd,"400","Bad Request",headerline);
  380.                 } else {
  381.                         clienterror(sockfd,"500","Internal Server Error","");
  382.                 }
  383.                 return -1;
  384.         }
  385.         size = extract_fieldvalue(headerline, fieldvalue_ptr, valuelen);
  386.         if(size < 0) {
  387.                 if(type == REQUEST) {
  388.                         clienterror(sockfd,"400","Bad Request",headerline);
  389.                 } else {
  390.                         clienterror(sockfd,"500","Internal Server Error","");
  391.                 }
  392.                 return -1;
  393.         }
  394.         return 1;
  395. }

  396. /*
  397.         * RFC HTTP/1.1:
  398.         * In the interest of robustness, servers SHOULD ignore any empty line(s) received
  399.         * where a Request-Line is expected. In other words, if the server is reading the
  400.         * protocol stream at the beginning of a message and receives a CRLF first, it
  401.         * should ignore the CRLF.
  402.         *
  403.         * return -1 if read error otherwise return 0;  
  404.    */
  405. int read_first_headerline(int id,int sockfd,char *headerline,int len,msg_t type) {
  406.         int size;
  407.         char *s = (type == REQUEST) ? "request":"response";
  408.         do {
  409.                 size = readline(sockfd,headerline,len);
  410.                 if(size == 0) {/* encounter EOF */
  411.                         debug("%d: readline encounter EOF when reading first headerline from %s\n",id,s);
  412.                         return -1;
  413.                 } else if(size == -1) { /* error */
  414.                         debug("%d: readline error when reading first headerline from %s : %s\n",id,s,strerror(errno));
  415.                         return -1;
  416.                 }
  417.         } while(equals(headerline,"\r\n"));
  418.         return 0;
  419. }

复制代码


然后是要用的unp.h和unp.c

unp.h

  1. #ifndef UNP_H_
  2. #define UNP_H_

  3. #include <netinet/in_systm.h>
  4. #include <netinet/ip.h>
  5. #include <netinet/ip_icmp.h>
  6. #include <netinet/udp.h>
  7. #include <arpa/inet.h>
  8. #include <sys/socket.h>
  9. #include <netdb.h>
  10. #include <errno.h>
  11. #include <signal.h>
  12. #include <stdlib.h>
  13. #include <time.h>
  14. #include <sys/time.h>
  15. #include <string.h>
  16. #include <unistd.h>
  17. #include <stdio.h>
  18. #include <stdarg.h>
  19. #include <sys/ioctl.h>
  20. #include <net/if.h>

  21. #define MAXLINE 1000
  22. #define LISTENQ 1024

  23. struct addrinfo * host_serv(const char *host,const char *serv,int family,int socktype);
  24. char *sock_ntop_host(const struct sockaddr * sa, socklen_t len);
  25. void sock_set_port(struct sockaddr *sa, socklen_t salen, int port);
  26. int sock_get_port(struct sockaddr *sa, socklen_t salen);
  27. int sock_cmp_addr(const struct sockaddr *sa1,const struct sockaddr *sa2,socklen_t salen);
  28. void tv_sub(struct timeval *out,struct timeval *in);
  29. uint16_t in_cksum(uint16_t *addr,size_t len);
  30. int tcp_connect(const char *host,const int port);
  31. size_t writen(int fd,const void *c,size_t len);
  32. ssize_t readline(int fd,void *vptr,size_t maxlen);
  33. void err_quit(const char *fmt,...);
  34. int getifaddr(int family, unsigned int ifindex, const char *ifname,void *ifaddr);
  35. int open_clientfd(char *hostname,int port);
  36. int open_listenfd(int port);
  37. #endif /*UNP_H_*/
复制代码


unp.c


  1. #include "cutil/unp.h"

  2. struct addrinfo * host_serv(const char *host,const char *serv,int family,int socktype){
  3.         int n;
  4.         struct addrinfo hints,*res;
  5.         bzero(&hints,sizeof(struct addrinfo));
  6.         hints.ai_flags = AI_CANONNAME;
  7.         hints.ai_family = family;
  8.         hints.ai_socktype = socktype;
  9.         if((n = getaddrinfo(host,serv,&hints,&res)) != 0){
  10.                 return (NULL);
  11.         }
  12.         return (res);
  13. }

  14. char *sock_ntop_host(const struct sockaddr * sa, socklen_t len){
  15.         static char str[128];               /* Unix domain is largest */
  16.         switch (sa->sa_family) {
  17.                 case AF_INET: {
  18.                         struct sockaddr_in        *sin = (struct sockaddr_in *) sa;
  19.                  if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL)
  20.                return(NULL);
  21.             return(str);
  22.       }
  23.         }  
  24. }

  25. void sock_set_port(struct sockaddr *sa, socklen_t salen, int port) {
  26.         switch (sa->sa_family) {
  27.                 case AF_INET:{
  28.                         struct sockaddr_in        *sin = (struct sockaddr_in *) sa;
  29.                         sin->sin_port = port;
  30.                 }
  31.         }
  32. }

  33. int sock_get_port(struct sockaddr *sa, socklen_t salen) {
  34.         switch (sa->sa_family) {
  35.                 case AF_INET:{
  36.                         struct sockaddr_in        *sin = (struct sockaddr_in *) sa;
  37.                         return sin->sin_port;
  38.                 }
  39.         }
  40. }

  41. int sock_cmp_addr(const struct sockaddr *sa1,const struct sockaddr *sa2,socklen_t salen){
  42.         if(sa1->sa_family != sa2->sa_family){
  43.                 return -1;
  44.         }
  45.         switch(sa1->sa_family){
  46.         case AF_INET:{
  47.                 return (memcmp(&((struct sockaddr_in *)sa1)->sin_addr,
  48.                  &((struct sockaddr_in *)sa2)->sin_addr,
  49.                  sizeof(struct in_addr)));
  50.         }
  51.         }
  52.         return -1;
  53. }

  54. void tv_sub(struct timeval *out,struct timeval *in){
  55.         if((out->tv_usec -= in->tv_usec) < 0){
  56.                 --out->tv_sec;
  57.                 out->tv_usec += 1000000;
  58.         }
  59.         out->tv_sec -= in->tv_sec;
  60. }

  61. uint16_t in_cksum(uint16_t *addr,size_t len){
  62.         int nleft = len;
  63.         uint32_t sum = 0;
  64.         uint16_t *w = addr;
  65.         uint16_t answer = 0;
  66.        
  67.         while(nleft > 1){
  68.                 sum += *w++;
  69.                 nleft -= 2;
  70.         }
  71.        
  72.         if(nleft == 1){
  73.                 *(unsigned char *)(&answer) = *(unsigned char *)w;
  74.                 sum+=answer;
  75.         }
  76.        
  77.         sum = (sum >> 16) + (sum & 0xffff);
  78.         sum += (sum >>16);
  79.         answer =~sum;
  80.         return (answer);
  81. }

  82. int tcp_connect(const char *host,const int port){
  83.         int sockfd;
  84.         struct hostent * hptr;
  85.         struct sockaddr_in servaddr;
  86.         int i;
  87.        
  88.         if((hptr = gethostbyname(host)) == NULL){
  89.                  fprintf(stderr,"gethostbyname error\n");
  90.                  return -1;
  91.         }
  92.        
  93.         if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0){
  94.                  fprintf(stderr,"socket error\n");
  95.                  close(sockfd);
  96.                  return -1;
  97.         }
  98.        
  99.         bzero(&servaddr,sizeof(servaddr));
  100.         servaddr.sin_family = AF_INET;
  101.         servaddr.sin_port = htons(port);
  102.         memcpy(&servaddr.sin_addr,hptr->h_addr,sizeof(struct in_addr));
  103.         if((i = connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr))) < 0){
  104.                  fprintf(stderr,"connect error\n");
  105.                  return -1;
  106.         }
  107.         return sockfd;
  108. }

  109. size_t writen(int fd,const void *c,size_t len){
  110.         int n;
  111.         size_t left = len;
  112.         const void *ptr = c;
  113.         while(left > 0){
  114.                 if((n = write(fd,ptr,len)) > 0){
  115.                         left -= n;
  116.                         ptr += n;
  117.                 }
  118.                 if(n < 0 && errno != EINTR){
  119.                         return -1;
  120.                 }
  121.         }
  122.         return len;
  123. }

  124. ssize_t readline(int fd,void *vptr,size_t maxlen){
  125.         ssize_t n,rc;
  126.         char c,*ptr;
  127.         ptr = vptr;
  128.         for(n=1;n<maxlen;n++){
  129.                 again:
  130.                 if((rc = read(fd,&c,1)) == 1){
  131.                         *ptr ++= c;
  132.                         if(c == '\n')
  133.                                 break;
  134.                 }else if(rc == 0){
  135.                         *ptr = 0;
  136.                         return (n-1);
  137.                 }else{
  138.                         if(errno == EINTR){
  139.                                 goto again;
  140.                         }
  141.                         return -1;
  142.                 }
  143.         }
  144.         *ptr = 0;
  145.         return n;
  146. }

  147. void err_quit(const char *fmt,...){
  148.         va_list ap;
  149.         va_start(ap,fmt);
  150.         vprintf(fmt,ap);
  151.         va_end(ap);
  152.         exit(1);
  153. }

  154. inline static int __getifaddr_ipv4(int ifindex, const char *ifname,
  155.                                    struct in_addr *ifaddr)
  156. {
  157.     struct ifreq ifreq;
  158.     int sockfd;
  159.     int ret = -1;
  160.     char ifn[IFNAMSIZ];
  161.                                                                                                                                                
  162.     if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0)
  163.     {
  164.         strncpy(ifreq.ifr_name, ifname, IFNAMSIZ);
  165.         if ((ret = ioctl(sockfd, SIOCGIFADDR, &ifreq)) >= 0)
  166.             *ifaddr = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
  167.                                                                                                                                                
  168.         close(sockfd);
  169.     }
  170.                                                                                                                                                
  171.     return ret;
  172. }
  173.                                                                                                                                                
  174. #ifdef IPV6
  175.                                                                                                                                                
  176. #define PROC_IFINET6_PATH   "/proc/net/if_inet6"
  177.                                                                                                                                                
  178. inline static int __getifaddr_ipv6(unsigned int ifindex, const char *ifname,
  179.                                    struct in6_addr *ifaddr)
  180. {
  181.     FILE *fp = fopen(PROC_IFINET6_PATH, "r");
  182.     char addrstr[INET6_ADDRSTRLEN];
  183.     char seg[8][5];
  184.     int index, plen, scope, flags;
  185.     char ifn[IFNAMSIZ];
  186.     int ret = -1;
  187.                                                                                                                                                
  188.     if (fp)
  189.     {
  190.         while (fscanf(fp, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %s\n"
  191.                       seg[0], seg[1], seg[2], seg[3], seg[4], seg[5], seg[6],
  192.                       seg[7], &index, &plen, &scope, &flags, ifn) != EOF)
  193.         {
  194.             if (ifindex == index || ifindex == 0 && strcmp(ifn, ifname) == 0)
  195.             {
  196.                 sprintf(addrstr, "%s:%s:%s:%s:%s:%s:%s:%s", seg[0], seg[1],
  197.                         seg[2], seg[3], seg[4], seg[5], seg[6], seg[7]);
  198.                 ret = inet_pton(AF_INET6, addrstr, ifaddr);
  199.                 goto out;
  200.             }
  201.         }
  202.                                                                                                                                                
  203.         errno = ENXIO;
  204. out:
  205.         fclose(fp);
  206.     }
  207.                                                                                                                                                
  208.     return ret;
  209. }
  210.                                                                                                                                                
  211. #endif
  212.                                                                                                                                                
  213. int getifaddr(int family, unsigned int ifindex, const char *ifname,
  214.               void *ifaddr)
  215. {
  216.     switch (family)
  217.     {
  218.     case AF_INET:
  219.         return __getifaddr_ipv4(ifindex, ifname, (struct in_addr *)ifaddr);
  220. #ifdef IPV6
  221.     case AF_INET6:
  222.         return __getifaddr_ipv6(ifindex, ifname, (struct in6_addr *)ifaddr);
  223. #endif
  224.     default:
  225.         errno = EAFNOSUPPORT;
  226.         return -1;
  227.     }
  228. }

  229. int open_clientfd(char *hostname,int port){
  230.         int clientfd;
  231.         struct hostent *hp;
  232.         struct sockaddr_in  serveraddr;
  233.        
  234.         if((clientfd = socket(AF_INET,SOCK_STREAM,0)) < 0){
  235.                 return -1;// check errno for cause of error
  236.         }
  237.        
  238.         //fill in server's IP address and port
  239.         if((hp = gethostbyname(hostname)) == NULL){
  240.                 return -2;//check h_errno for cause of error
  241.         }
  242.        
  243.         bzero((char *)&serveraddr,sizeof(serveraddr));
  244.         serveraddr.sin_family = AF_INET;
  245.         bcopy((char *)hp->h_addr,(char *)&serveraddr.sin_addr.s_addr,hp->h_length);
  246.         serveraddr.sin_port = htons(port);
  247.        
  248.         //establish a connection with the server
  249.         if(connect(clientfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr)) < 0){
  250.                 return -1;
  251.         }
  252.         return clientfd;
  253. }

  254. int open_listenfd(int port){
  255.         int listenfd,optval=1;
  256.         struct sockaddr_in serveraddr;
  257.        
  258.         //create a socket descriptor
  259.         if((listenfd = socket(AF_INET,SOCK_STREAM,0)) < 0){
  260.                 return -1;
  261.         }
  262.        
  263.         //eliminates "address already in use" error from bind
  264.         if(setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,(const void *)&optval,sizeof(int)) < 0){
  265.                 return -1;
  266.         }
  267.        
  268.         //listenfd will be an endpoint for all requests to port on any IP address for this host
  269.         bzero((char *)&serveraddr,sizeof(serveraddr));
  270.         serveraddr.sin_family = AF_INET;
  271.         serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //htonl(INADDR_ANY);
  272.         serveraddr.sin_port = htons((unsigned short)port);
  273.         if(bind(listenfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr)) < 0){
  274.                 return -1;
  275.         }
  276.        
  277.         //make it a listening socket ready to accept connection requests
  278.         if(listen(listenfd,LISTENQ) < 0){
  279.                 return -1;
  280.         }
  281.         return listenfd;
  282. }
  283.                
复制代码


生成可执行代码:
gcc kitty.c unp.c -o kitty

运行:
./kitty 8000

然后设置浏览器的代理服务器选项

大家测试看看有没有需要修改的地方,谢谢

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表