摘要:摘要: 我们在使用socket进行代理时,想到这是怎么实现的吗?小编带大家一起解密
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 即可,大家不妨下来试一试。
相关文章推荐
樱桃cherry.com域名价格或达7位数美元2022-09-06
紫燕食品上市,卤味市场域名哪家强?2022-09-27
新一期域名交易排行榜,国别域名MA.ca成无冕之王2022-09-27
威瑞信发布2022年Q2行业简报:.com注册量下降2022-09-27
域名Keys.xyz被元宇宙游戏终端收购2022-09-20