c++——正向代理
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/aedb7d4270aecb04dff101a0b773f7be.jpeg)
- 代理端作为客户端的监听端口、目的端的客户端口
- 正向代理B就像中转站,只做信息转发
实现思路
- 监听客户端的连接,如果有客户端连上来,代理程序向目标端发起连接请求,建立连接。
- 不管哪个socket连接收到了报文,原封不动的发给对端。
#include <sys/epoll.h>
#include <signal.h>
#include <string.h>
#include <sys/socket.h>
#include <iostream>
#include <fcntl.h>
#include <vector>
#include <poll.h>
#include <unistd.h>
#include <netdb.h>
struct st_route{
int listenport;
char* dstip;
int dstport;
int listensock;
} stroute;
int epollfd;
int initsocket(int port);
int conntodst(char* ip, int port);
int clientvec[2048];
void EXIT(int sig);
int main(int argv, char** argc){
for(int i = 0; i < 64; i++){signal(i, SIG_IGN);}
signal(2, EXIT); signal(15, EXIT);
if(argv != 4){printf("Error argc! ./inetd listenport dstip dstport \n"); return -1;}
stroute.listenport = atoi(argc[1]);
stroute.dstip = argc[2];
stroute.dstport = atoi(argc[3]);
if((stroute.listensock = initsocket(stroute.listenport)) < 0){perror("failed listen.\n"); return -1;}
epollfd = epoll_create(1);
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = stroute.listensock;
epoll_ctl(epollfd, EPOLL_CTL_ADD, stroute.listensock, &ev);
struct epoll_event Evs[10];
while(true){
int infds = epoll_wait(epollfd, Evs, 10, -1);
if(infds < 0){printf("epoll failed\n"); return -1;}
for(int i = 0; i < infds; i++){
if(Evs[i].data.fd == stroute.listensock){
struct sockaddr_in client_addr;
socklen_t len = sizeof(client_addr);
int srcsockfd;
if ((srcsockfd = accept(Evs[i].data.fd, (struct sockaddr*)&client_addr, &len)) < 0){perror("error accept.\n"); return -1;}
int dstsockfd;
if((dstsockfd = conntodst(stroute.dstip, stroute.dstport)) < 0) {perror("error conntodst\n"); return -1;}
ev.data.fd = srcsockfd; ev.events = EPOLLIN;
epoll_ctl(epollfd, EPOLL_CTL_ADD, srcsockfd, &ev);
ev.data.fd = dstsockfd; ev.events = EPOLLIN;
epoll_ctl(epollfd, EPOLL_CTL_ADD, dstsockfd, &ev);
clientvec[srcsockfd] = dstsockfd; clientvec[dstsockfd] = srcsockfd;
}else{
char buffer[2048];
int buflen = 0;
memset(&buffer, 0, sizeof(buffer));
if((buflen = recv(Evs[i].data.fd, buffer, sizeof(buffer), 0)) <= 0){
printf("client(%d, %d) disconnect\n", Evs[i].data.fd, clientvec[Evs[i].data.fd]);
close(Evs[i].data.fd);
close(clientvec[Evs[i].data.fd]);
clientvec[clientvec[Evs[i].data.fd]] = 0;
clientvec[Evs[i].data.fd] = 0;
continue;
}
send(clientvec[Evs[i].data.fd], buffer, buflen, 0);
}
}
}
return 0;
}
int initsocket(int port){
int sockfd;
int opt = 1;
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){return -1;}
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(opt));
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons(port);
if(bind(sockfd, (struct sockaddr *)& serveraddr, sizeof(struct sockaddr)) < 0){perror("bind failed.\n");close(sockfd);return -1;}
if(listen(sockfd, 10) != 0) {perror("listen failed.\n");close(sockfd);return -1;}
fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK);
return sockfd;
}
int conntodst(char* ip, int port){
int sockfd;
int opt = 1;
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){return -1;}
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(opt));
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(port);
struct hostent *h;
if((h = gethostbyname(ip)) == 0){close(sockfd); return -1;}
memcpy(&servaddr.sin_addr, h->h_addr, h->h_length);
if(connect(sockfd, (struct sockaddr*)&servaddr, sizeof(struct sockaddr)) < 0){
perror("error connect.\n");
close(sockfd);
return -1;
}
fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK);
return sockfd;
}
void EXIT(int sig){
printf("Exit! Signal=%d\n", sig);
for(int i = 0; i < 2048; i++){
if(clientvec[i]>0){close(clientvec[i]);}
}
if(stroute.listensock>0){close(stroute.listensock);}
close(epollfd);
exit(0);
}
结果