end; end else begin host:=trim(line);{获取主机地址} port:=80; end; if not session[i-1].remote_connected then{假如远征尚未连接} begin session[i-1].Request:=true;{置请求数据就绪标志} session[i-1].CSocket.host:=host;{设置远程主机地址} session[i-1].CSocket.port:=port;{设置端口} session[i-1].CSocket.active:=true;{连接远程主机} session[i-1].Lookingup:=true;{置标志} session[i-1].LookupTime:=0;{从0开始计时} end else {假如远程已连接,直接发送请求} session[i-1].CSocket.socket.sendtext(session[i-1].request_str); break;{停止扫描请求文本} end; j:=pos(char(13)+char(10),tmp);{指向下一行} end; break;{停止循环} end; //当连接远程主机成功时 procedure TForm1.ClientSocket1Connect(Sender: TObject;Socket: TCustomWinSocket); var i: integer; begin for i:=1 to sessions do if (session[i-1].CSocket.socket.sockethandle= socket.SocketHandle)and session[i-1].Used < BR> then begin session[i-1].CSocket.tag:=socket.SocketHandle; session[i-1].remote_connected:=true;{置远程主机已连通标志} session[i-1].Lookingup:=false;{清标志} break; end; end; //当远程主机断开时 procedure TForm1.ClientSocket1Disconnect(Sender: TObject; Socket: TCustomWinSocket); var i,j,k: integer; begin for i:=1 to sessions do if (session[i-1].CSocket.tag=socket.SocketHandle) and session[i-1].Used then begin session[i-1].remote_connected:=false;{置为未连接} if not session[i-1].client_connected then session[i-1].Used:=false{假如客户机已断开,则置释放资源标志} else for k:=1 to serversocket1.Socket.ActiveConnections do if (serversocket1.Socket.Connections[k-1].SocketHandle=session[i-1].SS_Handle) and session[i-1].used then begin serversocket1.Socket.Connections[k-1].Close; break; end; break; end; j:=sessions; k:=0; for i:= 1 to j do begin if session[j-i].Used then break; inc(k); end; if k>0 then{修正会话数组} begin sessions:=sessions-k; setlength(session,sessions); end; edit1.text:=inttostr(sessions); end; file://当与远程主机通信发生错误时/ procedure TForm1.ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer); var i,j,k: integer; begin for i:=1 to sessions do if (session[i-1].CSocket.tag=socket.SocketHandle) and session[i-1].Used then begin socket.close; session[i-1].remote_connected:=false;{置为未连接} if not session[i-1].client_connected then session[i-1].Used:= false{假如客户机已断开,则置释放资源标志} else for k:=1 to serversocket1.Socket.ActiveConnections do if (serversocket1.Socket.Connections[k-1].SocketHandle=session[i-1].SS_Handle) and session[i-1].used then begin serversocket1.Socket.Connections[k-1].Close; break; end; break; end; j:= sessions; k:= 0; for i:= 1 to j do begin if session[j-i].Used then break; inc(k); end; errorcode:= 0; if k>0 then{修正会话数组} begin sessions:=sessions-k; setlength(session,sessions); end; edit1.text:= inttostr(sessions); end; //向远程主机发送页面请求 procedure TForm1.ClientSocket1Write(Sender: TObject; Socket:TCustomWinSocket); var i: integer; begin for i:= 1 to sessions do if (session[i-1].CSocket.tag= socket.SocketHandle) and session[i-1].Used then begin if session[i-1].Request then begin socket.SendText(session[i-1].request_str);{假如有请求,发送} session[i-1].Request:= false;{清标志} end; break; end; end; //远程主机发来页面数据时 procedure TForm1.ClientSocket1Read(Sender: TObject;Socket: TCustomWinSocket); var i,j: integer; rec_bytes: integer;{传回的数据块长度} rec_Buffer: array[0..2047] of char; {传回的数据块缓冲区} begin for i:= 1 to sessions do if (session[i-1].CSocket.tag= socket.SocketHandle) and session[i-1].Used then begin rec_bytes:= socket.ReceiveBuf(rec_buffer,2048); {接收数据} for j:= 1 to serversocket1.Socket.ActiveConnections do if serversocket1.Socket.Connections[j-1].SocketHandle= session[i-1].SS_Handle then begin serversocket1.Socket.Connections[j-1].SendBuf(rec_buffer,rec_bytes); {发送数据} break; end; break; end; end; //“页面找不到”等错误信息出现时 procedure TForm1.AppException(Sender:TObject; E: Exception); begin inc(invalidrequests); end; file://查找远程主机定时/ procedure TForm1.Timer1Timer(Sender: TObject); var i,j: integer; begin for i:= 1 to sessions do if session[i-1].Used and session[i-1].Lookingup then{假如正在连接} begin inc(session[i-1].LookupTime); if session[i-1].LookupTime > lookuptimeout then{假如超时} begin session[i-1].Lookingup:=false; session[i-1].CSocket.active:=false;{停止查找} for j:=1 to serversocket1.Socket.ActiveConnections do if serversocket1.Socket.Connections[j-1].SocketHandle=session[i-1].SS_Handle then begin serversocket1.Socket.Connections[j-1].Close;{断开客户机} break; end; end; end; end; end. 三、总结 由于这种设计思路仅仅在被代理端和远程主机之间增加了一个重定向功能,被代理端原有的缓存技术等特点均保留,因此效率较高。经过测试,利用1个33.6K的Modem上网时,三到十个被代理工作站同时上网,仍有较好的响应速度。由于被代理工作站和代理服务器之间的连接一般通过高速链路,因此瓶颈主要出现在代理服务器的上网方式上。 通过上述方法,作者成功开发了一套完善的代理服务器软件并与机房计费系统完全集成,实现了利用一台工作站完成上网代理、上网计费、用机计费等功能。 有编程经验的朋友完全可以另行增加代理服务器功能,如设定禁止访问站点、统计客户流量、Web访问列表等等。