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

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

来源:图灵教育
时间:2024-03-03 10:37:20

  在Java出现之前,编写多线程序是一件繁琐的事情,伴随着许多不安全因素。使用Java编写安全高效的多线程序变得简单,我们可以通过使用多线程和Java网络包轻松实现多线程服务器程序。

  ----Java伴随着Internet的潮流,对网络和多线程有内在的支持,具有网络时代编程语言的所有特点。从Java的当前应用来看,Java主要用于Internet或局域网上的网络编程,Java作为主流网络编程语言的趋势越来越明显。在实践中,除了使用商业服务器软件外,我们还经常需要根据实际环境编写自己的服务器软件,以完成特定的任务或与特定的客户端软件交互。在实现服务器程序时,为了提高程序运行效率,减少用户等待时间,我们应用了Javaplet中常见的多线程技术。

  ----Java中的服务器程序和多线程 ----在Java之前,没有一种主流的编程语言能够为先进的网络编程提供固有的支持。在其他语言环境中,网络程序的实现往往需要依赖于操作平台的网络API技术,Java提供完整的软件包,没有平台相关性的网络支持,因此程序员不需要担心系统网络支持的细节。

  ----Java软件包内部支持的网络协议是TCP/IP,也是当今最流行的广域网/局域网协议。Java网络的类别和界面定义在Java.在net包中。java通常用于客户端软件.net包中的核心socket与服务器的某个端口建立连接,服务器程序不同于客户机。它需要初始化一个端口进行监控,并在与相应的客户机建立连接之前遇到连接呼叫。Java.net包的ServerSocket类包含了编写服务器系统所需的一切。以下是ServerSocket类的部分定义。 publicclassServerSocket{ publicServerSocket(intport) throwsIOException; publicSocketaccept()throwsIOException; publicInetAddressgetInetAddress(); publicintgetLocalPort(); publicvoidclose()throwsIOException; publicsynchronizedvoidsetSoTimeout (inttimeout)throwsSocketException; publicsynchronizedint getSoTimeout()throwsIOException; }

  ----Serversocket结构器是服务器程序运行的基础。它将参数port指定的端口初始化为服务器的端口,并监控客户机器的连接请求。port的范围是0到6536,但0到1023是标准的internet协议保留端口,只有rooot用户可以在unix主机上使用。一般来说,自定义的端口号在8000到16000之间。仅仅初始化serversocket还远远不够。它没有与客户机交互的套接字(Socket),因此,需要调用这种accept方法接受客户呼叫。Accept()方法直到有连接请求才返回通信套接字(Socket)例子。通过这个例子的输入输出流,服务器可以接收用户指令,并将相应的结果回应客户机。Serversocket类的getinetadress和getlocalport方法可以获得服务器的IP地址和端口。setsotimeout和getsotimeout方法分别设置和超时设置服务器。如果服务器在timout设置时间内未获得accept方法返回的套接字实例,则抛出ioexception的异常。 ----Java的多线程可以说是Java编程的本质之一。适当的应用可以大大提高程序的响应时间和程序的并行性。在服务器程序中,由于您经常需要同时接收不同的客户机器的请求或命令,您可以生成每个客户机器的请求的命令处理线程,并响应每个用户的指令。在一些更复杂的系统中,我们还可以为每个数据库查询指令生成一个单独的线程,并行操作数据库。实践证明,多线程设计可以改善系统的响应,确保用户指令执行的独立性。由于Java本身是“线程安全”的 ----Java中有两种方法可以实现线程。一种是生成Thread子类,并定义子类自己的run方法。线程操作在方法run中实现。然而,我们通常定义其他子类,Java不允许多重继承。因此,实现线程的第二种方法是实现runnable接口。该线程的功能是通过覆盖runable接口中的run来实现的。本例采用第一种方法实现线程。

  ----多线程服务器程序的例子 ----以下是我们在项目中使用的多线程服务器程序的架构,可以在此基础上扩展命令。这个例子不涉及数据库。如果数据库需要根据用户指令在线程操作中更新,则应注意线程之间的同步,以便同一更新方法一次只能通过一个线程调用。这里有两个类别。receiveserver包含启动代码(main(),并在accept方法返回用户请求后,初始化ServerSocket的例子,将返回的套接字返回(Socket)将线程类serverthread交给生成的实例,直到用户结束连接。 ///类receiveservererver importjava.io.*; importjava.util.*; importjava.net.*; publicclassreceiveServer{ finalintRECEIVE_PORT=9090; ////服务器的端口号 ////receiveserver结构器 publicreceiveServer(){ ServerSocketrServer=null; ///ServerSocket的实例 Socketrequest=null; /////用户要求的套接字 ThreadreceiveThread=null; try{ rServer=newServerSocket(RECEIVE_PORT); ///初始化ServerSocketet System.out.println("Welcometotheserver!"); System.out.println(newDate()); System.out.println("Theserverisready!"); System.out.println("Port:"+RECEIVE_PORT); while(true){ //等待用户请求 request=rServer.accept(); ////接收客户机连接请求 receiveThread=newserverThread(request); ////生成serverthread的实例 receiveThread.start(); ///启动serverthread线程 } }catch(IOExceptione){ System.out.println(e.getMessage());} } publicstaticvoidmain(Stringargs[]){ newreceiveServer(); }//endofmain }//endofclass ///类型serverthredaddaddader importjava.io.*; importjava.net.*; classserverThreadextendsThread{ SocketclientRequest; /////用户连接的通信套接字 BufferedReaderinput;//输入流 PrintWriteroutput; //输出流 publicserverThread(Sockets) {//serverthread构造器 this.clientRequest=s; ///接收receiveserver传来的套接字 InputStreamReaderreader; OutputStreamWriterwriter; try{ ///初始化输入,输出流 reader=newInputStreamReader (clientRequest.getInputStream()); writer=newOutputStreamWriter (clientRequest.getOutputStream()); input=newBufferedReader(reader); output=newPrintWriter(writer,true); }catch(IOExceptione){ System.out.println(e.getMessage());} output.println("Welcometotheserver!"); ///客户机连接欢迎词 output.println("Nowis: "+newjava.util.Date()+""+ "Port:"+clientRequest.getLocalPort()); output.println("WhatcanIdoforyou?"); } publicvoidrun(){///线程执行方法 Stringcommand=null;//用户指令 Stringstr=null; booleandone=false; while(!done){ try{ str=input.readLine();//接收客户机指令 }catch(IOExceptione){ System.out.println(e.getMessage());} command=str.trim().toUpperCase(); if(str==null ||command.equals("QUIT")) ///命令quit结束连接 done=true; elseif(command.equals("HELP")){ ///命令help查询服务器可接受的命令 output.println("query"); output.println("quit"); output.println("help"); } elseif(command.startsWith("QUERY")) {//命令queryy output.println("OKtoquerysomething!"); } //elseif……..///可以在此添加服务器的其他指令 elseif(!"); } //elseif……..///可以在此添加服务器的其他指令 elseif(!command.startsWith("HELP")&& !command.startsWith("QUIT")&& !command.startsWith("QUERY")){ output.println("CommandnotFound! PleaserefertotheHELP!"); } }//endofwhile try{ clientRequest.close(); ///关闭套接字 }catch(IOExceptione){ System.out.println(e.getMessage()); } command=null; }//endofrun ----服务器程序启动后,可以通过telnetmachineport命令连接,其中machine是本机的名称或地址,port是程序中指定的端口。还可以通过TCP的Socket套接字编写特定的客户机软件。