3-基于TCP的Socket通信

上传人:门**** 文档编号:242968701 上传时间:2024-09-13 格式:PPT 页数:33 大小:536KB
返回 下载 相关 举报
3-基于TCP的Socket通信_第1页
第1页 / 共33页
3-基于TCP的Socket通信_第2页
第2页 / 共33页
3-基于TCP的Socket通信_第3页
第3页 / 共33页
点击查看更多>>
资源描述
单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,单击此处编辑母版标题样式,*,3,基于,TCP,的,Socket,通信,3.1 Socket,类与,ServerSocket,类,3.2,简单服务器程序,3.3,简单客户端程序,3.4,基于多线程的服务器程序,3.5,基于多线程的客户端程序,基于,TCP,的,Socket,通信,基于,TCP,的,Socket,通信是通过指定,IP,地址,和,port,号,,采用,C/S,模式建立,TCP,协议下的两个通信进程间的连接,实现可靠的双向通信。,Java,中:实现,客户端,套接字的,Socket,类;实现,服务器端,套接字的,ServerSocket,类。,2,Socket,类的构造方法与常用方法,构造方法,功能,Socket(InetAddress,address,int,port),Socket(String,host,int,port),创建一个流套接字并将其连接到指定,IP,地址的指定端口号,创建一个流套接字并将其连接到指定主机上的指定端口号,表,3-2,常用方法及功能,常用方法,功能,public void close(),public,InetAddress,getInetAddress,(),* public,InputStream,getInputStream,(),public,InetAddress,getLocalAddress,(),public,int,getLocalPort,(),*public,OutputStream,getOutputStream,(),public,int,getPort,(),关闭此套接字,返回套接字连接的地址,返回套接字的输入流,获取套接字绑定本地地址,返回套接字绑定的本地端口,返回套接字的输出流,返回套接字连接的远程端口,3,ServerSocket,类构造方法与常用方法,构造方法,功能,ServerSocket(int,port),ServerSocket(int,port,int,backlog),ServerSocket(int,port,int,backlog,InetAddress,bindAddr,),创建绑定到特定端口服务器套接字,用,backlog,创建服务器套接字,将其绑定到指定本地端口号,用指定端口、侦听,backlog,和要绑定本地,IP,地址创建服务器,常用方法,功能,*,public Socket accept(),public void close(),public,InetAddress,getInetAddress,(),public,int,getLocalPort,(),侦听并接受到此套接字的连接,关闭此套接字,返回此服务器套接字的本地地址,返回此套接字在其上侦听的端口,3.1,Socket,类与,ServerSocket,类,Socket,通信原理,网络中基于,Socket,通信的两个进程间建立连接时,会将其中一个进程作为客户端,而另一个进程作为服务器端。,(,1,),C/S,模型,ServerSocket,类和,Socket,类实现通信的,C/S,模型。,(,1,)基于,Socket,通信的,C/S,模型,(,续一,),图,3-1,使用,ServerSocket,类和,Socket,类实现通信的,C/S,模型,基于,Socket,通信的基本算法,:,S1,:,用,一致端口,分别建,Socket,类和,ServerSocket,类对象,;,S2:,服务器端,ServerSocket,类对象用,accept(),监视端口;,S3:,打开连接到客户端,Socket,类对象的输入,/,输出流,向服务器端,ServerSocket,类对象发送相应请求,服务器接受客户请求并返回客户端,Socket,类对象,从而建立连接;,S4:,通信双方按照一定协议对,Socket,对象进行读,/,写操作,;,S5:,关闭,Socket,。,(,2,)客户端进程,按给定,服务器端地址,及,端口号,,建立客户端套接字,Socket,类对象,并向服务器端发送请求,等待服务器响应。代码如下:,try ,/,创建客户端,Socket,类的对象,socket,服务器地址取本地,端口号为,8888,Socket,socket,= new,Socket(localhost, 8888);, catch (,UnknownHostException,e) ,e.printStackTrace,();,catch (,IOException,e) ,e.printStackTrace,();,(,3,)服务器端进程,按与客户端商定的端口号建立服务器端套接字,ServerSocket,类对象,然后用,ServerSocket,对象方法,accept(),监听该端口是否有客户端发送请求。,若无请求,则服务器进程处于等待状态并一直监听端口;一旦接收到客户端请求,,accept(),获取返回该客户端对象,,即在服务器端保存与客户端的连接,接下来可利用该连接实现与客户端之间的数据交换。,(,3,)服务器端进程,建立服务器端套接字及端口监听的代码:,try ,ServerSocket,serversocket,= new,ServerSocket(8888,);,Socket,socket,=,serversocket.accept,();, catch (,IOException,e) ,e.printStackTrace,();,强调:服务器的端口号和客户端进程中指定端口号应该一致,否则不能建立连接。,3.2,简单服务器程序,由服务器端程序与客户端程序两部分组成,基本功能是:,()服务器端程序,监听,C/S,双方约定的端口(,55558,),等待并接收客户请求,接受客户请求后建立一个至客户端的基于套接字的连接,然后利用该连接返回到客户端的,Socket,对象,创建一个服务器端输入流,InputStream,和一个服务器端输出流,OutputStream,,同时将它们分别包装成便于操作与刷新的,BufferedReader,输入流和,PrintWriter,输出流。,然后,服务器端从,InputStream,读入客户端输出的数据,用,OutputStream,向客户端输出数据,直到接收到客户端的数据终止标志“结束”为止,,最后关闭连接,释放网络资源,结束本次通信。,()客户端程序,首先创建客户端,Socket,对象后,然后在约定端口向服务器端发送请求,待服务器端接受请求后建立基于套接字的连接,然后利用该连接的,Socket,对象,创建一个客户端输入流,InputStream,和一个客户端输出流,OutputStream,,同时将它们分别包装成便于操作与刷新的,BufferedReader,输入流和,PrintWriter,输出流。,然后,客户端从,InputStream,读入服务器端输出的数据,用,OutputStream,向服务器端输出数据,直到发送完数据终止标志“结束”为止,最后关闭连接,释放网络资源,结束本次通信。,例,3-1,基于,Socket,的简单服务器程序。,程序清单,:,DaytimeClient,.java,【,例,3-1】,程序分析:,服务器端程序与客户端程序都使用同样的,端口号,(,55558,),服务器端程序在本地机器上运行其,ServerSocket,只需要一个端口号,而不需要,IP,地址。,服务器端,ServerSocket,类的实例调用,accept(),方法时,会陷入阻塞状态,直到某个客户端程序请求与它建立连接。,连接正常建立后,,accept(),将返回一个客户端,Socket,类的实例,即本次,C/S,套接字连接的实例,它是一个可读写的双向管道。,【,例,3-1】,程序分析:,(,续一,),必须将,ServerSocket,构造方法、,accept(),方法和,I/O,流操作方法等放在一个,try-finally,代码块,以确保无论什么方式结束,,ServerSocket,、,Socket,和,I/O,流都能被正确关闭。,若,ServerSocket,对象创建失败,则抛出,IOException,异常,并由,finally,块确保无论正常与否结束通信,均会关闭连接、释放网络套接字等资源。由于套接字使用了重要的非内存资源,因此要特别谨慎,必须以显式方式将它们及时清除。,【,例,11-5】,程序分析:,(,续二,),当程序中利用标准输出流,System.out,将,ServerSocket,类构造的实例和,accept(),方法返回的,Socket,类的实例打印输出时,自动调用了它们的,toString,(),方法,其结果如下:,ServerSocket,addr,=0.0.0.0/0.0.0.0,port=0,localport=55558,Socket ,addr,=/127.0.0.1,port=3024,localport=55558,【,例,11-5】,程序分析:,(,续三,),数据交换部分,:服务器端的输入流,InputStream,和输出流,OutputStream,是从,Socket,类的实例创建的。,它采用,装饰模式,,先利用两个“转换器”类,InputStreamReader,和,OutputStreamWriter,,将,InputStream,和,OutputStream,对象分别转换成为,Reader,和,Writer,对象。,再利用类,BufferedReader,和,PrintWriter,,将,Reader,和,Writer,对象分别转换成为,BufferedReader,和,PrintWriter,对象,以方便读写与刷新操作。,若构造方法,PrintWriter(Writer,out,boolean,autoFlush,),中的“,autoFlush,”,为“,true”,时,则,PrintWriter,类的,out,对象每次调用,println,(),结束时会自动刷新输出缓冲区(但不适用于,print(),语句),使输出流中的信息能即时通过网络传递出去。,11.3.3,简单客户端程序,根据,11.3.2,节中基于,Socket,的通信系统中对客户端程序功能的分析,其实现代码如例,11-6,所示。,P400【,例,11-6】,基于,Socket,的简单客户端程序。,程序清单,11-6:,SimpletClientSocketDemo.java,运行方法:在待运行类的主目录下编写并运行,SimpletClientSocketDemo.bat,文件,其内容如下:,java,socket.SimpletClientSocketDemo,pause,运行结果:如图,11-4,所示。,图,11-4,例,11-6,中客户端的输出结果,【,例,11-6】,程序分析:,客户端使用本地主机(,Localhost,)地址与位于同一台机器中的服务器程序建立连接,因此可在一台物理机器中完成测试,若将客户端程序与服务器端程序分布在一个物理网络中,则可在客户端,Socket,对象中指定服务器的,IP,地址,即可实现通信。,客户端程序中获得本地主机,IP,地址的,InetAddress,的途径有三种:使用,null,、使用,localhost,,或者直接使用保留地址,127.0.0.1,。若向,getByName,( ),传递一个,null,,则默认寻找,localhost,,并生成特殊的保留地址,127.0.0.1,。注意:在创建名为,socket,的套接字时,同时使用了,InetAddress,以及端口号。,【,例,11-6】,程序分析:,(,续一,),服务器程序启动后在本地主机(,127.0.0.1,)上为其分配端口,55558,。一旦客户端程序发出请求,当前机器中的下一个可用端口就会分配给客户端程序(此处为,3024,),并同时告知与其连接的服务程序。此例中,服务器端进程获取的客户端套接字如下所示:,Socket ,addr,= 127.0.0.1,port=3024,localport =55558,它表示服务器进程已接受来自,IP,为,127.0.0.1,机器的,3024,端口的客户端进程的连接,同时监听其本地的,55558,端口,而在客户端输出的套接字如下所示:,Socket ,addr,= localhost/127.0.0.1,port=55558,localport=3024,它表示客户端进程已用其本地端口,3024,与,127.0.0.1,机器上的,55558,端口建立了连接。,【,例,11-6】,程序分析:,(,续二,),数据交换:,创建好客户端,Socket,对象后,调用其,getInputStream,(),和,getOutputStream,(),方法分别创建客户端的输入流,InputStream,和输出流,OutputStream,,并与服务器端程序一样采用装饰模式,最终将它们分别转换成为,BufferedReader,输入流和,PrintWriter,输出流,以方便读写与刷新操作。,为了测试通信正常与否,此处,客户端输出流通过发送“,From Client ”,加数字的字符串数据来初始化通信,而客户端输入流则从服务器输出流中接收“,From Server ”,加数字的字符串行,写入,System.out,后,在屏幕打印输出。最后,为终止数据交换,客户端输出流通过向服务器端输入流发送“结束”字符串,以结束本次通信,释放套接字连接资源。,【,例,11-6】,程序分析:,(,续三,),在客户端程序中同样采用,try-finally,块,以确保由,Socket,代表的网络资源能得到正确的清除。,套接字建立的“专用”连接会一直持续到明确断开连接为止(除非某端或中间链路出现故障而崩溃)。在连接未拆除前,参与连接的双方都被锁定在通信中,且无论是否有数据传递,连接都会连续处于开放状态。因此,每次通信结束时,若不及时拆除连接将会增加网络的额外开销,甚至使资源耗尽,导致系统崩溃。,11.3.4,基于多线程的服务器程序,例,11-5,中的,SimpleServerSocketDemo,尽管能正常工作,但每次只能为一个客户端程序提供服务。实际应用中,要求服务器能同时处理多个客户端的请求。,解决此问题的关键就是将多线程处理机制应用到网络通信中来。如图,11-5,所示是在图,11-2,的基础上改进而来的基于,Socket,的多线程,C/S,通信模型,它可应用于对例,11-5,与例,11-6,的改造,从而实现响应多客户请求的数据通信,提高服务器的并发性能。,11.3.4,基于多线程的服务器程序,(,续一,),图,11-5,基于,Socket,的多线程,C/S,通信模型,其基本思想是,:在服务器程序中创建单个,ServerSocket,的实例,并循环调用其,accept( ),方法以等候一个新连接。一旦,accept( ),返回一个客户端线程的,Socket,的实例,就用该,Socket,实例新建一个服务线程,为该特定的客户端线程服务。客户端程序采用多线程技术能创建多个,Socket,实例的线程,并能控制其活动线程的总数量,以防止服务器过载和网络拥塞。,11.3.4,基于多线程的服务器程序,(,续二,),例,11-7,是基于多线程的服务器程序,它是对例,11-5,的改进,它与,SimpleServer,SocketDemo.java,很相似,只是为一个特定的客户端线程提供服务的所有操作都被移入一个独立的线程类,MultithreadServerSocket,中。,P402【,例,11-7】,基于多线程的服务器程序。,程序清单,11-7:,MultithreadServerSocketDemo.java,11.3.4,基于多线程的服务器程序,(,续三,),运行方法:在待运行类的主目录下编写并运行,MultithreadServerSocketDemo.bat,文件,其内容如下:,java,socket.MultithreadServerSocketDemo,pause,图,11-6,例,11-7,中服务器端输出的部分结果,【,例,11-7】,程序分析:,一旦有新的客户端,Socket,线程请求建立一个连接时,服务器端的,MultithreadServerSocket,线程会取得由,accept( ),返回的,Socket,对象。然后与例,11-5,一样,创建一个,BufferedReader,输入流和一个,PrintWriter,输出流。最后,它调用,Thread,的,start( ),方法进行服务线程的初始化,然后调用,run( ),完成数据交换。数据交换操作与例,11-5,相同。,【,例,11-7】,程序分析:,(,续一,),套接字的清除必须进行谨慎的设计。此例中,,ServerSocket,套接字是在,MultithreadServerSocket,外部创建的,所以清除工作可以“共享”。若,MultithreadServerSocket,构造方法失败,则只需向调用者抛出一个异常即可,然后由调用者负责线程的清除。但若构造方法成功,则必须由,MultithreadServerSocket,对象负责线程的清除,这是在它的,run( ),里进行的。,11.3.5,基于多线程的客户端程序,为了验证服务器代码确实能为多个客户端提供服务,下面这个程序将使用线程创建许多客户端,并与相同的服务器建立连接。每个线程的“存在时间”都是有限的。一旦到期,就留出空间以便创建一个新线程。允许创建的线程的最大数量是由,final,int,MAXTHREADS,决定的。这个值很关键,若把它设得很大,线程便有可能耗尽资源,产生不可预知的程序错误。基于多线程的客户端程序如例,11-8,所示,它是对例,11-6,的改进。,P405【,例,11-8】,基于多线程的客户端程序。,程序清单,11-8:,MultithreadClientSocketDemo.java,11.3.5,基于多线程的客户端程序,(,续一,),运行方法:在待运行类的主目录下编写并运行,MultithreadClientSocketDemo.bat,文件,其内容是:,java,socket.MultithreadClientSocketDemo,pause,图,11-7,例,11-8,中客户端输出的部分结果,【,例,11-8】,程序分析:,MultithreadClientSocket,构造方法用于获取一个,InetAddress,,并用它创建一个客户端的套接字实例。然后用,Socket,实例创建输入流,InputStream,和输出流,OutputStream,对象,再用,start( ),执行线程的初始化,并调用,run( ),,其数据交换与例,11-6,相同。,线程的“存在时间”是有限的,最终都会结束。在套接字创建好以后,在构造方法完成之前,假若构造方法失败,套接字会被清除。否则,为套接字调用,close(),的责任便落到了,run( ),方法上。,【,例,11-8】,程序分析:,(,续一,),tcount,跟踪计算目前存在的,MultithreadClientSocket,对象的数量。它将作为构造方法的一部分增值,并在,run( ),退出时减值。在,MultithreadClientSocketDemo.main,( ),中线程的数量会被检查。若数量太多,则多余的暂不创建。方法随后进入“休眠”状态。因此一旦部分线程最后被终止,则多出的那些线程就可以创建了。,
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 小学资料


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!