时间: 2021-07-31 作者:daque
c#搜集编制程序之十二——实现Web代理功能 代劳效劳步调是一种普遍运用的搜集运用步调。代劳步调的品种特殊多,按照和议各别不妨分红http代劳效劳步调、ftp代劳效劳步调等,而运转代劳效劳步调的效劳器也就相映称为http代劳效劳器和ftp代劳效劳器。正文将引见的web代劳效劳步调代劳的是http和议。 一、搜集代劳步调的便宜 代劳效劳所起的是一个桥的效率,它是搜集消息的中间转播站。在搜集中运用代劳效劳普遍是鉴于以次几个因为: (1)充溢运用ip地方资源。在局域网中,普遍对外的ip地方都利害常有限的,为了保护局域网里面的长机都不妨考察互联网络资源,经过搜集代劳就不妨实行。 (2)不妨保护搜集安定。搜集代劳不妨充任里面网和互联网络之间的风火墙,经过过滤ip地方,控制某些ip地方对外部资源的考察。 (3)不妨灵验地湮没本人的ip地方和长机名。因为一切对外网的乞求都是经过代劳效劳器实行的,以是手段长机只能领会代劳效劳器的ip地方。 (4)普及搜集速率。常常代劳效劳器都设有一个较大的硬盘缓冲区,它保存界数据,当你再考察沟通的数据时,则不妨径直从缓冲区中掏出消息,进而普及考察速率。 二、搜集代劳的典型及实行道理 搜集代劳效劳按照处事档次,普遍可分为运用层代劳、传输层代劳和socks代劳。运用层代劳是处事在tcp/ip参考模子的运用层之上,它扶助对运用层和议(如http、ftp)的代劳。它供给的遏制最多,然而不精巧,必需要有相映的和议扶助。即使和议不扶助代劳(如smtp和pop),那就只能在运用层以次代劳,也即传输层代劳。传输层代劳径直与tcp层交互,越发精巧。诉求代劳效劳器具备局部真实效劳器的功效:监听一定tcp或udp端口,接受存户端的乞求同声向存户端发出相映的相应。另一种代劳须要变换存户端的ip栈,即socks代劳。它是可用的最宏大、最精巧的代劳规范和议。sock v4承诺代劳效劳器里面的存户端实足地贯穿到外部的效劳器,sock v5减少了对存户端的受权和认证,所以它是一种安定性较高的代劳。本节反面引见的代劳是一种运用层上头的代劳,所代劳的和议是http,也即是经罕见到的web代劳。 正如上头所说,搜集代劳即是一个贯穿存户端(须要代劳的计划机)和效劳器端(供给考察资源的效劳器)的桥。要实行这种桥的功效,搜集代劳就必需满意下列前提,本来也是代劳效劳的运转的过程: (1)接受并领会存户端的乞求。 (2)创造到效劳器的新贯穿,并转发存户端的乞求消息。 (3)接受效劳器反应的消息。 (4)证明效劳器的相应并将该相应传回给存户端。 图1是搜集代劳效劳的一个典范模子图:
搜集代劳固然有很多便宜,但因为运用代劳后,本人对搜集的一切乞求都是经过代劳效劳器这个中央人来实行的,以是有大概碰上存有歹意的人监听你的输出的实质。同样,即使采用的代劳效劳器的带宽比拟小,运用代劳还会贬低网速。总之,运用代劳利于有弊,运用者要按照自己的情景来确定。但不管怎样,采用一个好的代劳效劳器利害常要害的。 三、c#实行web代劳效劳步调 过程了上头的引见,我想大师对代劳效劳该当有了一个基础的看法,底下就让咱们经过一个范例来深刻领会一下怎样用c#实行web代劳效劳。web代劳效劳的功效程序是如许的: (1)侦听端口,等候存户端欣赏器发送来的web乞求消息。 (2)接受到存户端web乞求消息后,领会出目的web效劳器的地方,并创造一个socket范例,并以此范例贯穿web效劳器上。 (3)经过创造的socket传递存户端的web乞求数据包到web效劳器的80端口。 (4)接受web效劳器归来的页面数据。 (5)把接受来的数据传递到存户端,进而实行web代劳。 存户端对某个web地方的欣赏,大概要传递很多的web乞求消息(比方网页中的图像、flash等),为了更快更精确地处置那些消息,web代劳效劳步调常常沿用多线程来处置每一个web乞求。经心的读者群大概会创造,处置每一个存户端的web乞求消息,代劳效劳器软硬件都要运用二个socket,一个是用来接受/传递存户机的消息,一个是和web效劳器举行交谈。为了辨别这二个socket,咱们把和效劳器对话的称为“效劳socket”,和存户端呆板对话的称为“存户socket”。 底下就发端web代劳效劳步调的编写处事。这个范例包括三个局部实质: 1.创造一个web代劳类。 2.web代劳效劳的类的范例化。 3.怎样经过这个web代劳类的范例实行web代劳效劳。 (一)创造一个web代劳类 简直操纵办法如次: 1.启用visual studio.net,顺序采用“文献”、“兴建”、“名目”菜单后,在弹出“兴建名目”对话框中将“名目典型”树立为“visual c#名目”,将“沙盘”树立为“windows运用步调”,在“称呼”文本框中输出“webproxy”,在“场所”文本框中输出“e:\vs.net名目”,而后单击“决定”按钮,如许名目便创造好了。 2.顺序采用菜单“名目”、“增添类”,将弹出“增添新项”对话框。 3.将“沙盘”树立为“类”。 4.在“称呼”文本框中输出“proxy”,单击“翻开”按钮,简直如图2所示: 5.在“处置计划资源处置器”窗口中,双击proxy.cs文献,加入proxy.cs文献的编纂界 6.在proxy.cs源文献的发端,增添下列代码,下列代码是导出proxy.cs中要运用到的定名空间: using system; using system.net; using system.net.sockets; using system.text; using system.io; 7.用下列结构因变量代替默许的结构因变量。底下的代码是在proxy类中创造一个结构因变量。proxy类惟有一个结构因变量,而且这个结构因变量惟有一个参数,这个参数是socket东西,它重要用来和存户端举行数据调换,是一个“存户socket”: public proxy(socket socket) { // // todo: 在此处增添结构因变量论理 // this.clientsocket = socket ; }
[page_break] 8.在设置proxy类代码区中介入下列代码,下列代码是设置proxy类中的运用的少许变量,那些变量主假如在反面的设置run本领中运用。 socket clientsocket; byte[] read = new byte[1024]; //设置一个空间,保存来自存户端乞求数据包 byte [] buffer = null; encoding ascii = encoding.ascii; //设定源代码 byte[] recvbytes = new byte[4096]; //设置一个空间,保存web效劳器归来的数据 9.创造proxy类中的run本领。run本领是proxy类中独一的本领。其功效是从存户端接受http乞求,并传递到web效劳器,而后从web效劳器接受反应来的数据,并传递到存户端。为了实行这二个各别上面的数据传递,run本领中是经过两个socket范例来实行的。在编写run本领的功夫,要提防底下零点: (1)因为http创造于tcp和议之上,以是创造的socket范例该当运用tcp和议。底下代码是创造不妨传递http乞求吩咐到web效劳器和接受来自web效劳器反应来消息的socket范例: socket ipsocket = new socket(addressfamily.internetwork, sockettype.stream, protocoltype.tcp); (2)其余一个socket是在代劳效劳步调侦听端标语,接受贯穿乞求功夫获得的,以是该当以此socket为参数,运用proxy类中的结构因变量来创造一个proxy范例。此socket实行从存户端接受http乞求消息,并传递数据到存户端。 socket创造和运用是实行web代劳软硬件的要害。在结构因变量代码反面,输出下列代码: public void run() { string clientmessage = " " ; //寄存来自存户端的http乞求字符串 string url = " " ; //寄存领会出地方乞求消息 int bytes = readmessage(read, ref clientsocket, ref clientmessage); if (bytes == 0) { return ; } int index1 = clientmessage.indexof(' '); int index2 = clientmessage.indexof(' ', index1 + 1); if ((index1 == -1) || (index2 == -1)) { throw new ioexception(); } string part1 = clientmessage.substring(index1 + 1, index2 - index1); int index3 = part1.indexof('/', index1 + 8); int index4 = part1.indexof(' ', index1 + 8); int index5 = index4 - index3; url = part1.substring(index1 + 4, (part1.length - index5) - 8); try { iphostentry iphost = dns.resolve(url); console.writeline("长途长机名: " + iphost.hostname); string [] aliases = iphost.aliases; ipaddress[] address = iphost.addresslist; console.writeline("web效劳器ip地方:" + address[0]); //领会出要考察的效劳器地方 ipendpoint ipendpoint = new ipendpoint(address[0], 80); socket ipsocket = new socket(addressfamily.internetwork, sockettype.stream, protocoltype.tcp); //创造贯穿web效劳器端的socket东西 ipsocket.connect(ipendpoint); //socket连web接效劳器 if (ipsocket.connected) console.writeline("socket 精确贯穿!"); string get = clientmessage; byte[] byteget = ascii.getbytes(get); ipsocket.send(byteget, byteget.length, 0); //代劳考察软硬件对效劳器端传递http乞求吩咐 int32 rbytes = ipsocket.receive(recvbytes, recvbytes.length, 0); //代劳考察软硬件接受来自web效劳器端的反应消息 console.writeline("接受字节数:" + rbytes.tostring()); string strretpage = null; strretpage = strretpage + ascii.getstring(recvbytes, 0, rbytes); while (rbytes > 0) { rbytes = ipsocket.receive(recvbytes, recvbytes.length, 0); strretpage = strretpage + ascii.getstring(recvbytes, 0, rbytes); } ipsocket.shutdown(socketshutdown.both); ipsocket.close(); sendmessage(clientsocket, strretpage); //代劳效劳软硬件往存户端传递接受到的消息 } catch (exception exc2) { console.writeline(exc2.tostring()); } } //接受存户端的http乞求数据 private int readmessage(byte [] bytearray, ref socket s, ref string clientmessage) { int bytes = s.receive(bytearray, 1024, 0); string messagefromclient = encoding.ascii.getstring(bytearray); clientmessage = (string)messagefromclient; return bytes; } //传递从web效劳器反应的数据到存户端 private void sendmessage(socket s, string message) { buffer = new byte[message.length + 1]; int length = ascii.getbytes(message, 0, message.length, buffer, 0); console.writeline("传递字节数:" + length.tostring()); s.send(buffer, length, 0); } 至此,proxy类的设置进程就实行了。