一個簡易的proxy程式的開發過程(2)(轉)
一個簡易的proxy程式的開發過程(2)(轉)[@more@]原創 01-08-20 17:42 68p ariesram
--------------------------------------------------------------------------------
簡易Proxy程式(原始碼)
上次貼出了一篇<>和<>之後,有不少網友來信詢問下文何時出現。我卻一直忙於工作,忘記了將下文貼上來,非常抱歉。現在在這裡把原始碼貼出來。我申明這個原始碼基於GNU GPL,目的在於希望大家能夠有時間去更加完善它。你也可以按照你自己的希望去改變它。不過,如果你做了任何大的改動,請通知我.
TODO:
1、使程式能夠監聽多個埠,並且連線多個遠端服務。
2、使程式能夠從配置檔案中讀取設定監聽埠和所要連線的遠端服務地址以及埠以滿足多種服務並存
的需要。
sp.c
/*******************************************************************************
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*******************************************************************************/
/*******************************************************************************
Program: sp.c
Description: a smart proxy
Author: Alan Chen (ariesram@may10.ca)
Date: July 18, 2001
*******************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#define ERRLOG "./sp.log"
int do_proxy(int infd, char* addr, int port);
int max(int i, int j);
void waitchild(int);
void version();
void usage();
void daemonize();
void p_error(const char * err_msg);
int main(int argc, char** argv) {
struct sockaddr_in servaddr, clientaddr;
int listenfd, connfd;
int clientlen;
pid_t chpid;
int service_port = 0, remote_port = 0;
char remote_addr[17];
const char optstring[] = "s:r:p:vh";
int opt;
extern char *optarg;
extern int optind, opterr, optopt;
extern FILE *stderr;
memset(remote_addr, 0, 17);
if( argc == 2 ) {
while( (opt = getopt(argc, argv, optstring)) != -1 ) {
if( opt == 'v' ) {
version();
exit(0);
}
else if ( opt == 'h' ) {
usage();
exit(0);
}
else {
printf("type sp -h for help message ");
usage();
exit(0);
}
}
}
else {
while( (opt = getopt(argc, argv, optstring)) != -1 ) {
switch(opt) {
case 's':
service_port = atoi(optarg);
break;
case 'r':
memcpy(remote_addr, optarg, strlen(optarg));
remote_addr[strlen(remote_addr)] = '';
break;
case 'p':
remote_port = atoi(optarg);
break;
default:
usage();
exit(0);
}
}
}
if( service_port == 0' 'remote_port == 0' 'remote_addr[0] == '') {
usage();
exit(0);
}
daemonize();
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(service_port);
servaddr.sin_addr.s_addr = INADDR_ANY;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if(listenfd < 0) {
p_error("socket error");
exit(-1);
}
if( bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 ) {
p_error("bind error");
exit(-1);
}
if( listen(listenfd, 5) < 0 ) {
p_error("listen error");
exit(-1);
}
signal(SIGCHLD, waitchild);
for(;;) {
connfd = accept( listenfd, (struct sockaddr *)&clientaddr,
&clientlen );
if( connfd < 0 ) {
p_error("accept error");
exit(-1);
}
if( (chpid = fork()) == -1 ) {
p_error("fork error");
exit(-1);
}
if( chpid == 0 ) {
close(listenfd);
do_proxy(connfd, remote_addr, remote_port);
exit(0);
}
if( chpid > 0 ) {
close(connfd);
}
}
exit(0);
}
int do_proxy(int infd, char *addr, int port) {
struct sockaddr_in rout;
int outfd;
int maxfd;
int count = 65535;
int n;
fd_set set;
char buf[count];
bzero(&rout, sizeof(rout));
rout.sin_family = AF_INET;
rout.sin_port = htons(port);
rout.sin_addr.s_addr = inet_addr(addr);
if( (outfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
p_error("socket error");
exit(-1);
}
if( connect(outfd, (struct sockaddr *)&rout, sizeof(rout)) < 0 ) {
p_error("connect error");
exit(-1);
}
while(1) {
FD_ZERO(&set);
FD_SET(infd, &set);
FD_SET(outfd, &set);
maxfd = max(outfd, infd);
if( select(maxfd + 1, &set, NULL, NULL, NULL) < 0 ) {
perror("select error:");
exit(-1);
}
if( FD_ISSET(infd, &set) ) {
n = read(infd, (void *)buf, count);
if( n <= 0)
break;
if( write(outfd, (const void *)buf, n) != n ) {
p_error("write error");
continue;
}
}
if( FD_ISSET(outfd, &set) ) {
n = read(outfd, (void *)buf, count);
if( n <= 0)
break;
if( write(infd, (const void *)buf, n) != n ) {
p_error("write error");
continue;
}
}
}
close(infd);
close(outfd);
}
int max(int i, int j) {
return i>j?i:j;
}
void waitchild(int signo) {
int status;
pid_t childpid;
if( (childpid = waitpid(-1, &status, WNOHANG)) < 0 ) {
p_error("wait error");
exit(1);
}
return;
}
void version() {
printf("GNU SP 1.0
Copyright 2001 Aryes Software Studio, Inc.
SP is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions. ");
}
void usage() {
printf("This is the GNU smart proxy daemon. Usage:
sp -s service_port -r remote_address -p remote_port
sp -v
sp -h
option:
-s specify service port of sp
-r specify remote address which sp will connect
-p specify remote port while sp will connect to
-v display version message
-h display this help message
Report bugs to. ");
}
void daemonize() {
int i;
#ifndef _DEBUG
signal(SIGINT, SIG_IGN);
#endif
signal(SIGHUP, SIG_IGN);
signal(SIGABRT, SIG_IGN);
signal(SIGSTOP, SIG_IGN);
signal(SIGCHLD, SIG_IGN);
#ifndef _DEBUG
if (fork() != 0)
exit(0);
setsid();
for (i = 256; i >= 0; i --)
#endif
#ifdef _DEBUG
for (i = 256; i >= 3; i --)
#endif
close(i);
}
void p_error(const char * err_msg)
{
FILE * fp;
#ifdef _DEBUG
printf("%s ", err_msg);
#endif
fp = fopen(ERRLOG, "a");
if (fp == NULL)
return;
fprintf(fp, "%s ", err_msg);
fclose(fp);
}
--------------------------------------------------------------------------------
簡易Proxy程式(原始碼)
上次貼出了一篇<>和<>之後,有不少網友來信詢問下文何時出現。我卻一直忙於工作,忘記了將下文貼上來,非常抱歉。現在在這裡把原始碼貼出來。我申明這個原始碼基於GNU GPL,目的在於希望大家能夠有時間去更加完善它。你也可以按照你自己的希望去改變它。不過,如果你做了任何大的改動,請通知我
TODO:
1、使程式能夠監聽多個埠,並且連線多個遠端服務。
2、使程式能夠從配置檔案中讀取設定監聽埠和所要連線的遠端服務地址以及埠以滿足多種服務並存
的需要。
sp.c
/*******************************************************************************
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*******************************************************************************/
/*******************************************************************************
Program: sp.c
Description: a smart proxy
Author: Alan Chen (ariesram@may10.ca)
Date: July 18, 2001
*******************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#define ERRLOG "./sp.log"
int do_proxy(int infd, char* addr, int port);
int max(int i, int j);
void waitchild(int);
void version();
void usage();
void daemonize();
void p_error(const char * err_msg);
int main(int argc, char** argv) {
struct sockaddr_in servaddr, clientaddr;
int listenfd, connfd;
int clientlen;
pid_t chpid;
int service_port = 0, remote_port = 0;
char remote_addr[17];
const char optstring[] = "s:r:p:vh";
int opt;
extern char *optarg;
extern int optind, opterr, optopt;
extern FILE *stderr;
memset(remote_addr, 0, 17);
if( argc == 2 ) {
while( (opt = getopt(argc, argv, optstring)) != -1 ) {
if( opt == 'v' ) {
version();
exit(0);
}
else if ( opt == 'h' ) {
usage();
exit(0);
}
else {
printf("type sp -h for help message ");
usage();
exit(0);
}
}
}
else {
while( (opt = getopt(argc, argv, optstring)) != -1 ) {
switch(opt) {
case 's':
service_port = atoi(optarg);
break;
case 'r':
memcpy(remote_addr, optarg, strlen(optarg));
remote_addr[strlen(remote_addr)] = '';
break;
case 'p':
remote_port = atoi(optarg);
break;
default:
usage();
exit(0);
}
}
}
if( service_port == 0' 'remote_port == 0' 'remote_addr[0] == '') {
usage();
exit(0);
}
daemonize();
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(service_port);
servaddr.sin_addr.s_addr = INADDR_ANY;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if(listenfd < 0) {
p_error("socket error");
exit(-1);
}
if( bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 ) {
p_error("bind error");
exit(-1);
}
if( listen(listenfd, 5) < 0 ) {
p_error("listen error");
exit(-1);
}
signal(SIGCHLD, waitchild);
for(;;) {
connfd = accept( listenfd, (struct sockaddr *)&clientaddr,
&clientlen );
if( connfd < 0 ) {
p_error("accept error");
exit(-1);
}
if( (chpid = fork()) == -1 ) {
p_error("fork error");
exit(-1);
}
if( chpid == 0 ) {
close(listenfd);
do_proxy(connfd, remote_addr, remote_port);
exit(0);
}
if( chpid > 0 ) {
close(connfd);
}
}
exit(0);
}
int do_proxy(int infd, char *addr, int port) {
struct sockaddr_in rout;
int outfd;
int maxfd;
int count = 65535;
int n;
fd_set set;
char buf[count];
bzero(&rout, sizeof(rout));
rout.sin_family = AF_INET;
rout.sin_port = htons(port);
rout.sin_addr.s_addr = inet_addr(addr);
if( (outfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
p_error("socket error");
exit(-1);
}
if( connect(outfd, (struct sockaddr *)&rout, sizeof(rout)) < 0 ) {
p_error("connect error");
exit(-1);
}
while(1) {
FD_ZERO(&set);
FD_SET(infd, &set);
FD_SET(outfd, &set);
maxfd = max(outfd, infd);
if( select(maxfd + 1, &set, NULL, NULL, NULL) < 0 ) {
perror("select error:");
exit(-1);
}
if( FD_ISSET(infd, &set) ) {
n = read(infd, (void *)buf, count);
if( n <= 0)
break;
if( write(outfd, (const void *)buf, n) != n ) {
p_error("write error");
continue;
}
}
if( FD_ISSET(outfd, &set) ) {
n = read(outfd, (void *)buf, count);
if( n <= 0)
break;
if( write(infd, (const void *)buf, n) != n ) {
p_error("write error");
continue;
}
}
}
close(infd);
close(outfd);
}
int max(int i, int j) {
return i>j?i:j;
}
void waitchild(int signo) {
int status;
pid_t childpid;
if( (childpid = waitpid(-1, &status, WNOHANG)) < 0 ) {
p_error("wait error");
exit(1);
}
return;
}
void version() {
printf("GNU SP 1.0
Copyright 2001 Aryes Software Studio, Inc.
SP is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions. ");
}
void usage() {
printf("This is the GNU smart proxy daemon. Usage:
sp -s service_port -r remote_address -p remote_port
sp -v
sp -h
option:
-s specify service port of sp
-r specify remote address which sp will connect
-p specify remote port while sp will connect to
-v display version message
-h display this help message
Report bugs to
}
void daemonize() {
int i;
#ifndef _DEBUG
signal(SIGINT, SIG_IGN);
#endif
signal(SIGHUP, SIG_IGN);
signal(SIGABRT, SIG_IGN);
signal(SIGSTOP, SIG_IGN);
signal(SIGCHLD, SIG_IGN);
#ifndef _DEBUG
if (fork() != 0)
exit(0);
setsid();
for (i = 256; i >= 0; i --)
#endif
#ifdef _DEBUG
for (i = 256; i >= 3; i --)
#endif
close(i);
}
void p_error(const char * err_msg)
{
FILE * fp;
#ifdef _DEBUG
printf("%s ", err_msg);
#endif
fp = fopen(ERRLOG, "a");
if (fp == NULL)
return;
fprintf(fp, "%s ", err_msg);
fclose(fp);
}
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10796304/viewspace-962588/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 一個簡單java程式的執行全過程Java
- 一個Flutter中臺元件的開發過程Flutter元件
- 敏捷開發過程中易產生安全問題的6個習慣敏捷
- 熟悉一個“高質量”軟體的開發過程
- [前端]基於vue和nodejs的一個簡陋blog的開發過程中遇到的問題前端VueNodeJS
- mpvue & 小程式開發過程中的坑Vue
- 200行程式碼寫一個簡易的dva行程
- 一起來擼個簡易的小程式框架框架
- 一個簡易版的T4程式碼生成
- 總結開發過程踩到的坑(一)
- 記錄開發過程一個路由問題路由
- Python 使用QT5開發介面的一個demo開發過程的總結PythonQT
- 手寫一個簡易的WebpackWeb
- 實現一個簡易的vueVue
- 【Mysql】一個簡易的索引方案MySql索引
- [轉]:如何快速構建一個簡單的程式
- 敏捷轉型過程中避不開的4個問題敏捷
- 簡易的開發環境搭建開發環境
- 硬體開發基本流程,製作一個USB轉RS232的模組(一):開發基本過程和元器件選型
- 用threejs開發一個簡易的打飛機和飛機破碎效果JS
- 記一次nodejs開發CLI的過程NodeJS
- SAP MM採購定價過程的一個簡單例子單例
- 如何搭建一個簡易的 Web Terminal(一)Web
- zabbix server & proxy部署操作過程Server
- golang開發一個簡單的grpcGolangRPC
- 如何通過幾個簡單的步驟編寫一個漂亮的初級開發者簡歷
- 2.深入一點理解C源程式的編譯過程編譯
- 用 Go 寫一個簡易的 dockerGoDocker
- 皮膚開發過程中遇到的3個問題
- CSS開發過程中的20個快速提升技巧CSS
- 簡單上手SpringBean的整個裝配過程SpringBean
- 從零開始實現一個簡易的Java MVC框架JavaMVC框架
- 開發小程式過程中採坑
- 1個開發如何撐起一個過億使用者的小程式
- 從面相過程的拖拽到物件導向的拖拽再到簡易的元件拖拽物件元件
- micropython TPYBoard v201 簡易的web伺服器的實現過程PythonWeb伺服器
- 來實現一個簡易版的 PromisePromise
- 一個簡易的渲染迴圈結構
- 記錄從0開發一個vue的富文字外掛過程以及遇到的坑Vue