1、5:36第第1页页 JavaJava网络程序网络程序设计基础设计基础5:36第第2页页了解端口、套接字等网络程序常用专有名词了解端口、套接字等网络程序常用专有名词的意义的意义了解了解TCP/IPTCP/IP与与UDPUDP等网络协议的数据传递方等网络协议的数据传递方式式了解了解JavaJava语言中的常用数据流语言中的常用数据流掌握客服掌握客服/ /服务服务SocketSocket通信的流程通信的流程掌握多线程与其他程序的结合掌握多线程与其他程序的结合5:36第第3页页1.1.SocketSocket编程常用专有名字编程常用专有名字2.2.TCP/IPTCP/IP与与UDPUDP通信比较通信比
2、较3.3.客服客服/ /服务服务SocketSocket通信程序设计通信程序设计4.4.编写多线程的客户编写多线程的客户/ /服务程序服务程序5:36第第4页页 信息在一个进程的信息在一个进程的Socket和另一个进程的和另一个进程的Socket间,以报文传输的形式进行交换。间,以报文传输的形式进行交换。 发送端发送端Socket,报文以队列的形式等待,直报文以队列的形式等待,直到网络协议传输它们。当报文到达后,又在接收到网络协议传输它们。当报文到达后,又在接收端的端的Socket排队,等待接收进程以一定的系统排队,等待接收进程以一定的系统调用来接收它们。调用来接收它们。 在客户服务模式下,服
3、务器是监听请求的在客户服务模式下,服务器是监听请求的进程,客户是发送请求的进程。一旦服务器进程进程,客户是发送请求的进程。一旦服务器进程接收到了请求,它就试图去处理该请求,并且将接收到了请求,它就试图去处理该请求,并且将输出发送给客户。输出发送给客户。5:36第第5页页 Socket(套接字套接字)就是就是进程之间通信的抽进程之间通信的抽象连接点象连接点。 要理解这个概念,以现代生活举例,电要理解这个概念,以现代生活举例,电话是人们联系的常用方法,双方只要使用话是人们联系的常用方法,双方只要使用两部电话机就可以交谈。那么在计算机通两部电话机就可以交谈。那么在计算机通信中,两个程序就是使用信中,
4、两个程序就是使用Socket进行通信进行通信的,一个的,一个Socket就好比一部电话机,两个就好比一部电话机,两个程序通过一个双向链路进行通信,这个双程序通过一个双向链路进行通信,这个双向链路的每一端就成为一个向链路的每一端就成为一个Socket。5:36第第6页页 在在TCPIP协议的传输层提供了有关协议的传输层提供了有关Socket的各种调用,目的是在这个协议层的各种调用,目的是在这个协议层上实现网络进程之间的通信。上实现网络进程之间的通信。 进程之间要通信,首先要建立各自的进程之间要通信,首先要建立各自的Socket,就像要打电话一定要先有电话机就像要打电话一定要先有电话机一样,一样,
5、当电话通过当电话通过中间服务器中间服务器接通时接通时,每,每部电话机都可以说和听。与此类似,每个部电话机都可以说和听。与此类似,每个Socket也都可以进行读操作和写操作,进也都可以进行读操作和写操作,进行读行读/写操作时分别要用到写操作时分别要用到Socket中的输入中的输入流和输出流。流和输出流。5:36第第7页页 有些时候,一个有些时候,一个IP地址并不足以完整地址并不足以完整标识一个服务器。这是由于在一台物理主标识一个服务器。这是由于在一台物理主机中通常运行着多个服务器机中通常运行着多个服务器(程序程序)。由。由IP表表达的每台机器也包含了达的每台机器也包含了“端口端口”(Port)。
6、)。 端口是一个逻辑概念。主机上每一个提端口是一个逻辑概念。主机上每一个提供服务的程序都运行在该主机的一个对外供服务的程序都运行在该主机的一个对外开放的端口上。端口与使用该端口的服务开放的端口上。端口与使用该端口的服务进程是对应的。进程是对应的。5:36第第8页页 当设置一个客户机或者服务器的时候,当设置一个客户机或者服务器的时候,必须选择一个无论客户机还是服务器都认必须选择一个无论客户机还是服务器都认可连接的端口。可连接的端口。 就像我们去拜会某人时,就像我们去拜会某人时,IP地址是他居地址是他居住的房子,而端口是他在的那个房间。住的房子,而端口是他在的那个房间。 程序员可以在程序员可以在创
7、建自己的服务器程序创建自己的服务器程序时时使用使用自定义的端口自定义的端口(除了系统默认的端口和除了系统默认的端口和已占用的端口已占用的端口)。系统服务保留了使用端口。系统服务保留了使用端口1到端口到端口1024的权力。的权力。5:36第第9页页 ServerSocket会在主机上创建一个物会在主机上创建一个物理性的理性的“服务器服务器”或者侦听用的套接字,或者侦听用的套接字,服务器用它服务器用它“侦听侦听”进入的连接,一旦客进入的连接,一旦客户户(程序)申请建立一个套接字连接,程序)申请建立一个套接字连接,ServerSocket就就(利用利用accept()方法方法),会,会返回一个对应的
8、服务端套接字,以便进行返回一个对应的服务端套接字,以便进行直接通信。从此时起,我们就得到了真正直接通信。从此时起,我们就得到了真正的的“套接字一套接字套接字一套接字”连接,可以用同样连接,可以用同样的方式对待两端的连接。的方式对待两端的连接。5:36第第10页页 创建一个创建一个ServerSocket时,只需为其时,只需为其赋予一个端口编号。不必把一个赋予一个端口编号。不必把一个IP地址分地址分配给他,因为它已经在自己代表的那台机配给他,因为它已经在自己代表的那台机器上了。器上了。 但在创建一个但在创建一个Socket时,却必须同时时,却必须同时赋予赋予IP地址以及要连接的端口编号。地址以及
9、要连接的端口编号。(特指特指客户端客户端Socket,因为服务端通过因为服务端通过ServerSocket.accept()返回的返回的Socket对对象已经包含了这些相关信息象已经包含了这些相关信息)。5:36第第11页页 对于对于Socket程序,可以使用两种通信程序,可以使用两种通信协议:数据报通信协议:数据报通信(Datagram Communication)协议和流通信协议和流通信(Stream Communication)协议。它们都被协议。它们都被Java所所支持。支持。 数据报通信协议,如数据报通信协议,如UDP,为无连接协为无连接协议,可以在任何时候发送数据包。议,可以在任何
10、时候发送数据包。5:36第第12页页 流通信协议最广为人知的如流通信协议最广为人知的如TCP协议。协议。它与它与UDP不同,不同,TCP是一个面向连接的协是一个面向连接的协议。议。 为了使用为了使用TCP协议进行通信,必须先协议进行通信,必须先在两个在两个Socket之间建立连接。其中一个之间建立连接。其中一个Socket监听连接请求监听连接请求(服务器服务器),另一个发,另一个发出连接请求。一旦两个出连接请求。一旦两个Socket之间建立了之间建立了连接,它们就能被用来双向连接,它们就能被用来双向(或单向或单向)传递传递数据。数据。5:36第第13页页 使用使用UDP,每一次发送数据报时,都
11、每一次发送数据报时,都要随之一起发送本地的描述符和接收方要随之一起发送本地的描述符和接收方Socket地址。而使用地址。而使用TCP则不需如此,但则不需如此,但由于由于TCP是一个面向连接的协议,所以在是一个面向连接的协议,所以在通信之前,必须在通信之前,必须在Socket之间建立连接。之间建立连接。由上可知,使用由上可知,使用TCP需要建立连接的时间,需要建立连接的时间,而使用而使用UDP则需要更多的信息。则需要更多的信息。 TCP提供了双向的、有序的、无重复并提供了双向的、有序的、无重复并且无记录边界的数据流服务。且无记录边界的数据流服务。UDP也支持也支持双向的数据流,但并不保证可靠、有
12、序、双向的数据流,但并不保证可靠、有序、无重复,并且它保留了记录边界(无重复,并且它保留了记录边界(64K)。)。5:36第第14页页Socket是传输层提供的网络进程通信接口是传输层提供的网络进程通信接口。 它封装了通信协议族系的不同或同一它封装了通信协议族系的不同或同一族系传输层不同协议的差别。族系传输层不同协议的差别。 通信的主动方是客户,它利用通信的主动方是客户,它利用Socket机制,向服务器机制,向服务器(接收方)发送请求,服务接收方)发送请求,服务器接收客户请求,返回服务结果。器接收客户请求,返回服务结果。 用户可以为用户可以为Socket机制选取不同参数,机制选取不同参数,使使
13、Socket机制支持不同族系的通信协议机制支持不同族系的通信协议(TCPIP或其他或其他)、同族通信协议中不同、同族通信协议中不同质量要求的协议质量要求的协议(TCP或或UDP)。)。5:36第第15页页1、我们通过下图来了解一下客服、我们通过下图来了解一下客服/服务服务Socket通信程序设计的整个流程:通信程序设计的整个流程:1 1、建立服务器套接字对象、建立服务器套接字对象监视端口监视端口svrsocsvrsoc=new ServerSocket(8000) =new ServerSocket(8000) 3 3、客户建立、客户建立SocketSocket对象对象 soc=new soc
14、=new SocketSocket(“(“svrHost,8000)svrHost,8000)服务器服务器 客户机客户机 输入流输入流5 5、关闭、关闭 输出流输出流 Socket Socket 输入流输入流5 5、关闭、关闭 输出流输出流 Socket Socket2 2、接收连接、接收连接返回新返回新SocketSocket对象对象Socket soc=Socket soc=svrsoc.acceptsvrsoc.accept() () 监听监听4 4、构造数据输入流对象、构造数据输入流对象(接收)(接收) 数据输出流对象数据输出流对象 (发送)(发送)4 4、构造数据输出流对象、构造数据
15、输出流对象(发送)(发送) 数据输入流对象数据输入流对象(接收)(接收)socsocsocsoc5:36第第16页页 在在Java中,所有输入输出的核心就是数据流。中,所有输入输出的核心就是数据流。可以将数据流看作是一个管道,你可以可以将数据流看作是一个管道,你可以将数据输入将数据输入管道管道(即写入流即写入流),或,或从管道中取出信息从管道中取出信息(即从流中读即从流中读出出)。 使用使用Socket,所有读写的信息都被打包成不同所有读写的信息都被打包成不同形式的流。通过构建形式的流。通过构建OutputStream(提供了提供了Write()方法)写信息,通过构建方法)写信息,通过构建In
16、putStream(提供了提供了Read()方法)读信息,当一个方法)读信息,当一个Socket连接成功建立连接成功建立后,每一个终止点处都创建了一个后,每一个终止点处都创建了一个InputStream和和OuputStream。 lnputStream使用使用getlnputStream()来创建,来创建,OutputStream使用使用getOutputStream()来创建。这来创建。这些流既允许你读写单字节,也允许你读写多字节。些流既允许你读写单字节,也允许你读写多字节。5:36第第17页页1)编程步骤如下:)编程步骤如下:(1)创建一个创建一个ServerSocket对象,用于端口监
17、听对象,用于端口监听(只用于服务器程序只用于服务器程序)。)。public final static int TestPort=5000;ServerSocket checkServer=null;try checkServer=new ServerSocket(TestPort);catch(IOException ioe)System.err.println(ioe); 5:36第第18页页对于客户机:对于客户机:Socket c1=null;c1=new Socket(dbms-pc,RemotePort);(注意:为节省篇幅,程序省略异常处理,注意:为节省篇幅,程序省略异常处理,下同。
18、下同。)对于服务器:对于服务器:Socket clientSocket=null;clientSocket=checkServer.accept();(2)打开一个打开一个Socket对象。对象。5:36第第19页页BufferedReader is=null;BufferedWriter os=null;tryis =new BufferedReader(new InputStreamReader(clientSocket.getInputStream();os=new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputS
19、tream();catch(IOException e)System.err.println(e);调用调用is、os的相关方法(的相关方法(read(),write())可可以使用以使用Socket进行数据的发送和接收。进行数据的发送和接收。(3)创建一个数据输入流和一个数据输出流。创建一个数据输入流和一个数据输出流。客户机使用其客户机使用其Socket对象对象c1?为什么使用为什么使用BufferedReader和和BufferedWriter的做读、的做读、写流的对象,而不使用常写流的对象,而不使用常规的规的DataInputStream 与与DataOutputStream做读、做读、
20、写流的对象写流的对象?5:36第第20页页(4)关闭)关闭Socket。在退出前要关闭输入输出流及在退出前要关闭输入输出流及Socket,以此断开以此断开连接并且释放所有占用的资源。连接并且释放所有占用的资源。 需要注意的是,要先将对应的输入输出流关需要注意的是,要先将对应的输入输出流关闭,然后再关闭闭,然后再关闭Socket本身。本身。tryos.close();is.close();clientSocket.close();/客服机使用其客服机使用其Socket对象对象c1 catch(IOException e)System.err.println(e);5:36第第21页页2)实例程序
21、:)实例程序:Greetings服务器实例:服务器实例: 在这个客户服务器应用程序中,服务在这个客户服务器应用程序中,服务器监听着一个预定的端口号(器监听着一个预定的端口号(5000),等待),等待客户的连接。客户的连接。 当客户程序运行后,它请求用户输入一当客户程序运行后,它请求用户输入一个要发往服务器的关键句。个要发往服务器的关键句。 如果用户输入了正确的关键句如果用户输入了正确的关键句“Greetings”,那么服务器将把信息那么服务器将把信息“visit successfully!”发送回客户;否则服务器发发送回客户;否则服务器发送信息送信息“Sorry,you fogot our p
22、rotocol!”5:36第第22页页 下面,让我们看这个客户服务器下面,让我们看这个客户服务器应用程序的开发过程。大家可以通过这应用程序的开发过程。大家可以通过这个应用程序中的开发,掌握个应用程序中的开发,掌握TCP/IP协议协议通信的主要思想。通信的主要思想。5:36第第23页页 服务器程序所要做的内容就是:服务器程序所要做的内容就是: 产生一个产生一个ServerSocket对象,以接受客户对象,以接受客户的连接,连接成功后初始化一个的连接,连接成功后初始化一个Socket对象;对象; 产生一个输入流以便从客户机读信息;产产生一个输入流以便从客户机读信息;产生一个一个输出流,以便发送响应
23、给连接的生一个一个输出流,以便发送响应给连接的客户机。客户机。 服务器程序服务器程序SocketServer.java。(1)服务器程序设计)服务器程序设计5:36第第24页页 客户程序程序所要做的内容就是:客户程序程序所要做的内容就是: 它打开一个端口号为它打开一个端口号为5000的的Socket连接,连接,此端口为服务器运行的端口;此端口为服务器运行的端口; 它使用一个输出流它使用一个输出流os,发送信息到服务器:发送信息到服务器:使用一个输入流使用一个输入流is,读来自服务器的信息读来自服务器的信息(即即应答消息应答消息)。 客户机程序客户机程序SocketClient.java。(2)
24、客户程序设计)客户程序设计5:36第第25页页结果讨论(结果讨论(结果文档:结果文档:TCPSocket结果结果.txt) 该程序的结果可分为三种情况:该程序的结果可分为三种情况:情况一:情况一: 服务器未开启服务器未开启,或网络有问题或网络有问题连接不连接不成功!成功!情况二:情况二: 与服务器连接成功,但是输入口令错误与服务器连接成功,但是输入口令错误返回错误信息!返回错误信息!情况三:情况三: 与服务器连接成功,且口令输入成功与服务器连接成功,且口令输入成功返回成功信息!返回成功信息!(3)结果讨论)结果讨论5:36第第26页页 在这个程序中,服务器与客服机都是在这个程序中,服务器与客服
25、机都是单线流程,接受了一个客户的请求之后,单线流程,接受了一个客户的请求之后,程序便中止了,这是不合理的,为什么?程序便中止了,这是不合理的,为什么?怎么解决?怎么解决?(4)思考)思考5:36第第27页页 以前所编写的程序,以前所编写的程序,每个程序都有一个入每个程序都有一个入口、一个出口以及一个顺序执行的序列口、一个出口以及一个顺序执行的序列,在,在程序执行过程中的任何指定时刻,都只有一程序执行过程中的任何指定时刻,都只有一个单独的执行点。个单独的执行点。 事实上,在单个程序内部是可以在同一时事实上,在单个程序内部是可以在同一时刻进行多种运算的,这就是所谓的多线程刻进行多种运算的,这就是所
26、谓的多线程(这与多任务的概念有相似之处)。(这与多任务的概念有相似之处)。 具有单控制流的程序称作序列具有单控制流的程序称作序列(Sequential)程序。在序列程序中,任一时程序。在序列程序中,任一时刻计算机只能执行一点。相反,如果一个程刻计算机只能执行一点。相反,如果一个程序在任一时刻能够执行多点,就称它为并发序在任一时刻能够执行多点,就称它为并发(Concurrent)程序。程序。5:36第第28页页n能直接共享数据和资源,提高运行效率高能直接共享数据和资源,提高运行效率高n 适合于开发服务程序适合于开发服务程序(如(如Web服务,聊天服务等服务,聊天服务等)n 适合于开发有多种交互接
27、口的程序适合于开发有多种交互接口的程序(如聊天程序(如聊天程序的客户端,网络下载工具的客户端,网络下载工具)n 适合于有人机交互又有计算量的程序适合于有人机交互又有计算量的程序(如字处理(如字处理程序程序Word,Excel)n 减轻编写交互频繁、涉及面多的程序的困难减轻编写交互频繁、涉及面多的程序的困难n 程序的吞吐量会得到改善(同时监听多种设备,如程序的吞吐量会得到改善(同时监听多种设备,如网络端口、串口、并口以及其他外设)网络端口、串口、并口以及其他外设)n 有多个处理器的系统,可以并行运行不同的线程有多个处理器的系统,可以并行运行不同的线程(否则,(否则,任何时刻只有一个线程在被任何时
28、刻只有一个线程在被CPU执行执行)5:36第第29页页从从Thread类的构造方法可以看出,用户可以类的构造方法可以看出,用户可以有两种方法构造自己的有两种方法构造自己的run( )方法。方法。 方法一:通过继承方法一:通过继承Tread类类 定义一个线程类,它继承类定义一个线程类,它继承类Thread并重写并重写其中的方法其中的方法run()。这时在初始化这个类的实这时在初始化这个类的实例时,目标对象例时,目标对象target可以为可以为null,表示这个表示这个实例本身具有线程体。由于实例本身具有线程体。由于Java只支持单继只支持单继承,用这种方法定义的类不能再继承其他类。承,用这种方法
29、定义的类不能再继承其他类。5:36第第30页页import java.lang.*;class MyThread extends Threadpublic MyThread (String name)super(name);public void run()for(int i=0;i3;i+)System.out.println(this.getName()+:+i);tryThread.sleep(2000);catch(InterruptedException e)e.printStackTrace();5:36第第31页页public static void main(String ar
30、gv )MyThread t1=new MyThread(Thread1); MyThread t2=new MyThread(Thread2); t1.start(); t2.start();5:36第第32页页方法二:通过实现方法二:通过实现Runnable接口接口 提供一个实现接口提供一个实现接口Runnable的类作为线程的类作为线程的目标对象。在初始化一个的目标对象。在初始化一个Thread类或子类类或子类生成线程实例时,把目标对象传递给这个线程生成线程实例时,把目标对象传递给这个线程实例,由该目标对象提供线程体实例,由该目标对象提供线程体run()方法。方法。这时,实现接口这时,实
31、现接口Runnable的类还可以再继承的类还可以再继承其他类,即实现接口其他类,即实现接口Runnable的类可以不单的类可以不单纯是提供线程体。纯是提供线程体。5:36第第33页页 import java.lang.*; class MyThread2 implements Runnablepublic void run()for(int i=0;i3;i+)System.out.println(Thread.currentThread().getName()+:+i);tryThread.sleep(1000);catch(InterruptedException e)e.printSta
32、ckTrace();注意:这里必须注意:这里必须指明当前线程。指明当前线程。5:36第第34页页public static void main(String argv)MyThread2 s=new MyThread2();MyThread2 k=new MyThread2();Thread t1=new Thread(s,Thread1);Thread t2=new Thread(k,Thread2);t1.start();t2.start();注意:两种不同方式进行注意:两种不同方式进行多线程程序设计的多线程程序设计的线程类线程类的创建的创建和和线程对象的初始线程对象的初始化化方式有什么不
33、同。你怎方式有什么不同。你怎么选择么选择5:36第第35页页nvoid run()n线程所执行的代码线程所执行的代码nvoid start()n使程序开始执行,多次调用会产生异常使程序开始执行,多次调用会产生异常nvoid sleep(long milis) throws InterruptedExceptionn让线程睡眠一段时间,此期间线程不消耗让线程睡眠一段时间,此期间线程不消耗CPU资源资源nvoid interrupt()n中断线程中断线程nstatic boolean interrupted()n判断当前线程是否被中断(会清除中断状态标记)判断当前线程是否被中断(会清除中断状态标记
34、)5:36第第36页页nboolean isInterrupted()n判断指定线程是否被中断判断指定线程是否被中断nstatic Thread currentThread()n返回当前线程对象的引用返回当前线程对象的引用nvoid setName(String threadName)n改变线程的名字改变线程的名字nString getName()n获得线程的名字获得线程的名字nvoid join(long millis, int nanos)n等待线程结束等待线程结束5:36第第37页页nboolean isAlive()n判断线程是否处于活动状态(即已调用判断线程是否处于活动状态(即已调用
35、start,但但run还未返回)还未返回)nvoid destroy()n销毁线程销毁线程nvoid stop()n终止线程的执行终止线程的执行nvoid suspend() / void resume()n线程挂起线程挂起/ 恢复恢复nstatic void yield()n暂停当前线程,让其他线程执行暂停当前线程,让其他线程执行nnotify() / notifyAll() / wait() 从从Object继承而来继承而来5:36第第38页页nint getPriority()n获得线程的优先级获得线程的优先级nvoid setPriority( int p )n设置线程的优先级设置线程
36、的优先级n关键字:关键字: synchronized : 用于标注临界区代码段,防止同时访问共享资源。用于标注临界区代码段,防止同时访问共享资源。5:36第第39页页 线程是程序内部的一个顺序控制流,线程是程序内部的一个顺序控制流,它具有一个特定的生命周期。在一个线程它具有一个特定的生命周期。在一个线程的生命周期中,它总处于某一种状态中。的生命周期中,它总处于某一种状态中。线程的状态表示了线程正在进行的活动以线程的状态表示了线程正在进行的活动以及在这段时间内线程能完成的任务。及在这段时间内线程能完成的任务。5:36第第40页页new Thread()New ThreadRunnablestar
37、t()Not Runnablestop()stop()Deadyield()stop()run()exit. .suspend()sleep()wait()I/O流阻塞resume()notify()/notifyAll()I/O指令指令.waitingsleepingsuspendingblockedreadyrunning通过线程控制和哲学家就餐问题,对多线程进行了解。通过线程控制和哲学家就餐问题,对多线程进行了解。5:36第第41页页 在对线程的编写进行简单介绍后,我们在对线程的编写进行简单介绍后,我们就可以编写一些多线程服务器应用程序,就可以编写一些多线程服务器应用程序,该程序能够同时
38、为多个客户程序提供的服该程序能够同时为多个客户程序提供的服务器程序。下图所示:在一个客户和一个务器程序。下图所示:在一个客户和一个多线程服务器之间建立的通信步骤。多线程服务器之间建立的通信步骤。 5:36第第42页页1、我们通过下图来了解一下多线程服务与、我们通过下图来了解一下多线程服务与客户客户Socket通信程序设计的整个流程:通信程序设计的整个流程:1 1、建立服务器套接字对象、建立服务器套接字对象监视端口监视端口svrsocsvrsoc=new ServerSocket(8000) =new ServerSocket(8000) 3 3、客户建立、客户建立SocketSocket对象对
39、象 soc=new soc=new SocketSocket(“(“svrHost,8000)svrHost,8000)服务器服务器 客户机客户机 输入流输入流5 5、关闭、关闭 输出流输出流 Socket Socket 输入流输入流5 5、关闭、关闭 输出流输出流 Socket Socket2 2、接收连接、接收连接返回新返回新SocketSocket对象对象Socket soc=Socket soc=svrsoc.acceptsvrsoc.accept() () 监听监听4 4、构造数据输入流对象、构造数据输入流对象(接收)(接收) 数据输出流对象数据输出流对象 (发送)(发送)4 4、构
40、造数据输出流对象、构造数据输出流对象(发送)(发送) 数据输入流对象数据输入流对象(接收)(接收)socsocsocsoc5:36第第43页页实例:局域网络通信客户实例:局域网络通信客户/服务器应用程序服务器应用程序编写聊天程序。在这个分布式程序中编写聊天程序。在这个分布式程序中:客户客户发送发送接收用户和信息内容接收用户和信息内容给服务器;给服务器;服务器服务器接收接收,并将接收的信息,并将接收的信息转发转发给给目目标客户标客户。目标客户程序目标客户程序接收接收信息,并将其显示出信息,并将其显示出来。来。服务器随时为客户机服务。服务器随时为客户机服务。 5:36第第44页页5:36第第45页
41、页 我们知道要实现多线程,只需派生我们知道要实现多线程,只需派生(或继或继承承)Tread类的子类,并实现类的子类,并实现run()方法即可。方法即可。run()方法实际上包括了服务程序所要进行的方法实际上包括了服务程序所要进行的所有操作,但是线程只有在所有操作,但是线程只有在start()方法后才会方法后才会开始执行,并按顺序执行开始执行,并按顺序执行run()方法。方法。 本例中:将服务器的程序分派给两个线程本例中:将服务器的程序分派给两个线程进行运行。一个进行运行。一个Server类类用于完成监听客户用于完成监听客户机的连接;一旦连接,即调用机的连接;一旦连接,即调用Connects类类
42、中中的的run()方法,方法, run()执行了所有的操作。在执行了所有的操作。在run()方法中,从客户方法中,从客户Socket中读入目标客户中读入目标客户和信息内容,然后,将内容发送给目标客户。和信息内容,然后,将内容发送给目标客户。这样可以达到监听器与通信程序并行。这样可以达到监听器与通信程序并行。 服务器程序的源代码:服务器程序的源代码:Server.java 5:36第第46页页 此客户程序所做的就是打开一个此客户程序所做的就是打开一个Socket连接,一个输入流和一个输出流。完成这项工连接,一个输入流和一个输出流。完成这项工作后,客户程序发送目标客户编号和信息内容作后,客户程序发送目标客户编号和信息内容到服务器,发送程序就结束了到服务器,发送程序就结束了。 但是客户也需要创建线程,一直等待服务器但是客户也需要创建线程,一直等待服务器转发来的别人的信息。转发来的别人的信息。 客户程序的源代码:客户程序的源代码:Client.java