SOCKS5实现(二)
2018-03-03 17:29
916 查看
上一篇文章介绍了一些基本概念,以及简单的用现有的软件搭建透明代理。这篇文章简单说下在linux下用C++进行socket编程的过程。
参考:
C++ Socket : http://lengly.top/archives/155
C++ epoll : https://gist.github.com/dtoma/417ce9c8f827c9945a9192900aff805b
第一步是makefile的编写了,可以参考我的文章:makefile的使用
第二步是理解socket编程的一些公共函数、API,建立连接有几个过程:
服务器:
create: socket(AF_INET,SOCK_STREAM,0)
调整SOCK_STREAM这个位置的参数就可以建立TCP、UDP、RAW socket
setOptions : int setsockopt(struct socket *sock, int lvl, int opt, char __user *ov, unsigned int ol);
允许复用地址:SO_REUSEADDR
bind : int bind(int sockfd, const struct sockaddr * my_addr, socklen_t addrlen);
将一个本地地址与一个套接口绑定,如果client端不需要指定自己的地址和端口则无需进行这个设置
listen
connect: int connect (int sockfd,struct sockaddr * serv_addr, int addrlen);
accept
recv
send
close
客户端:
creat
connect
send
recv
close
这里贴一下代码~
Makefile
项目开源在 github -> wuyisheng/socks
当前代码:commit 0331d8d0817ae3ba7ef663756bfbcc7435d31c78
扫码关注,实时互动
参考:
C++ Socket : http://lengly.top/archives/155
C++ epoll : https://gist.github.com/dtoma/417ce9c8f827c9945a9192900aff805b
第一步是makefile的编写了,可以参考我的文章:makefile的使用
第二步是理解socket编程的一些公共函数、API,建立连接有几个过程:
服务器:
create: socket(AF_INET,SOCK_STREAM,0)
调整SOCK_STREAM这个位置的参数就可以建立TCP、UDP、RAW socket
setOptions : int setsockopt(struct socket *sock, int lvl, int opt, char __user *ov, unsigned int ol);
允许复用地址:SO_REUSEADDR
bind : int bind(int sockfd, const struct sockaddr * my_addr, socklen_t addrlen);
将一个本地地址与一个套接口绑定,如果client端不需要指定自己的地址和端口则无需进行这个设置
listen
connect: int connect (int sockfd,struct sockaddr * serv_addr, int addrlen);
accept
recv
send
close
客户端:
creat
connect
send
recv
close
这里贴一下代码~
Makefile
all : main.o server.o test.o client.o g++ -o server main.o server.o g++ -o test test.o client.o main.o : main.cc server.h g++ -c main.cc server.o : server.cc server.h g++ -c server.cc test.o : test.cc client.h g++ -c test.cc client.o: client.cc client.h g++ -c client.cc clean: rm -f *.o *.so server test
// // server.cc // // Created by Yeshen on 1/03/2018. // Copyright © 2018 yeshen.org. All rights reserved. // #include "server.h" #include <iostream> #include <cstdio> #include <cstdlib> #include <cerrno> #include <cstring> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #include <sys/wait.h> #include <arpa/inet.h> #include <unistd.h> #include <fcntl.h> #include <sys/epoll.h> #include <netdb.h> #define SERVER_PORT 2018 #define MAX_CONNECTION 10 #define MAX_DATA_SIZE 1000 #define MAX_EVENT 32 using namespace std; Server::Server(){ this->port = 2018; this->running = false; }; Server::Server(int port){ this->port = port; this->running = false; }; void Server::start(){ cout << "start" << endl; //create and bind int sock_fd,client_fd; int sin_size; struct sockaddr_in local_addr; struct sockaddr_in remote_addr; if((sock_fd = socket(AF_INET,SOCK_STREAM,0))==-1){ perror("fail to create socket"); exit(1); } long flag = 1; setsockopt(sock_fd,SOL_SOCKET,SO_REUSEADDR,(char *)&flag,sizeof(flag)); local_addr.sin_family = AF_INET; local_addr.sin_port = htons(SERVER_PORT); local_addr.sin_addr.s_addr = INADDR_ANY; bzero(&(local_addr.sin_zero),8); if(bind(sock_fd,(struct sockaddr *)&local_addr,sizeof(struct sockaddr)) == -1){ perror("fail to bind socket"); exit(1); } int sock_flags = fcntl(sock_fd,F_GETFL,0); sock_flags |= O_NONBLOCK; if(fcntl(sock_fd, F_SETFL, sock_flags) == -1){ perror("fail to set nonblock"); exit(1); } //listen if(listen(sock_fd,MAX_CONNECTION) == -1){ perror("fail to listen"); exit(1); } int epoll_fd; if((epoll_fd = epoll_create1(0))==-1){ perror("fail to create epoll"); exit(1); } struct epoll_event event,events[MAX_EVENT]; event.data.fd = sock_fd; event.events = EPOLLIN | EPOLLET; if(epoll_ctl(epoll_fd,EPOLL_CTL_ADD,sock_fd,&event) == -1){ perror("fail to create epoll ctl"); exit(1); } while(true){ int n = epoll_wait(epoll_fd,events,MAX_EVENT,-1); for(int i =0;i<n; ++i){ if(events[i].events & EPOLLERR || events[i].events & EPOLLHUP || !(events[i].events & EPOLLIN) ){ perror("error in epoll event"); close(events[i].data.fd); }else if(sock_fd == events[i].data.fd){ while(true){ struct sockaddr in_addr; socklen_t in_len = sizeof(in_addr); int in_fd; if((in_fd = accept(sock_fd,&in_addr,&in_len)) == -1){ if(errno == EAGAIN || errno == EWOULDBLOCK){ continue; }else{ perror("accept failed"); continue; } } std::string hbuf(NI_MAXHOST,'\0'); std::string sbuf(NI_MAXSERV,'\0'); if(getnameinfo(&in_addr,in_len, const_cast<char*>(hbuf.data()),hbuf.size(), const_cast<char*>(sbuf.data()),sbuf.size(), NI_NUMERICHOST | NI_NUMERICSERV) == 0 ){ std::cout << "Accepted:" << in_fd << "(host=" << hbuf << ", port=" << sbuf << ")" << endl; } int in_flags = fcntl(in_fd,F_GETFL,0); in_flags |= O_NONBLOCK; if(fcntl(in_fd, F_SETFL, in_flags) == -1){ std::cout << "nonblocking" << "(host=" << hbuf << endl; continue; } event.data.fd = in_fd; event.events = EPOLLIN | EPOLLET; if(epoll_ctl(epoll_fd,EPOLL_CTL_ADD,in_fd,&event) ==-1){ printf("fail to add epoll\n"); continue; } if(send(in_fd,"Hello, you are connected!\n",26,0) == -1){ printf("fail to send\n"); continue; } break; } }else{ int fd = events[i].data.fd; while(true){ char buf[512]; int count = read(fd,buf,512); if(count == -1){ if(errno == EAGAIN){ continue; } }else if(count ==0){ printf("close %d\n",fd); close(fd); continue; }else{ std::cout <<"says:" << buf << endl; } break; } } } } close(sock_fd); } void Server::stop(){ cout << "stop" << endl; }
// // client.cc // // Created by Yeshen on 1/03/2018. // Copyright © 2018 yeshen.org. All rights reserved. // #include <iostream> #include <string> #include "client.h" #include <cstdio> #include <cstdlib> #include <cerrno> #include <netdb.h> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <netinet/in.h> #include <arpa/inet.h> #define MAX_DATA_SIZE 1000 using namespace std; Client::Client(){ this->ip = "127.0.0.1"; this->port = 2018; }; Client::Client(const char * ip, int port){ this->ip = ip; this->port = port; }; void Client::run(){ cout << "run" << this->ip << this->port << endl ; int sock_fd = -1; char buf[MAX_DATA_SIZE]; int recvbytes,sendbytes,len; in_addr_t server_ip = inet_addr(this->ip); in_port_t server_port = atoi("2018");//TODO in_addr_t my_ip = inet_addr(this->ip); in_port_t my_port = atoi("2028"); if((sock_fd = socket(AF_INET,SOCK_STREAM,0)) == -1){ perror("fail to creat socket"); exit(1); } long flag = 1; setsockopt(sock_fd,SOL_SOCKET,SO_REUSEADDR,(char *)&flag,sizeof(flag)); struct sockaddr_in my_addr; my_addr.sin_addr.s_addr = my_ip; my_addr.sin_family = AF_INET; my_addr.sin_port = htons(my_port); if(bind(sock_fd,(sockaddr*)&my_addr,sizeof(sockaddr)) == -1){ perror("fail to bind socket"); exit(1); } struct sockaddr_in server_addr; server_addr.sin_addr.s_addr = server_ip; server_addr.sin_family = AF_INET; server_addr.sin_port = htons(server_port); printf("try to connect %s:%u\n", inet_ntoa(server_addr.sin_addr), ntohs(server_addr.sin_port)); if(connect(sock_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1){ perror("fail to connect"); exit(1); } if(send(sock_fd,"here\n",4,0) == -1){ perror("fail to send"); } if((recvbytes=recv(sock_fd,buf,MAX_DATA_SIZE,0)) == -1){ perror("fail to recv"); exit(1); } buf[recvbytes] = '\0'; printf("Received: %s",buf); close(sock_fd); exit(0); }
项目开源在 github -> wuyisheng/socks
当前代码:commit 0331d8d0817ae3ba7ef663756bfbcc7435d31c78
扫码关注,实时互动
相关文章推荐
- 一个简单的Golang实现的Socks5 Proxy
- ProxyCap +ccproxy 组合使用Socks5 实现代理服务器
- Socks5和HTTP代理实现PAM+OpenLDAP用户认证
- ProxyCap +ccproxy 组合使用Socks5 实现代理服务器
- python socks5 proxy实现
- SOCKS5实现(三)
- 使用httpclient 4.3实现 socks5 proxy + 身份验证
- java实现一个socks5代理 <一>了解socks5协议
- 斐波那契数列(fibonacci)两种python实现的效率对比
- 使用vector类实现string的输入和输出
- u-boot-2011.03在TQ2440上的移植(5)—实现Nand/Nor 双启动
- 微信jssdk,实现多图上传的一点心得
- windows7下实现用户自动登录
- MATLAB中与串行借口实现通讯
- "Java中可复用事件处理的设计与实现"代码
- 使用Servlet实现动态文件下载
- 在SQL Server 2005中用存储过程实现搜索功能