📄 proxy2.c
字号:
#include <comlib.h>int main(int argc, char *argv[]){ int nListenSock = -1, nLocalSock = -1, nRemoteSock = -1; pid_t nChild; if (argc != 2) /* 命令行参数:“proxy1 本地端口” */ { PrintLog(stdout, "proxy1 LOCALPORT\n"); return 1; } /* ---------------------------父进程------------------------------- */ /* ① 创建侦听套接字 */ ASSERT(CreateSock(&nListenSock, atoi(argv[1]), 8) == 0); PrintLog(stdout, "listen service: service is activated."); InitServer(); /* ② 进程转后台运行 */ while (1) { /* ③ 等待并创建连接套接字 */ if (!VERIFY(AcceptSock(&nLocalSock, nListenSock) == 0)) continue; /* ③ 继续等待 */ VERIFY((nChild = fork()) >= 0); /* ④ 创建子进程 */ if (nChild == 0) break; /* 子进程跳转到子进程代码 */ close(nLocalSock); /* ⑤ 父进程关闭连接套接字 */ } /* ---------------------------子进程------------------------------- */ close(nListenSock); /* ⑦ 子进程关闭侦听套接字 */ /* 解析HTTP报文头,并与目标服务器建立连接 */ if (HttpConnect(nLocalSock, &nRemoteSock) == 0) SendReciveServer(nLocalSock, nRemoteSock); /* 通信转发 */ if (nLocalSock >= 0) close(nLocalSock); /* ⑨ 子进程关闭本地端套接字 */ if (nRemoteSock >= 0) close(nRemoteSock);/* ⑨ 子进程关闭目标端套接字 */}/* --- 解析HTTP报文头,并与目标服务器建立连接 --- */int HttpConnect(int nLocalSock, int *nRemoteSock){ char szIp[30], buf[4096]; int nread; memset(buf,0,sizeof(buf)); /* 接收网页浏览端发送的数据请求 */ while ((nread = read(nLocalSock, buf, sizeof(buf))) < 0) { if (errno != EINTR) /* 信号导致read中断,继续接收 */ { perror("read"); /* 其它错,结束子进程 */ return 1; } } memset(szIp, 0, sizeof(szIp)); /* 解析HTTP报文,简单验证报文,并获取目标服务器的IP地址 */ if (GetObjectIp(buf, szIp) != 0) return 2; /* 连接目标服务器,端口80(网页浏览端口) */ if (!VERIFY(ConnectSock(nRemoteSock, 80, szIp) == 0)) { PrintLog(stderr, "Connect Server Fail,Addr[%s]", szIp); return 3; /* 连接目标端失败,结束子进程 */ } if (WriteFile(*nRemoteSock, buf, nread) != 0) /* 转发数据 */ { PrintLog(stderr, "Write message to server error[%d]", nread); perror("write"); /* 数据转发失败,结束子进程 */ return 4; } return 0; /* 成功返回 */}/* --- 解析HTTP报文,简单验证报文,并获取目标服务器的IP地址 --- */int GetObjectIp(char *buf, char *ip){ char *p = NULL, *p1 = NULL, hostname[50]; struct hostent *host; if (strstr(buf, "HTTP") == NULL) return 1; /* 验证是否为HTTP报文 */ /* HTTP报文的“Host: ”实体头信息中记载了目标服务器的域名,以下获取域名数据 */ if ((p = strstr(buf, "Host:")) == NULL) return 2; /* HTTP报文错 */ if ((p1 = strstr(p, "\n")) == NULL) return 3; /* HTTP报文错 */ memset(hostname, 0, sizeof(hostname)); strncpy(hostname, p+strlen("Host: "), p1 - p - strlen("Host: ")); /* 去除字符串末端的CRLF(回车换行) */ if (hostname[strlen(hostname) - 1] == '\n' || hostname[strlen(hostname) - 1] == '\r') hostname[strlen(hostname) - 1] = 0; PrintLog(stderr, "[%s]", hostname); if ((host = gethostbyname(hostname)) == NULL) /* 域名转协议地址 */ { herror("gethostbyname"); return 3; } strcpy(ip, (char *)inet_ntoa(*((struct in_addr *)host->h_addr))); PrintLog(stderr, ip); return 0;}int SendReciveServer(int nLocalSock, int nRemoteSock){ int nMaxSock; struct timeval wait; fd_set fdset; int ret; while(1) { /* ①创建套接字描述符集合 */ FD_ZERO(&fdset); FD_SET(nLocalSock,&fdset); FD_SET(nRemoteSock,&fdset); /* ②准备超时时间 */ wait.tv_sec=60; wait.tv_usec=0; /* ③调用select,检查返回 */ nMaxSock = nLocalSock > nRemoteSock ? nLocalSock : nRemoteSock; if (select(nMaxSock+1,&fdset, NULL, NULL, &wait) == -1) { PrintLog(stderr, "Select Failed."); return 1; } /* ④监测状态变化的套接字 */ /* 如果套接字nLocalSock可以接收,则接收数据,发送数据到套接字nRemoteSock */ if (FD_ISSET(nLocalSock, &fdset)) { PrintLog(stderr, "Local To Remote"); ret = TransSock(nLocalSock, nRemoteSock); } /* 如果套接字nRemoteSock可以接收,则接收数据,发送到套接字nLocalSock */ else if (FD_ISSET(nRemoteSock, &fdset)) { PrintLog(stderr, "Remote To Local"); ret = TransSock(nRemoteSock, nLocalSock); } /* 结果判断 */ if (ret == 1) return 1; else if (ret == 2) break; }/* end for while */ return 0;}int TransSock(int nReadSock, int nWriteSock){ int nread; char buf[4096]; memset(buf,0,sizeof(buf)); if ((nread = read(nReadSock, buf, sizeof(buf))) < 0) /* 接收数据 */ { if (errno != EINTR) return 1; else return 0; } else if (nread == 0) /* 套接字关闭 */ { PrintLog(stderr, "client is close"); return 2; } PrintLog(stderr, "[%d]", nread); if (WriteFile(nWriteSock, buf, nread) != 0) /* 转发数据 */ { PrintLog(stderr, "Write message to server error[%d]", nread); perror("write"); return 1; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -