分布式系统编程_第1页
分布式系统编程_第2页
分布式系统编程_第3页
分布式系统编程_第4页
分布式系统编程_第5页
已阅读5页,还剩86页未读 继续免费阅读

下载本文档

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

文档简介

分布式系统编程第1页,课件共91页,创作于2023年2月网络APIAPI:应用程序编程接口Java网络应用程序编程接口(包)Socket接口RMI:RemoteMethodInvocation远程方法调用UNIXBerkeleysockets&RPC(RemoteProcedurecall)WindowsWinsock第2页,课件共91页,创作于2023年2月各种常见的应用程序编程接口第3页,课件共91页,创作于2023年2月4TCP/IP基础第4页,课件共91页,创作于2023年2月5第5页,课件共91页,创作于2023年2月6第6页,课件共91页,创作于2023年2月7Socket和Socket通信基础

Socket(套接字)的定义

面向客户端/服务器结构的SocketSocket最基本的函数与函数调用流程第7页,课件共91页,创作于2023年2月8Socket的定义进程标识一个主机的每一个网络进程使用协议端口进行标识,这样,要唯一确定网络环境的某个进程(计算机),就同时需要主机和端口号,在Internet网络环境中,就是同时采用IP地址和端口号来标识的。端口号只能取整数,范围是从0~65535,其中0~1023的端口号一般固定分配给一些系统服务。第8页,课件共91页,创作于2023年2月9查看进程及其端口第9页,课件共91页,创作于2023年2月10第10页,课件共91页,创作于2023年2月11第11页,课件共91页,创作于2023年2月12多重协议标识多重协议中需要指明是何种通信协议。一个通信进程的多重协议的标识就要用一个三元组:{协议,本地主机网络地址,本地主机进程瑞口},进行全局唯一地标识。一个完整的网间网进程通信由两个通信进程组成,需要一个五元组来标识:{协议,本地主机网络地址,本地主机进程瑞口,远程主机网络地址,远程主机进程端口}。第12页,课件共91页,创作于2023年2月13Socket套接字(Socket):在Internet网络环境中,协议、IP地址和端口构成了进程间通信的一个端点,抽象为网络编程的接口对象。每个Socket有一个本地唯一的Socket号,由操作系统分配.第13页,课件共91页,创作于2023年2月14Socket接口与TCP/IP协议的关系TCP(TransmissionControlProtocol):传输控制协议。UDP(UserDataProtocol):用户数据报协议。IP协议(InternetProtocol):在网络层采用的网间协议。DNS(DomainNameSystem):域名系统,简称域名,是IP地址的字符型地址。TCP/IP(TransmissionControlProtocol/InternetProtocol)协议簇:一个工业标准的协议集,简称TCP/IP协议,它是为广域网(WAN)设计的。其中IP协议和TCP协议是协议中最核心的两个协议。第14页,课件共91页,创作于2023年2月15Socket接口与TCP/IP协议Socket是应用层与TCP/IP协议通信的中间软件抽象层,是一组接口。把复杂的TCP/IP协议隐藏在Socket接口后面,对用户来说使用非常方便,通过Socket接口应对复杂网络间通信,以符合指定的协议。第15页,课件共91页,创作于2023年2月16不同的Socket不同的传输协议采用不同的Socket接口。(1)字节流套接字(StreamSocket)(2)数据报套接字(DatagramSocket)(3)原始数据报套接字(RawSocket)

Socket的出现只是可以更方便地使用TCP/IP协议而已,与TCP/IP协议并没有必然的联系。Socket接口在设计的时候,希望也能适应其他的网络协议。第16页,课件共91页,创作于2023年2月17

面向客户端/服务器结构的

套接字Socket服务器端(Server):专门处理消息、提供服务的进程。客户端(Client):发送消息、请求处理的进程。总体过程就是客户端发送一个消息给服务器端,服务器端进程收到消息进行处理,把处理结果发送给客户端。Socket正是面向客户/服务器(C/S)结构而设计的,针对客户和服务器程序提供不同的Socket系统调用。客户端随机申请一个半关联Socket;服务器拥有公认的Socket,它事先开启,即“侦听”,任何客户都可以向它发出连接请求和信息请求,当服务器Socket“侦听”到客户端Socket便可实现连接和通信。对于客户端和服务器端Socket创建时关于端口号要事先进行约定,即共同操作同一个端口。第17页,课件共91页,创作于2023年2月18

套接字Socket最基本的

函数与函数调用流程socket():对网络通信信道实现创建套接字bind():绑定网络地址和端口recv()/send()或read()/write():接受信息和发送信息sendto()和recvfrom()函数connect():连接远程机器listen():监听到达的数据accept():接收请求closesocket():关闭套接字或连接Socket对通信协议进行了抽象,形成了很多灵活的函数(方法)。一些最基本的函数为:第18页,课件共91页,创作于2023年2月191.面向连接的客户端/服务器结构应用系统的关键流程

依据TCP协议,使用字节流套接字接口(StreamSocket)的网络通信为面向连接的网络通信。第19页,课件共91页,创作于2023年2月20面向连接的网络通信服务系统,socket()函数调用的关键流程第20页,课件共91页,创作于2023年2月212.面向无连接的客户端/服务器结构

应用系统的关键流程基于UDP协议,使用数据报套接字接口(DatagramSocket)的网络通信为面向无连接通信。面向无连接的网络通信服务系统,socket()函数调用的关键流程如图3-3所示。第21页,课件共91页,创作于2023年2月22面向无连接的socket()函数调用的关键流程第22页,课件共91页,创作于2023年2月23综上所述,Socket套接字在计算机中实现了一个通用的通信接口,可以通过这个接口与任何一个具有Socket接口的计算机通信。应用程序在网络上传输,接收的信息都通过这个Socket接口来实现。如今,Socket接口已是TCP/IP网络协议最为通用的API,也是在Internet上进行应用开发最为通用的API。第23页,课件共91页,创作于2023年2月24WindowsSocket网络编程

WindowsSockets编程概述客户端和服务器端主要函数描述Socket分为BSDUNIXSockets和WindowsSockets,即BSDSocket和WinSock。这里仅讨论WindowsSockets编程。第24页,课件共91页,创作于2023年2月25WindowsSockets编程概述WindowsSockets规范是一套开放的、支持多种协议,Windows下的网络编程接口。已成为Windows网络编程事实上的标准。WindowsSockets套接字编程模型的设计为服务器端和客户端结构,服务器与客户机端都必须调用WindowsSocketsAPI函数socket()建立一个通信套接字Socket,通过套接字链接和通信。第25页,课件共91页,创作于2023年2月26客户端和服务器端

主要函数描述WindowsSockets套接字编程的主要函数分为四类,共11个。①WSAStartup()和WSACleanup()函数:绑定和释放WinSock库和版本。②socket()和closesocket()函数:创建和关闭Socket套接字。③listen()、accept()和connect()函数:基于套接字建立监听、接收和连接函数。④send()/recv()和sendto()/recvfrom()函数:发送和接收数据函数。第26页,课件共91页,创作于2023年2月27WindowsSocket

网络编程实例构建编程环境TCP协议服务器和客户端编程实例UDP服务器和客户端编程实例第27页,课件共91页,创作于2023年2月28构建编程环境在VC++中已为WinSockAPI网络应用开发提供了所需的所有头文件和库文件,是一个方便、易用和强大的开发平台。在VC++语言中,需要配置和使用的如下几个文件,两个主要的版本:WinSock1:头文件WINSOCK.H、库文件WSOCK32.LIB

WinSock2头文件MSWSOCK.H、库文件WS2_32.LIB、MSWSOCK.LIB,以及WINSOCK.DLL、

下载MicrosoftWindowsServer2003SP1PlatformSDK,安装SDK后,设置VC++开发环境。第28页,课件共91页,创作于2023年2月29TCP协议服务器和客户端

编程实例设计一个基本的网络TCP协议服务器程序有如下几个步骤:①用WSAStartup()函数初始化WinSock库和用WSACleanup()释放WinSock资源操作,已封装到initWinSock.h程序中的CInitWinSock类中,故创建CInitWinSock类对象即可。②用socket()函数创建一个监听的Socket,如sListen。用TCP协议type参数为SOCK_STREAM。③设置服务器地址信息,并将监听端口绑定到这个地址上。④用listen()函数开始监听。⑤用accept()函数接收客户端连接。⑥用recv()/send()函数和客户端通信。⑦用closesocket()关闭与客户端连接套接字sClient,关闭服务器监听套接字sListen,或者返回第④步。第29页,课件共91页,创作于2023年2月30设计一个简单的TCP协议客户端程序有以下几个步骤:①同上创建CInitWinSock类对象,初始化WinSock库或释放WinSock资源。②用socket()函数创建一个客户端连接Socket,如sConnect。type参数为SOCK_STREAM。③填写连接服务器地址信息。④用connect()函数和创建的套接字与指定地址的服务器连接。⑤用send()/recv()函数发送和接收数据,直到TCP协议会话结束。⑥用closesocket()关闭客户端连接套接字sConnect。(1)TCP协议服务器程序:TCPServer.h(2)TCP协议客户机程序:TCPClient.h第30页,课件共91页,创作于2023年2月31UDP服务器和客户端

编程实例

设计UDP服务器程序有以下几个步骤:①初始化和释放WinSock资源(同上)。②用socket()函数创建服务器端套接字,如sServer。使用UDP协议type参数为SOCK_DGRAM。③设置本地服务器地址信息,调用bind()函数将套接字sListen与IP地址和端口绑定在一起。④用recvfrom()/sendto()函数收发数据。⑤关闭服务器套接字sListen。第31页,课件共91页,创作于2023年2月32设计UDP客户端程序有以下几个步骤:①初始化和释放WinSock资源(同上)。②用socket()函数创建客户端套接字,如sClient。type参数为SOCK_DGRAM。③填写服务器地址信息,调用bind()函数将套接字sClient与远程服务器IP地址和端口绑定在一起。④用recvfrom()/sendto()函数收发数据。⑤关闭客户端套接字sClient。(1)UDP服务器程序:UDPServer.h(2)UDP客户机程序:UDPClient.h第32页,课件共91页,创作于2023年2月33

JAVA网络编程

数据流

基于TCP协议的套接字通信

基于UDP协议的数据报和套接字第33页,课件共91页,创作于2023年2月34网络通信中基于套接字输入流和输出流的创建客户端要实现套接字的网络通信,需四个步骤:①创建套接字socket(Socket),连接成功后形成网络连接通道;②完成绑定套接字通信的输入流和输出流对象的创建;③用输入和输出流对象调用其对应方法的操作方式实现网络通信;④网络通信结束,需要关闭输入流和输出流对象,尤其要关闭套接字对象。第34页,课件共91页,创作于2023年2月35基于套接字的字节输入流和输出流的创建-网络编程实例importjava.io.*;import.*;publicclassClient{ publicstaticvoidmain(String[]args)throwsIOException{

//①建立Socket,服务器在本机的8888端口处进行“侦听”

Socketsocket=newSocket("",8888);//建立套接字

System.out.println("客户端套接字信息:"+socket); try{//②套接字建立成功后,建立字节输入流dis和输出流dos对象

DataInputStreamdis=newDataInputStream(socket.getInputStream()); DataOutputStreamdos=newDataOutputStream(socket.getOutputStream());

//③调用其对应方法进行网络通信

for(inti=0;i<6;i++){ dos.writeUTF("客户端测试:"+i); //向服务器发数据

dos.flush(); //刷新输出缓冲区,以便立即发送

System.out.println(dis.readUTF()); //将从服务器接收的数据输出

} dos.writeUTF("end"); //向服务器发送终止标志

dos.flush(); //刷新输出缓冲区,以便立即发送

//④关闭对象

dos.close();//关闭输出流对象dos dis.close();//关闭输入流对象dis }finally{ System.out.println("客户端结束……"); socket.close();//关闭套接字对象socket } }}第35页,课件共91页,创作于2023年2月36⑵基于套接字的具有缓冲的字符输入流和字符输出流的创建importjava.io.*;import.*;publicclassClient{publicstaticvoidmain(String[]args)throwsIOException{ //①建立Socket,服务器在本机的8888端口处进行“侦听”

Socketsocket=newSocket("",8888);//建立套接字

try{

//②套接字建立成功后,通过转换器建立字符输入流br和自动刷新输出流pw BufferedReaderbr=newBufferedReader( newInputStreamReader( socket.getInputStream())); PrintWriterpw=newPrintWriter( newBufferedWriter(newOutputStreamWriter( socket.getOutputStream())),true);转换器转换器第36页,课件共91页,创作于2023年2月37

//③调用其对应方法进行网络通信

for(inti=0;i<10;i++){ //向服务器发数据,并自动刷新输出缓冲区

pw.println("测试:"+i); Stringstr=br.readLine();//从服务器接收数据

System.out.println(str);//将从服务器接收的数据输出

} //向服务器发送终止标志,并自动刷新输出缓冲区

pw.println("end");

//④关闭对象

pw.close();//关闭输出流对象pw br.close();//关闭输入流对象br }finally{ System.out.println("结束……"); socket.close();//关闭套接字对象socket }}}第37页,课件共91页,创作于2023年2月38TCP套接字一个套接字Socket就是在网络上运行的两个程序间的双向通信通道的一个端点,两个程序通过各自的套接字实现程序间的与网络拓扑结构无关的通信。客户端程序和服务器必须使用同样的通信协议,这就是TCP协议,即它们在传送的信息所使用的语言上达成一致。在Java的包中提供了两个套接字类,如客户端程序的套接字Socket和服务器端的套接字ServerSocket,它们很好地支持了TCP套接字。

套接字通信是利用IP地址和端口Port进行的,是一种基础性的底层连接。一般步骤是:首先,服务器“侦听”其端口进入的连接。其次,客户端套接字与服务器的端口连接建立套接字级别的连接通道。再次,客户端与服务器分别通过绑定和套接字连接通道的输入输出流操作,实现网络通信与服务。第38页,课件共91页,创作于2023年2月39Socket类Socket类为客户端的通信套接字。以下三个功能:由构造函数,定义指定远端IP地址、端口进行连接通信的通信套接字socket。将此socket以字节输入流和输出流的形式返回,当与数据输入流和输出流绑定,便可实现客户端的网络通信。也可通过方法获得已连接的socket的远端IP地址、端口。1.Socket定义和构造函数2.返回输入流和输出流的方法3.获取Socket信息方法第39页,课件共91页,创作于2023年2月401.Socket定义和构造函数Socket构造函数均为public修饰类型,如果创建socket时发生I/O错误,均抛出IOException异常。定义和常用的构造函数如下:定义:publicclassSocketextendsObject构造函数:Socket(InetAddressaddress,intport)创建一个socket并与指定的IP地址的指定的端口相连接。address为指定的IP地址。port为指定的端口。Socket(Stringhost,intport)创建一个socket并与指定的主机的指定的端口相连接。host为指定的主机的字符串名。port为指定的端口。如果无法确定主机的IP地址还抛出UnknownHostException异常。第40页,课件共91页,创作于2023年2月412.获取输入流和输出流的方法publicInputStreamgetInputStream()throwsIOException返回此套接字的输入流。publicOutputStreamgetOutputStream()throwsIOException返回此套接字的输出流。套接字建立成功后,建立字节输入流dis和输出流dos对象:DataInputStreamdis=newDataInputStream(socket.getInputStream());DataOutputStreamdos=newDataOutputStream(socket.getOutputStream());第41页,课件共91页,创作于2023年2月423.获取Socket信息方法此类方法可获取socket所连接的远端IP地址、端口号,及所绑定的本地IP地址、端口号。另外,socket用完需要用方法关闭。方法如下:publicInetAddressgetInetAddress()获取socket所连接的远端IP地址。publicInetAddressgetLocalAddress()获取socket所绑定的本地IP地址。publicintgetPort()获取socket所连接的远端端口号。publicintgetLocalPort()获取socket所绑定到的本地端口号。publicvoidclose()throwsIOException关闭socket。StringtoString()将此socket转换为String。第42页,课件共91页,创作于2023年2月43ServerSocket类ServerSocket类为服务器的通信套接字。用来侦听客户端请求的连接,并为每个新连接创建一个socket对象,由此创建绑定此socket的输入流和输出流,与客户端实现网络通信。1.定义与构造函数2.常用成员方法第43页,课件共91页,创作于2023年2月441.ServerScket定义与构造函数定义:publicclassServerSocketextendsObject构造函数:ServerSocket(intport)在所给定的用来侦听的端口上建立一个服务器套接字。如果端口号为零,则在任意的空闲的端口上创建一个服务器套接字。外来连接请求的数量默认最大为50。port参数为在服务器上所指定的用来侦听的端口。ServerSocket(intport,intbacklog)在所给定的用来侦听的端口上建立一个服务器套接字。如果端口号为零,则在任意的空闲的端口上创建一个服务器套接字。外来连接请求的最大连接数量由backlog指定。第44页,课件共91页,创作于2023年2月452.常用成员方法此类方法关键是侦听连接端口,建立与客户端的套接字连接。服务器套接字用完需要用方法关闭。方法如下:publicSocketaccept()throwsIOException侦听并接收指向本套接字的连接,返回客户端连接套接字。本方法将造成阻塞直到连接成功。如果在等待连接时套接字发生I/O错误,则抛出异常IOException。publicvoidclose()throwsIOException关闭本ServerSocket。如果在关闭本ServerSocket时发生I/O错误,则抛出异常IOException。publicInetAddressgetInetAddress()获取此服务器端套接字的本地IP地址。publicintgetLocalPort()获取此套接字侦听的端口。StringtoString()作为String返回此套接字的实现IP地址和实现端口。第45页,课件共91页,创作于2023年2月46建立数据输入流过程服务器端程序。建立数据输入流dis和输出流过程类似。以创建和使用输入流dis为例。ServerSockets=newServerSocket(PORT);DataInputStreamdis=:侦听PORT端口,获得客户端套接字Socketss=s.accept();newDataInputStream(ss.getInputStream());while(true){//从客户端中读数据

Stringstr=dis.readUTF();}创建捆绑客户端套接字的数据输入流建立服务器ServerSocket套接字通过数据输入流操作读取数据第46页,课件共91页,创作于2023年2月47例程

服务器端程序DS_Server.javaimportjava.io.*;import.*;publicclassDS_Server{ publicstaticfinalintPORT=8888; publicstaticvoidmain(String[]args)throwsIOException{ ServerSockets=newServerSocket(PORT);//建立服务器ServerSocket套接字

System.out.println("服务器套接字信息:"+s); try{//程序阻塞,等待连接。即直到有一个客户请求到达,程序方能继续执行

Socketss=s.accept();//侦听PORT端口,获得客户端套接字

System.out.println("套接字接收到的信息:"+ss); //连接成功,建立相应的数据输入输出流

DataInputStreamdis=newDataInputStream(ss.getInputStream()); DataOutputStreamdos=newDataOutputStream(ss.getOutputStream()); //在死循环中,来与客户端通信

while(true){// Stringstr=dis.readUTF(); //从客户端中读数据

if(str.equals("end"))break;//当读到end时,程序终止

System.out.println(str); dos.writeUTF("服务器应答:"+str);//向客户端中写数据

} dos.close();//关闭输出流对象dos dis.close();//关闭输入流对象dis ss.close();//关闭套接字 }finally{ System.out.println("服务器结束……"); s.close();//关闭服务器套接字

} }}第47页,课件共91页,创作于2023年2月48

异常处理IOException异常Socket类出现异常:在创建套接字时、在连接期间发生错误时、关闭套接字时、绑定操作失败或者已经绑定了套接字时、在创建输入流时或没有关闭套接字或没有连接套接字或关闭了套接字输入、创建输出流时或者没有连接套接字时,系统均会抛出IOException异常。ServerSocket类也会发生I/O错误,出现异常:在打开套接字时、关闭套接字时、绑定操作失败或者已经绑定了套接字、等待连接时,系统则会抛出IOException异常。这类通用的异常,采用try/catch/finally结构来抛出、捕捉和处理。第48页,课件共91页,创作于2023年2月49异常处理BindException试图将套接字绑定到本地地址和端口时发生错误,通常是端口正在使用或无法分配所请求的本地地址。ConnectException试图将套接字连接到远程地址和端口时发生错误,通常是远程拒绝连接。NoRouteToHostException试图将套接字连接到远程地址和端口时发生错误,通常是无法到达远程主机。InterruptedIOExceptionI/O操作已中断。UnKnownHostException无法确定主机的IP地址。IllEgalArgumentException方法参数错误。第49页,课件共91页,创作于2023年2月50TCP网络通信实例在上例中,为单线程通信。用多线程机制实现服务器能同时处理多个客户端的请求。常用的方法是在服务器程序中,accept()返回一个socket后,就用它新建一个线程,令一个线程只为它特定的客户服务。然后再调用accept(),等待下一次新的连接请求,同时产生下一个新的客户线程。第50页,课件共91页,创作于2023年2月51publicclassSingleThreadEchoServer{publicstaticvoidmain(String[]args)throwsIOException{staticprivatefinalintDEFAULT_PORT=8189;staticprivatefinalStringSIGN_OFF_TOKEN="BYE";ServerSocketserverSocket=null;SocketclientSocket=null;System.out.println("CreatinServerSocketon"+DEFAULT_PORT);serverSocket=newServerSocket(DEFAULT_PORT);while(true){System.out.println("Lookingforaclient...");clientSocket=serverSocket.accept();//blocksuntilclientconnectshandleRequest(clientSocket);}}单线程服务器实现第51页,课件共91页,创作于2023年2月52privatestaticvoidhandleRequest(SocketclientSocket)throwsIOException{System.out.println("Aclientconnected.");Scannerin=newScanner(clientSocket.getInputStream());PrintWriterout=newPrintWriter(clientSocket.getOutputStream(),true);out.println("Hello!EnterBYEtoexit.");第52页,课件共91页,创作于2023年2月53Stringline;while(true){line=in.nextLine();System.out.println(line);//Printsonserversideif(line.trim().toUpperCase().startsWith(SIGN_OFF_TOKEN)){out.println("Byebye,Seeyoulater!");//clientsideoutputSystem.out.println("Clientsignedoff");break;}}第53页,课件共91页,创作于2023年2月54publicclassEchoClient{publicstaticvoidmain(String[]args)throwsIOException{SocketechoSocket=newSocket(DEFAULT_SERVER,DEFAULT_PORT);PrintWriterout=newPrintWriter(echoSocket.getOutputStream(),true);Scannerin=newScanner(echoSocket.getInputStream());Scannersin=newScanner(System.in);

System.out.println("CreatingSocketon"+DEFAULT_PORT);第54页,课件共91页,创作于2023年2月55Stringline=in.nextLine();System.out.println(line);StringuserInput=null;while(true){System.out.print(PROMPT);//PromptStringuserInput=sin.nextLine();//Readinglineofkeyboardinputif(userInput.trim().toUpperCase().startsWith(SIGNOFF_TOKEN)){out.println(userInput);//WriteittoServerviasocketline=in.nextLine();//Readserver'sreplyfromsocketSystem.out.println("Serverreply:"+line);break;}else{out.println(userInput);//WriteittoServerviasocket}}}staticprivatefinalintDEFAULT_PORT=8189;staticprivatefinalStringDEFAULT_SERVER="localhost";staticprivatefinalStringPROMPT=">>";staticprivatefinalStringSIGNOFF_TOKEN="BYE";}第55页,课件共91页,创作于2023年2月56每请求每线程的服务器publicclassUnboundedServer{

publicstaticvoidmain(String[]args)throwsIOException{ServerSocketserverSocket=null;System.out.println("CreatinServerSocketon"+DEFAULT_PORT);serverSocket=newServerSocket(DEFAULT_PORT);第56页,课件共91页,创作于2023年2月57while(true){System.out.println("Lookingforaclient...");//blocksuntilclientconnectsfinalSocketclientSocket=serverSocket.accept();//onerequest,oneexecutor;oneexecutoronthread.ExecutorServiceec=Executors.newSingleThreadExecutor();Runnableresponse=newRunnable(){publicvoidrun(){try{handleRequest(clientSocket);}catch(IOExceptionex){System.err.println(ex.getMessage());}}};ec.execute(response);//launchandmanagethethreadec.shutdown();//shutdownthethread}}第57页,课件共91页,创作于2023年2月58privatestaticvoidhandleRequest(SocketclientSocket)throwsIOException{System.out.println("Aclientconnected.");Scannerin=newScanner(clientSocket.getInputStream());PrintWriterout=newPrintWriter(clientSocket.getOutputStream(),true);out.println("Hello!EnterBYEtoexit.");Stringline;while(true){line=in.nextLine();System.out.println(line);//Printsonserversideif(line.trim().toUpperCase().startsWith(SIGN_OFF_TOKEN)){out.println("Byebye,Seeyoulater!");//clientsideoutputSystem.out.println("Clientsignedoff");break;}}}staticprivatefinalintDEFAULT_PORT=8189;staticprivatefinalStringSIGN_OFF_TOKEN="BYE";}第58页,课件共91页,创作于2023年2月59每请求每线程特点1main线程只负责监听客户连接请求;一旦有客户请求连接,

main线程创建一个新的线程专门处理该连接;用以处理客户请求的代码(handleRequest)

必须设计为线程安全的。第59页,课件共91页,创作于2023年2月60线程池服务器实现使用线程池可以控制稳定性。线程池管理一定数目的线程,当并发线程数目达到上限后,将停止创建新的线程,阻塞创建请求直到有线程终止第60页,课件共91页,创作于2023年2月61publicclassPooledServer{publicstaticvoidmain(String[]args)throwsIOException{ServerSocketserverSocket=null;System.out.println("CreatinServerSocketon"+DEFAULT_PORT);serverSocket=newServerSocket(DEFAULT_PORT);ExecutorServiceec=

Executors.newFixedThreadPool(THREADS_THRESHOLD);第61页,课件共91页,创作于2023年2月62while(true){System.out.println("Lookingforaclient...");//blocksuntilclientconnectsfinalSocketclientSocket=serverSocket.accept();//onerequest,oneexecutor;oneexecutoronthread.Runnableresponse=newRunnable(){publicvoidrun(){try{handleRequest(clientSocket);}catch(IOExceptionex){

System.err.println(ex.getMessage());

}}};ec.execute(response);}

ec.shutdown();}第62页,课件共91页,创作于2023年2月63privatestaticvoidhandleRequest(SocketclientSocket)throwsIOException{System.out.println("Aclientconnected.");Scannerin=newScanner(clientSocket.getInputStream());PrintWriterout=newPrintWriter(clientSocket.getOutputStream(),true);out.println("Hello!EnterBYEtoexit.");Stringline;while(true){line=in.nextLine();System.out.println(line);//Printsonserversideif(line.trim().toUpperCase().startsWith(SIGN_OFF_TOKEN)){out.println("Byebye,Seeyoulater!");//clientsideoutputSystem.out.println("Clientsignedoff");break;}}第63页,课件共91页,创作于2023年2月64}staticprivatefinalintDEFAULT_PORT=8189;staticprivatefinalStringSIGN_OFF_TOKEN="BYE";privatestaticfinalintTHREADS_THRESHOLD=128;}第64页,课件共91页,创作于2023年2月65线程池优点线程池大小的参数防范了系统崩溃的风险,仔细地调整线程池大小的参数,也可以对性能调优第65页,课件共91页,创作于2023年2月66

基于UDP协议的数据报和套接字

用户数据报协议UDP与TCP协议相反,它并不刻意追求数据报会完全发送出去,也不能担保它们抵达的顺序与它们发出时是一样的,是一种不可靠数据传输协议。比TCP协议具有开销少、传输速度快。

第66页,课件共91页,创作于2023年2月67UDP概述Java中实现UDP协议的两个类DatagramPacket数据包类:将数据打成UDP数据包,也可将接收的UDP数据包解包成数据;DatagramSocket数据报套接字类:用于发送和接收UDP数据报。不分客户端和服务器套接字。用户接收数据时,从DatagramSocket接收DatagramPacket对象,并读取数据包的内容。第67页,课件共91页,创作于2023年2月68DatagramPacket类数据包DatagramPacket类所定义的对象表示为一个数据包,依据设定可确定数据包的大小。每个数据包中应该包含:源和目标地址、源和目标端口这些信息。才能在网络上通过路由器选定的路径传输,从始发源主机传送到目的主机。第68页,课件共91页,创作于2023年2月691.DatagramPacket的定义和构造函数定义:publicfinalclassDatagramPacketextendsObject构造函数:publicDatagramPacket(byte[]buf,intlength):buf表示接收数据的缓冲区;length表示接收数据的最大长度,它必须小于等于buf.length,通常为buf的长度。publicDatagramPacket(byte[]buf,intoffset,intlength):offset为在缓冲区中指定了偏移量。publicDatagramPacket(byte[]buf,intlength,InetAddressaddress,intport):创建数据报包。buf中存放发送的数据;length表示发送数据的长度;address表示目的地址;port表示目的端口号。DatagramPacket(byte[]buf,intoffset,intlength,InetAddressaddress,intport):offset为在缓冲区中指定了偏移量。第69页,课件共91页,创作于2023年2月702.常用方法publicInetAddressgetAddress():发送数据包时,返回接收数据包的主机的IP地址;接收数据包时,返回发出数据包的主机IP地址。publicintgetPort():发送数据包时,返回接收数据包的主机端口号;接收数据包时,返回发出数据包的主机端口号。publicintgetLength():返回被接收或发送的数据的长度。publicbyte[]getData():返回被接收或发送的缓冲区数据。publicintgetOffset():返回被接收或发送的数据的偏移量。publicvoidsetAddress(InetAddressiaddr):发送数据包时,设置返回接收数据包的主机IP地址;接收数据包时,设置返回发出数据包的主机IP地址。publicvoidsetPort(intiport):远程主机上的端口号。publicvoidsetLength(intlength):为此包设置长度。publicvoidsetData(byte[]buf):数据缓冲区。第70页,课件共91页,创作于2023年2月71DatagramSocket类在客户端和服务器都需要建立一个DatagramSocket对象,然后通过receive()方法接收数据包,通过send()方法发送数据包。无须像TCP协议套接字一样,还要建立会话流来传送数据。1.DatagramSocket的定义和构造函数2.常用方法第71页,课件共91页,创作于2023年2月721.DatagramSocket的定义和构造函数定义:publicclassDatagramSocketextendsObject构造函数:publicDatagramSocket()throwsSocketException:创建数据报套接字,系统自动将它与本地主机上的某个可使用的端口绑定在一起。publicDatagramSocket(intport)throwsSocketException:创建数据报套接字,并将它与本地主机的一个指定的端口(port)绑定在一起。publicDatagramSocket(intport,InetAddressladdr)throwsSocketException:创建数据报套接字,将其绑定到指定的本地laddr地址和端口port。抛出异常SocketException:如果数据报套接字不能被创建或不能与本地端口联系起来,就抛出异常。第72页,课件共91页,创作于2023年2月732.常用方法publicvoidreceive(DatagramPacketp)throwsIOException:从数据报套接字接收一个数据包。本方法返回时,数据包p中存放被接收的数据,且数据包中也含有发送地的IP地址和端口号。如果发生IO错误,就抛出异常IOException。publicvoidsend(DatagramPacketp)throwsIOException:发送数据包DatagramPacket将包括数据内容、数据长度、目的IP地址和端口的信息。抛出异常IOException。publicvoidclose():关闭套接字。publicInetAddressgetLocalAddress():获取套接字绑定的本地地址。publicintgetLocalPort():获取此套接字绑定的本地主机上的端口号第73页,课件共91页,创作于2023年2月74

构建UDP客户端/服务器服务器:建立数据包DatagramPacket的对象,未知客户端的IP和Port,但需要设置数据缓冲区的大小。建立数据报套接字DatagramSocket的对象时,需要确定和绑定服务器端口Port,以便由此端口接收客户端数据包。服务器先接收客户端发来的数据包,然后发送数据包。客户端:建立数据包DatagramPacket的对象时,必须已知目的(服务器)InetAddress地址和端口Port,并设置,以便数据包发送至目的地,确定数据包缓冲区大小。建立数据报套接字DatagramSocket的对象时,可不设定端口,系统自动获取客户端端口Port。客户端先发送数据包,后接收数据包。第74页,课件共91页,创作于2023年2月75例程:UDP协议服务器程序UDPServer.javaimport.*;publicclassUDPServer{publicstaticfinalintPORT=8765; //服务器端口publicstaticvoidmain(Stringargs[]){try{//建立指定端口Port的数据报套接字对象

DatagramSocketdgs=newDatagramSocket(PORTbyte[]buf=newbyte[1024];

DatagramPacketp=newDatagramPacket(buf,buf.length);System.out.println("服务器启动!");

第75页,课件共91页,创作于2023年2月76例:UDP协议服务器程序UDPServer.javafor(inti=0;i<3;i++){dgs.receive(p); //服务器收到数据包,带有客户端的IP和PortSystem.out.println("服务器收到数据报:#"+i+";"+newString(p.getData(),0,p.getLength()));dgs.send(p); //向客户端发送带有客户端的IP和Port的数据包p}}catch(Exceptione){e.printStackTrace();}}}第76页,课件共91页,创作于2023年2月77例:UDP协议客户端程序UDPClient.javaimport.*;publicclassUDPClient4_10extendsObject{publicstaticInetAddressia;pub

温馨提示

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

评论

0/150

提交评论