当前位置: 首页 > 图灵资讯 > 技术篇> 用Java实现多线程服务器程序

用Java实现多线程服务器程序

来源:图灵教育
时间:2024-02-21 10:21:13

  摘要: 在Java出现之前,编写多线程序是一件繁琐的事情,伴随着许多不安全因素。使用Java编写安全高效的多线程序变得简单,我们可以通过使用多线程和Java网络包轻松实现多线程服务器程序。 Java伴随着Internet的浪潮,对网络和多线程有内在的支持,具有网络时代编程语言的所有特点。从Java目前的应用来看,Java主要用于Internet或局域网上的网络编程,Java作为主流网络编程语言的趋势越来越明显。在实际工作中,除了使用商业服务器软件外,我们还经常需要根据实际环境编写自己的服务器软件,以完成特定的任务或与特定的客户端软件交互。我们在Java中应用了服务器程序,以提高程序运行效率,减少用户的等待时间。 多线程技术在Applet中很常见。 Java中的服务器程序和多线程 没有一种主流编程语言能够在Java之前为高级网络编程提供固有的支持。在其他语言环境中,网络程序的实现往往需要深入依赖于操作平台的网络API技术,Java提供完整的软件包,没有平台相关性的网络支持,因此程序员不需要担心系统网络支持的细节。 Java软件包内部支持的网络协议是TCP/IP,也是当今最流行的广域网/局域网协议。Java网络的类别和界面定义在Java.在net包中。javava通常用于客户软件.net包中的核心socket与服务器的某个端口建立连接,服务器程序不同于客户机。它需要初始化一个端口进行监控,并在与相应的客户机建立连接之前遇到连接呼叫。Java.ServerSocket类net包含了编写服务器系统所需的一切。以下是ServerSocket类的部分定义。 public class ServerSocket { public ServerSocket(int port) throws IOException ; public Socket accept() throws IOException ; public InetAddress getInetAddress() ; public int getLocalPort() ; public void close() throws IOException ; public synchronized void setSoTimeout (int timeout) throws SocketException ; public synchronized int getSoTimeout() throws IOException ; } ServerSocket结构器是服务器程序运行的基础,将参数port指定的端口初始化为服务器的端口,监控客户机的连接请求。Port的范围是0到65536,但0到1023是标准Internet协议保留端口,只有Rooot用户可以在Unix主机上使用。Port的范围是0到65536,但0到1023是标准Internet协议保留端口,只有Rooot用户可以在Unix主机上使用这些端口。一般来说,自定义的端口号在8000到16000之间。ServerSocket的初始化还远远不够。它没有与客户机交互的套接字(Socket),因此,需要调用这种accept方法接受客户呼叫。Accept()方法直到有连接请求才返回通信套接字(Socket)的实例。服务器可以通过这个例子的输入和输出流接收用户指令,并将相应的结果回应客户机。服务器的IP地址和端口可以通过Serversocket类的getinetadress和getlocalport获得。setsotimeout和getsotimeout方法分别是设置和获取服务器加班设置。如果服务器在timout设置时间内未获得accept方法返回的套接字实例,则抛出ioexception的异常。 Java的多线程可以说是Java编程的精髓之一。适当使用可以大大提高程序的响应时间和并行性。在服务器程序中,由于您经常需要同时接收不同客户机器的请求或命令,您可以生成每个客户机器请求的命令处理线程,并响应每个用户的指令。在一些复杂的系统中,我们还可以为每个数据库查询指令生成单独的线程,并行操作数据库。实践证明,采用多线程设计可以改善系统响应,保证用户指令执行的独立性。由于Java本身是“线程安全”的,因此有一个编程原则,即在一个线程中独立完成的操作应该打开一个新的线程。 Java中有两种方法可以实现线程。一种是生成Thread子类,并定义子类自己的run方法,在方法run中实现线程操作。然而,我们通常定义其他类别的子类,Java不允许多重继承,因此实现线程的第二种方法是实现Runnable接口。该线程的功能是通过覆盖Runnable接口中的Run方法来实现的。本例子采用第一种方法实现线程。 二、多线程服务器程序的例子 以下是我们在项目中使用的多线程服务器程序的架构,可以在此基础上扩展命令。本例不涉及数据库。如果在线程操作中需要根据用户指令更新数据库,则应注意线程之间的同步问题,使同一更新方法只能一次调用一个线程。这里有两个类别,receiveServer包含启动代码(main(),并初始化Serversocket的例子,在accept方法返回用户请求后,返回的套接字(Socket)将线程类serverthread交给生成的实例,直到用户结束连接。 ///类receiveservererver import java.io.*; import java.util.*; import java.net.*; public class receiveServer{ final int RECEIVE_PORT=9090; ////服务器的端口号 publiciceiveserver/ receiveServer() {ServerSocket rServer=null; ///ServerSocket的实例 Socket request=null; ////用户要求的套接字Thread receiveThread=null; try{ rServer=new ServerSocket(RECEIVE_PORT); ///初始化ServerSocketet System.out.println("Welcome to the server!"); System.out.println(new Date()); System.out.println("The server is ready!"); System.out.println("Port: "+RECEIVE_PORT); while(true){ //等待用户请求 request=rServer.accept(); ///接收客户机连接请求receivethreadadeaderead=new serverThread(request); ////生成serverthread的实例 receiveThread.start(); ///启动serverthread线程 } } catch(IOException e){ System.out.println(e.getMessage()) ; } } public static void main(String args[]){ new receiveServer(); } //end of main} //end of class//类serverthreadimporttport java.io.*; import java.net.*; class serverThread extends Thread {Socket clientRequest; ///用户连接的通信套接字Bufferedreader input; ///输入流PrintWriteriter output; //输出流 public serverThread(Socket s) { ///serverthread构造器 this.clientRequest=s; ///接收receiveserver传来的套接字 InputStreamReader reader; OutputStreamWriter writer; try{ ///初始化输入,输出流 reader=new InputStreamReader(clientRequest.getInputStream()); writer=new OutputStreamWriter(clientRequest.getOutputStream()); input=new BufferedReader(reader); output=new PrintWriter(writer,true); }catch(IOException e){ System.out.println(e.getMessage());} output.println("Welcome to the server!"); ///客户机连接欢迎词 output.println("Now is: "+new java.util.Date()+" "+ "Port:"+clientRequest.getLocalPort()); output.println("What can I do for you?"); } public void run(){ ///线程执行方法 String command=null; //用户指令 String str=null; boolean done=false; while(!done){ try{str=input.readLine(); ///接收客户机指令 }catch(IOException e){ System.out.println(e.getMessage());} command=str.trim().toUpperCase(); if(str==null