JAVA实现网络请求代理之Socket篇

阅读:464 2019-03-19 14:40:04 来源:开源中国

java实现网络请求代理之http篇(一)

java实现网络请求代理之socket篇(二)

java代理服务器之截取,篡改http请求(应用篇)

用java实现socket代理服务,原理上和http代理有些相似,只是两种协议的格式不一样。socket是对tcp/ip协议的抽象封装,所以socket的格式和tcp/ip的协议是不一样的。

具体详细的socket和tcp/ip的关系大家可以参考http://www.2cto.com/net/201211/166537.html这篇博文。

下面还是继续贴上代码,供大家研究

packagecom.mato.proxy.socket;importjava.net.serversocket;importjava.net.socket;/***createdbycjlon2015/9/9.*/publicclasssocketproxyextendsthread{privateserversocketserver;publicsocketproxy(serversocket_server){server=_server;start();}publicvoidrun(){//线程运行函数socketconnection;while(true){try{connection=server.accept();socksserverthreadhandler=newsocksserverthread(connection);}catch(exceptione){}}}}

接下来就是socket连接的具体处理类。

packagecom.mato.proxy.socket;importjava.io.datainputstream;importjava.io.dataoutputstream;importjava.io.ioexception;importjava.net.socket;/***createdbycjlon2015/9/8.*/publicclasssocksserverthreadextendsthread{privatesocketclient;intbytes2int(byteb){//将byte类型转换为int类型intmask=0xff;inttemp=0;intres=0;res<<=8;temp=b&mask;res|=temp;returnres;}publicsocksserverthread(socket_connection){//构造函数client=_connection;start();}publicvoidrun(){//线程运行函数bytecreadbuf[]=newbyte[10000],cwritebuf[]=newbyte[10000],buf2[]=newbyte[10000];intcreadlen=0,sreadlen=0,readbytes2=0;datainputstreamcin=null,sin=null;dataoutputstreamcout=null,sout=null;strings=null,s1=null,s2=null;inti;intport=0,port1=0;stringip=null;socketserver=null;byteip1[]=newbyte[4],ip2[]=newbyte[4];try{cin=newdatainputstream(client.getinputstream());cout=newdataoutputstream(client.getoutputstream());if(cin!=null&&cout!=null){creadlen=cin.read(creadbuf,0,10000);//从客户端读数据if(creadlen>0){//读到数据if(creadbuf[0]==5){//读到sock5请求//发送sock5应答,第一次cwritebuf[0]=5;cwritebuf[1]=0;cout.write(cwritebuf,0,2);cout.flush();creadlen=cin.read(creadbuf,0,10000);//继续读sock5请求if(creadlen>0){//读到sock5请求if(creadbuf[0]==5&&creadbuf[1]==1&&creadbuf[2]==0&&creadbuf[3]==1){//tcp请求//从该请求中取要连接的ip地址和端口号,并建立tcp套接字ip=bytes2int(creadbuf[4])+"."+bytes2int(creadbuf[5])+"."+bytes2int(creadbuf[6])+"."+bytes2int(creadbuf[7]);port=creadbuf[8]*256+creadbuf[9];server=newsocket(ip,port);//创建到远程服务端的套接字sin=newdatainputstream(server.getinputstream());sout=newdataoutputstream(server.getoutputstream());//发送sock5应答ip1=server.getlocaladdress().getaddress();port1=server.getlocalport();creadbuf[1]=0;creadbuf[4]=ip1[0];creadbuf[5]=ip1[1];creadbuf[6]=ip1[2];creadbuf[7]=ip1[3];creadbuf[8]=(byte)(port1>>8);creadbuf[9]=(byte)(port1&0xff);cout.write(creadbuf,0,10);//回复应答,第二次cout.flush();//建立线程,用于给客户端返回数据socketchannelchannel=newsocketchannel(sin,cout);while(true){//循环读数据try{if(sreadlen==-1)break;//无数据则退出循环sreadlen=cin.read(cwritebuf,0,10000);//从客户端读数据if(sreadlen>0){//读到数据,则发送给外网sout.write(cwritebuf,0,sreadlen);sout.flush();}}catch(exceptione1){break;}}}}}if(creadbuf[0]==4){//读到sock4请求port=creadbuf[2]*256+creadbuf[3];//从请求中取端口号if(creadbuf[4]==0&&creadbuf[5]==0&&creadbuf[6]==0&&creadbuf[7]!=0&&creadbuf[8]==0){//如请求中为域名s=newstring(creadbuf);s=s.substring(9);s=s.substring(0,s.indexof("�"));}else{//如请求中为ip地址ip=bytes2int(creadbuf[4])+"."+bytes2int(creadbuf[5])+"."+bytes2int(creadbuf[6])+"."+bytes2int(creadbuf[7]);s=ip;}for(i=1;i<=9;i++)creadbuf[i-1]=0;server=newsocket(s,port);//根据sock4请求中的地址建立tcp套接字sin=newdatainputstream(server.getinputstream());sout=newdataoutputstream(server.getoutputstream());//返回sock4应答,第二次ip1=server.getlocaladdress().getaddress();port1=server.getlocalport();creadbuf[0]=0;creadbuf[1]=0x5a;creadbuf[2]=ip1[0];creadbuf[3]=ip1[1];creadbuf[4]=(byte)(port1>>8);creadbuf[5]=(byte)(port1&0xff);cout.write(creadbuf,0,8);cout.flush();//建立线程,用于给客户端返回数据socketchannelthread1=newsocketchannel(sin,cout);while(true){//循环读数据try{if(sreadlen==-1)break;//无数据则退出循环sreadlen=cin.read(cwritebuf,0,10000);//从客户端读数据if(sreadlen>0){//读到数据,则发送给外网sout.write(cwritebuf,0,sreadlen);sout.flush();}}catch(exceptione1){break;}}}}}//执行关闭操作if(sin!=null)sin.close();if(sout!=null)sout.close();if(server!=null)server.close();if(cin!=null)cin.close();if(cout!=null)cout.close();if(client!=null)client.close();}catch(ioexceptione){}}}

再接下来就是socket建立传输通道的线程类

packagecom.mato.proxy.socket;importjava.io.datainputstream;importjava.io.dataoutputstream;/***createdbycjlon2015/9/8.*/publicclasssocketchannelextendsthread{privatedatainputstreamin;//读数据privatedataoutputstreamout;//写数据publicsocketchannel(datainputstream_in,dataoutputstream_out){in=_in;out=_out;start();}publicvoidrun(){//线程运行函数,循环读取返回数据,并发送给相关客户端intreadbytes=0;bytebuf[]=newbyte[10000];while(true){//循环try{if(readbytes==-1)break;//无数据则退出循环readbytes=in.read(buf,0,10000);if(readbytes>0){out.write(buf,0,readbytes);out.flush();}}catch(exceptione){break;}//异常则退出循环}}}

最后就是一个main启动

packagecom.mato.proxy;importcom.mato.proxy.http.httpproxy;importcom.mato.proxy.socket.socketproxy;importjava.io.ioexception;importjava.net.serversocket;/***createdbycjlon2015/9/8.*/publicclassproxy{publicstaticvoidmain(string[]args){try{serversockethttpserver=newserversocket(808);//建立http侦听套接字system.out.println("httpproxystartedon"+httpserver.getlocalport());serversocketsocksserver=newserversocket(888);//建立socks侦听套接字system.out.println("socksproxystartedon"+socksserver.getlocalport());httpproxyhttpproxy=newhttpproxy(httpserver);//建立http侦听线程socketproxysocksproxy=newsocketproxy(socksserver);//建立socks侦听线程}catch(ioexceptione){}}}

其中包括昨天的http代理服务的启动,socket代理只是实现了tcp协议的,如果要实现udp协议的话,按照其协议格式进行解析,socket类替换成datagramsocket即可,大家不妨下来试一试。

相关文章
{{ v.title }}
{{ v.description||(cleanHtml(v.content)).substr(0,100)+'···' }}
你可能感兴趣
推荐阅读 更多>
推荐商标

{{ v.name }}

{{ v.cls }}类

立即购买 联系客服