动态网站制作指南 [  QQ表情  ]
[ 投票调查 ]
[ 企业邮箱 ]
[ 网站空间 ]
网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
ASP源码 | .Net源码 | PHP源码 | JSP源码 | JAVA源码 | CGI源码 | VB源码 | C++源码 | Delphi源码 | PB源码 | VF源码 | 汇编 | 服务器
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > Java教程
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
文章搜索服务
邮件订阅
输入你的邮件地址,
你将不会错过任何关于:
[ Java教程 ]的信息

本月文章推荐
.有状态会话 bean运行结束时应及时.
.Struts初步知识.
.Java的字符串操作.
.关于Hibernate开发框架中的各个包.
.用J2SE1.5建立多任务的Java应用程.
.JavaI/OAPI之性能分析(上).
.在Web工程中实现任务计划调度.
.开天劈地:开发JAVA程序的新武器.
.PDA操作系统大比拼之一.
.Classworking 工具箱: .
.使用EclipseSWT控件开发WEB应用.
.StrutsVSTurbine.
.Happy New Year! 第一个XSP程序.
.JDK的命令详解(2).
.Win2000 Server下安装j2ee.
.SUN-JAVA技术在E-TRADE站点的应用.
.基于JDBC的数据库连接池高效管理.
.emf-sdo-xsd-SDK-2.0.1.
.Apache Geronimo 1.0 M3 Released.
.高级:使用异步Servlet扩展AJAX应.

菜鸟初学Java的备忘录(六)

发表日期:2008-1-5 |



通过程序建立了实际的概念之后,现在应该回到最开始的问题,Socket是什么?是实现计算机通信的一种方式,这毫无疑问.但如何能够用最轻易理解的语言比较形象而又不偏颇的描述它的原理呢?

BrUCe Eckel 在他的《Java 编程思想》一书中这样描述套接字:
套接字是一种软件抽象,用于表达两台机器之间的连接“终端”。对于一个给定的连接,每台机器上都有一个套接字,您也可以想象它们之间有一条虚拟的“电缆”,“电缆”的每一端都插入到套接字中。当然,机器之间的物理硬件和电缆连接都是完全未知的。抽象的全部目的是使我们无须知道不必知道的细节.

按我的理解,抽象点来说,一个Socket就是一个电话听筒,你有一个,和你通话的人也有一个,只不过其中有一个人的听筒叫ServerSocket,另一个人的听筒叫Socket.至于谁是ServerSocket,谁是Socket,这不重要,因为客户端和服务器端本来就是相对的,可以互相转化的.通话的两个人通过拿起两个听筒建立了一条通道,这条通道通不通就要看是不是双方都拿起听筒了,假如只有一方拿起听筒,那就只能听到一些嘟嘟的声音,证实通道不同.这里,拿起听筒的过程就是Socket初始化的过程.建立了通道之后,也就是大家都拿起听筒之后,通道两端的人就可以开始通话了.这里又有两个过程,即A对B说话,B接听,和B对A说话,A收听,这两个过程是通过两条线路完成的.传输在这两条线路上的,就是流.流隐藏了所有传输的细节,使得通信双方都认为,他们传过去的是声音,而不是编码.

前面写的服务器端的程序实际上是单任务版本,服务器对客户机的处理机制是在同一时间段内只能处理一个连接,因为handleConnection中采取的是不断循环的阻塞方法,检测到一个,就处理一个,然后再检测到一个,就再处理一个,假如有多个连接同时请求,那只能排队等候.这样的程序是无法在网络中应付多个连接的,因为你无法保证在同一时间内只有一个客户提出与服务器的连接请求,而用阻塞的方法应付多客户连接其速度之慢是可想而知的.

这样就催生了面向多连接的版本.显然,通过多线程可以来实现我们的要求.

由于要解决的是处理客户连接的问题,因此我们的工作只是在服务器端的程序当中修改.其原理不难推出,就是在检测到一个连接请求之后,马上建立一个线程去处理它,然后继续兼听下一个连接请求.所以,我们只需要将原来在handleConnection中的代码原封不动的放到线程的执行代码中,而在handleConnection中添加上新建线程的代码就可以了,十分简单.

同上一篇的风格一样,我们来观察各个部分的代码细节.
首先为这个多线程的版本创建类MultiThreadRemoteFileServer

看看这个类的定义
import java.io.*;
import java.net.*;

public class MultiThreadRemoteFileServer{
protected int listenPort;
public MultiThreadRemoteFileServer(int aListenPort){
}
public static void main(String[] args) {
}
public void acceptConnections() {
}
public void handleConnection(Socket incomingConnection) {
}
}

几乎和RemoteFileServer是一样的,唯一的区别是在我们现在创建的这个类中增加了一个构造函数,这是为了能够使得监听的端口号由我们自己来定.定义如下

public MultithreadedRemoteFileServer(int aListenPort) {
listenPort = aListenPort;
}

先来看main()
public static void main(String[] args) {
MultithreadedRemoteFileServer server = new MultithreadedRemoteFileServer(3000);
server.acceptConnections();
}

没有区别吧,和RemoteFileServer的main()函数,只是端口号在创建的时候由主程序指定而已。

我们主要关心的改动都在后面
现在看acceptConnection监听程序
public void acceptConnections() {
try {
ServerSocket server = new ServerSocket(listenPort, 5);//注重到没有,建立服务器Socket的时候多了一个参数,这个参数是用来指定能够同时申请连接的最大数目,缺省值是50
Socket incomingConnection = null;
while (true) {
incomingConnection = server.accept();
handleConnection(incomingConnection);
}
} catch (BindException e) {
System.out.println("Unable to bind to port " + listenPort);
} catch (IOException e) {
System.out.println("Unable to instantiate a ServerSocket on port: " + listenPort);
}
}

改动的地方就一个,多了个参数.这里是它的工作机制。假设我们指定待发数(backlog 值)是5并且有五台客户机请求连接到我们的服务器。我们的服务器将着手处理第一个连接,但处理该连接需要很长时间。由于我们的待发值是 5,所以我们一次可以放五个请求到队列中。我们正在处理一个,所以这意味着还有其它五个正在等待。等待的和正在处理的一共有六个。当我们的服务器仍忙于接受一号连接(记住队列中还有 2?6 号)时,假如有第七个客户机提出连接申请,那么,该第七个客户机将遭到拒绝

接着看,我们的下一个改动显然是在处理监听到的线程的方法handleConnection中,前面已经说了,在多线程的版本中,我们检测到一个连接请求,就马上生成一个线程,然后就不用理它了,那么在这里就是新建线程的一句话.

public void handleConnection(Socket connectionToHandle) {
new Thread(new ConnectionHandler(connectionToHandle)).start();
}

我们注重到有一个新的类ConnectionHandler,这个类是Runnable的,即是一个接口类(这是用接口实现的一个线程,要是有不明白的话,可以去看看17号的关于线程的东西).我们用 ConnectionHandler 创建一个新 Thread 并启动它。正如我们刚才所说的,原来在RemoteFileServer的handleConnection中的代码统统原封不动的转移到了这个接口类ConnectionHandler的run()方法中来了.

那么我们来看看整个ConnectionHandler类的定义吧。

class ConnectionHandler implements Runnable {
protected Socket socketToHandle;
public ConnectionHandler(Socket aSocketToHandle) {
socketToHandle = aSocketToHandle;//通过构造函数,将待处理的Socket实例作为参数传送进来
}
public void run() {//原来对Socket的读/写的代码都在这里了
try {
PrintWriter streamWriter = new PrintWriter(socketToHandle.getOutputStream());
BufferedReader streamReader = new BufferedReader(new InputStreamReader(socketToHandle.getInputStream()));

String fileToRead = streamReader.readLine();
BufferedReader fileReader = new BufferedReader(new FileReader(fileToRead));

String line = null;
while ((line = fileReader.readLine()) != null)
streamWriter.println(line);

fileReader.close();
streamWriter.close();
streamReader.close();
} catch (Exception e) {
System.out.println("Error handling a client: " + e);
}
}
}

ConnectionHandler 的 run() 方法所做的事情就是 RemoteFileServer 上的 handleConnection() 所做的事情。首先把 InputStream 和 OutputStream 分别包装(用 Socket 的 getOutputStream() 和 getInputStream())进 BufferedReader 和 PrintWriter。然后我们用这些代码逐行地读目标文件.由于InputStream中装的是文件路径,所以中间还需要使用FileReader流将文件路径包装,再经由BufferedReader包装读出.

我们的多线程服务器研究完了,同样,我们回顾一下创建和使用“多线程版”的服务器的步骤:

1.修改 acceptConnections() 以用缺省为 50(或任何您想要的大于 1 的指定数字)实例化 ServerSocket。

2. 修改 ServerSocket 的 handleConnection() 以用 ConnectionHandler 的一个实例生成一个新的 Thread。

3.借用 RemoteFileServer 的 handleConnection() 方法的代码实现 ConnectionHandler 类的run()函数。
上一篇:struts构建文件上传(八) 人气:767
下一篇:struts构建文件上传(九) 人气:856
浏览全部Java的内容 Dreamweaver插件下载 常用网页广告代码全集
  最新网站源码 最新软件下载
2008-8-21 Nucleus v3.33 多国语言版
2008-8-21 HDWiki v4.0 bulid 080821 UTF-8
2008-8-21 明科在线客服系统 v6.0
2008-8-21 KesionCMS v5.0.2 正式版 utf-8
2008-8-21 KesionEshop v5.0.2 正式版 utf-8
2008-8-21 HDWiki v4.0 bulid 080821 GBK
2008-8-21 新文互动酷站展示系统 v1.5
2008-8-21 Punbb v1.2.20 多国语言版
2008-8-21 QQ头像网 beta
2008-8-16 iLaba Player(小喇叭播放器) v2.
2008-8-16 DoubleClickFix 鼠标双击修正工具
2008-8-16 CrystalCPUID 4.15.2.451
2008-8-16 VeryCD 电驴(easyMule) 1.0.4 Bu
2008-8-16 uTorrent 1.8 Build 11813 - Sta
2008-8-16 比特精灵(BitSpirit) v3.3.2.287
2008-8-16 StayInTune音叉 v1.0 破解版
2008-8-16 iChing《周易》汉化补丁 v1.0
2008-8-16 Starmap星空图v1.0汉化破解版
  发表评论
姓 名: 验证码:
内 容:
[ 汉字翻译拼音 ] [ 广告代码 ] [ 符号对照表 ] [ 进制转换 ] [ 经典小工具 ] [ 个税计算 ] [ 汉字简繁转换 ] [ 普通单位换算 ] [ 公制单位换算 ]
[ 生辰老黄历 ] [ 国内电话区号 ] [ 国家代码与域名缩写 ] [ 文字加密解密 ] [ 健康查询 ] [ 万年历 ] [ 手机号码查询 ] [ ip搜索 ] [ Google PR查询 ]
业务联系 | 广告刊登 | 频道合作 | 投稿荐稿 | 联系方式 | 加入收藏 | RSS订阅
Copyright © 2000-2008 www.knowsky.com All rights reserved | 网络实名:动态网站制作指南 | 沪ICP备05001343号