java套接字(socket)多线程例子_第1页
java套接字(socket)多线程例子_第2页
java套接字(socket)多线程例子_第3页
java套接字(socket)多线程例子_第4页
java套接字(socket)多线程例子_第5页
全文预览已结束

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

一个多线程的示例 1. 介绍 前面的示例教给您基础知识,但并不能令您更深入。如果您到此就停止了,那么您一次只能处理一台客户 机。原因是 handleConnection() 是一个阻塞方法。只有当它完成了对当前连接的处理时,服务器才能接受 另一个客户机。在多数时候,您将需要(也有必要)一个多线程服务器。 要开始同时处理多台客户机,并不需要对 RemoteFileServer 作太多改变。事实上,要是我们前面讨论过 待发(backlog) ,那我们就只需改变一个方法,虽然我们将需要创建一些新东西来处理进入的连接。这里 我们还将向您展示 ServerSocket 如何处理众多等待(备份)使用服务器的客户机。本示例对线程的低效 使用,所以请耐心点。 2. 接受(太多)连接 这里我们实现改动过的 acceptConnections() 方法,它将创建一个能够处理待发请求的 ServerSocket,并告 诉 ServerSocket 接受连接: Java 代码 1. public void acceptConnections() 2. try 3. ServerSocket server = new ServerSocket(listenPort, 5); 4. Socket incomingConnection = null; 5. while (true) 6. incomingConnection = server.accept(); 7. handleConnection(incomingConnection); 8. 9. catch (BindException e) 10. System.out.println(“Unable to bind to port “ + listenPort); 11. catch (IOException e) 12. System.out.println(“Unable to instantiate a ServerSocket on port: “ + listenPort); 13. 14. 新的 server 仍然需要 acceptConnections(),所以这些代码实际上是一样的。突出显示的行表示一个重 大的不同。对这个多线程版,我们现在可以指定客户机请求的最大数目,这些请求都能在实例化 ServerSocket 期间处于待发状态。如果我们没有指定客户机请求的最大数目,则我们假设使用缺省值 50。 这里是它的工作机制。假设我们指定待发数(backlog 值)是 5 并且有五台客户机请求连接到我们的服 务器。我们的服务器将着手处理第一个连接,但处理该连接需要很长时间。由于我们的待发值是 5,所以 我们一次可以放五个请求到队列中。我们正在处理一个,所以这意味着还有其它五个正在等待。等待的和 正在处理的一共有六个。当我们的服务器仍忙于接受一号连接(记住队列中还有 26 号)时,如果有第 七个客户机提出连接申请,那么,该第七个客户机将遭到拒绝。我们将在带有连接池服务器示例中说明如 何限定能同时连接的客户机数目。 3. 处理连接:第 1 部分 这里我们将讨论 handleConnection() 方法的结构,这个方法生成一个新的 Thread 来处理每个连接。我 们将分两部分讨论这个问题。这一屏我们将着重该方法本身,然后在下一屏研究该方法所使用的 ConnectionHandler 助手类的结构。 Java 代码 1. public void handleConnection(Socket connectionToHandle) 2. new Thread(new ConnectionHandler(connectionToHandle).start(); 3. 我们对 RemoteFileServer 所做的大改动就体现在这个方法上。我们仍然在服务器接受一个连接之后调用 handleConnection(),但现在我们把该 Socket 传递给 ConnectionHandler 的一个实例,它是 Runnable 的。 我们用 ConnectionHandler 创建一个新 Thread 并启动它。ConnectionHandler 的 run() 方法包含 Socket 读写和读 File 的代码,这些代码原来在 RemoteFileServer 的 handleConnection() 中。 4. 处理连接:第 2 部分 这里是 ConnectionHandler 类的结构: Java 代码 1. import java.io.*; 2. import .*; 3. 4. public class ConnectionHandler implements Runnable 5. Socket socketToHandle; 6. 7. public ConnectionHandler(Socket aSocketToHandle) 8. socketToHandle = aSocketToHandle; 9. 10. 11. public void run() 12. 13. 这个助手类相当简单。跟我们到目前为止的其它类一样,我们导入 和 java.io。该类只有一个实 例变量 socketToHandle,它保存由该实例处理的 Socket。 类的构造器用一个 Socket 实例作参数并将它赋给 socketToHandle。 请注意该类实现了 Runnable 接口。实现这个接口的类都必须实现 run() 方法,我们的类就是这样做的。 稍后我们将探究 run() 的细节。现在只需知道它将实际处理连接,所用的代码跟我们先前在 RemoteFileServer 类中看到的是一样的。 5. 实现 run() 这里我们实现 run() 方法,它将攫取我们的连接的流,用它来读写该连接,并在任务完成之后关闭它: Java 代码 1. public void run() 2. try 杭州 java 软件培训 杭州网络营销培训 3. PrintWriter streamWriter = new PrintWriter(socketToHandle.getOutputStream(); 4. BufferedReader streamReader = 5. new BufferedReader(new InputStreamReader(socketToHandle.getInputStream(); 6. 7. String fileToRead = streamReader.readLine(); 8. BufferedReader fileReader = new BufferedReader(new FileReader(fileToRead); 9. 10. String line = null; 11. while (line = fileReader.readLine() != null) 12. streamWriter.println(line); 13. 14. fileReader.close(); 15. streamWriter.close(); 16. streamReader.close(); 17. catch (Exception e) 18. System.out.println(“Error handling a client: “ + e); 19. 20. 复制 打印 1. ConnectionHandler 的 run() 方法所做的事情就是 RemoteFileServer 上的 handleConnection() 所做的事情。 首先,我们把 InputStream 和 OutputStream 分别包装(用 Socket 的 getOutputStream() 和 getInputStream())进 BufferedReader 和 PrintWriter。然后我们用这些代码逐行地读目标文件: Java 代码 1. FileReader fileReader = new FileReader(new File(streamReader.readLine(); 2. BufferedReader bufferedFileReader = new BufferedReader(fileReader); 3. String line = null; 4. while (line = bufferedFileReader.readLine() != null) 5. streamWriter.println(line); 6. 请记住我们应该从客户机获取一条有效的文件路径,这样用该路径名构造一个新 File,把它包装进 FileReader 以处理读文件的操作,然后把它包装进 BufferedReader 以让我们逐行地读该文件。我们在 while 循环中调用 BufferedReader 上的 readLine() 直到不再有要读的行。请记注,对 readLine() 的调用 将造成阻塞,直到有字节来到为止。我们获取一些字节之后就把它们放到本地的 line 变量中,然后写出 到客户机上。完成读写操作之后,我们关闭打开的流。 6. 总结一下多线程服务器 我们的多线程服务器研究完了。在我们接着讨论带有连接池示例之前,让我们回顾一下创建和使用“多线 程版”的服务器的步骤: 修改 acceptConnections() 以用缺省为 50(或任何您想要的大于 1 的指定数字)实例化 ServerSocket。 修改 ServerSocket 的 handleConnection() 以用 ConnectionHandler 的一个实例生成一个新的 Thread。 借用 RemoteFileServer 的 handleConnection() 方法的代码实现 ConnectionHandler 类。 附: MultithreadedRemoteFileServer 的完整代码清单 Java 代码 1. import java.io.*; 2. import .*; 3. 4. public class MultithreadedRemoteFileServer 5. protected int listenPort; 6. public MultithreadedRemoteFileServer(int aListenPort) 7. listenPort = aListenPort; 8. 9. public void acceptConnections() 10. try 11. ServerSocket server = new ServerSocket(listenPort, 5); 12. Socket incomingConnection = null; 13. while (true) 14. incomingConnection = server.accept(); 15. handleConnection(incomingConnection); 16. 17. catch (BindException e) 18. System.out.println(“Unable to bind to port “ + listenPort); 19. catch (IOException e) 20. System.out.println(“Unable to instantiate a ServerSocket on port: “ + listenPort); 21. 22. 23. public void handleConnection(Socket connectionToHandle) 24. new Thread(new ConnectionHandler(connectionToHandle).start(); 25. 26. public static void main(String args) 27. MultithreadedRemoteFileServer server = new MultithreadedRemoteFileServer(3000); 28. server.acceptConnections(); 29. 30. ConnectionHandler 的完整代码清单 Java 代码 1. import java.io.*; 2. import .*; 3. 4. public class ConnectionHandler implements Runnable 5. protected Socket socketToHandle; 6. public ConnectionHandler(Socket aSocketToHandle) 7. socketToHandle = aSocketToHandle; 8. 9. public void run() 10. try 杭州 java 软件培训 杭州网络营销培训 www.hzbe

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论