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

下载本文档

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

文档简介

1、1,Socket编程,参考:Java 网络编程原理与JSP Web开发核心技术 马晓敏 等编著 中国铁道出版社 2010年3月,网络API,API:应用程序编程接口 Java网络应用程序编程接口( 包) Socket接口 RMI: Remote Method Invocation远程方法调用 UNIX Berkeley sockets import .*; public class Client public static void main(String args) throws IOException / 建立Socket,服务器在本机的8888端口处进行“侦听” Socket socke

2、t =new Socket(,8888); /建立套接字 System.out.println(客户端套接字信息:+ socket); try / 套接字建立成功后,建立字节输入流dis和输出流dos对象 DataInputStream dis=new DataInputStream(socket.getInputStream(); DataOutputStream dos=new DataOutputStream(socket.getOutputStream(); / 调用其对应方法进行网络通信 for(int i=0;i6;i+) dos.writeUTF(客户端测试:+

3、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 ,36, 基于套接字的具有缓冲的字符输入流和字符输出流的

4、创建,import java.io.*; import .*; public class Client public static void main(String args) throws IOException / 建立Socket,服务器在本机的8888端口处进行“侦听” Socket socket =new Socket(,8888); /建立套接字 try / 套接字建立成功后,通过转换器建立字符输入流br和自动刷新输出流pw BufferedReader br= new BufferedReader( new InputStreamReader ( socket.

5、getInputStream(); PrintWriter pw = new PrintWriter( new BufferedWriter( new OutputStreamWriter( socket.getOutputStream(),true);,转换器,转换器,37,/ 调用其对应方法进行网络通信 for(int i=0;i10;i+) /向服务器发数据,并自动刷新输出缓冲区 pw.println(测试:+i); String str = br.readLine(); /从服务器接收数据 System.out.println(str); /将从服务器接收的数据输出 /向服务器发送终止

6、标志,并自动刷新输出缓冲区 pw.println(end); / 关闭对象 pw.close(); /关闭输出流对象pw br.close(); /关闭输入流对象br finally System.out.println(结束); socket.close(); /关闭套接字对象socket ,38,TCP套接字,一个套接字Socket就是在网络上运行的两个程序间的双向通信通道的一个端点,两个程序通过各自的套接字实现程序间的与网络拓扑结构无关的通信。 客户端程序和服务器必须使用同样的通信协议,这就是TCP协议,即它们在传送的信息所使用的语言上达成一致。 在Java的包中提供了两个套接字类,如客

7、户端程序的套接字Socket和服务器端的套接字ServerSocket,它们很好地支持了TCP套接字。 套接字通信是利用IP地址和端口Port进行的,是一种基础性的底层连接。一般步骤是: 首先,服务器“侦听”其端口进入的连接。 其次,客户端套接字与服务器的端口连接建立套接字级别的连接通道。 再次,客户端与服务器分别通过绑定和套接字连接通道的输入输出流操作,实现网络通信与服务。,39,Socket类,Socket类为客户端的通信套接字。以下三个功能: 由构造函数,定义指定远端IP地址、端口进行连接通信的通信套接字socket。 将此socket以字节输入流和输出流的形式返回,当与数据输入流和输出

8、流绑定,便可实现客户端的网络通信。 也可通过方法获得已连接的socket的远端IP地址、端口。,1Socket定义和构造函数 2返回输入流和输出流的方法 3获取Socket信息方法,40,1Socket定义和构造函数,Socket构造函数均为public修饰类型,如果创建socket时发生I/O错误,均抛出IOException异常。定义和常用的构造函数如下: 定义:public class Socket extends Object 构造函数: Socket(InetAddress address,int port) 创建一个socket并与指定的IP地址的指定的端口相连接。address为

9、指定的IP地址。port为指定的端口。 Socket(String host,int port) 创建一个socket并与指定的主机的指定的端口相连接。host为指定的主机的字符串名。port为指定的端口。如果无法确定主机的IP地址还抛出UnknownHostException异常。,41,2获取输入流和输出流的方法,public InputStream getInputStream() throws IOException 返回此套接字的输入流。 public OutputStream getOutputStream() throws IOException 返回此套接字的输出流。 套接字建

10、立成功后,建立字节输入流dis和输出流dos对象: DataInputStream dis=new DataInputStream(socket.getInputStream(); DataOutputStream dos=new DataOutputStream(socket.getOutputStream();,42,3获取Socket信息方法,此类方法可获取socket所连接的远端IP地址、端口号,及所绑定的本地IP地址、端口号。另外,socket用完需要用方法关闭。方法如下: public InetAddress getInetAddress() 获取socket所连接的远端IP地址。

11、 public InetAddress getLocalAddress() 获取socket所绑定的本地IP地址。 public int getPort() 获取socket所连接的远端端口号。 public int getLocalPort() 获取socket所绑定到的本地端口号。 public void close() throws IOException 关闭socket。 String toString() 将此socket转换为String。,43,ServerSocket类,ServerSocket类为服务器的通信套接字。用来侦听客户端请求的连接,并为每个新连接创建一个socke

12、t对象,由此创建绑定此socket的输入流和输出流,与客户端实现网络通信。 1定义与构造函数 2常用成员方法,44,1ServerScket定义与构造函数,定义: public class ServerSocket extends Object 构造函数: ServerSocket(int port) 在所给定的用来侦听的端口上建立一个服务器套接字。如果端口号为零,则在任意的空闲的端口上创建一个服务器套接字。外来连接请求的数量默认最大为50。port参数为在服务器上所指定的用来侦听的端口。 ServerSocket(int port,int backlog) 在所给定的用来侦听的端口上建立一个

13、服务器套接字。如果端口号为零,则在任意的空闲的端口上创建一个服务器套接字。外来连接请求的最大连接数量由backlog指定。,45,2常用成员方法,此类方法关键是侦听连接端口,建立与客户端的套接字连接。服务器套接字用完需要用方法关闭。方法如下: public Socket accept() throws IOException 侦听并接收指向本套接字的连接,返回客户端连接套接字。本方法将造成阻塞直到连接成功。如果在等待连接时套接字发生I/O错误,则抛出异常IOException。 public void close() throws IOException 关闭本ServerSocket。如果在

14、关闭本ServerSocket时发生I/O错误,则抛出异常IOException。 public InetAddress getInetAddress() 获取此服务器端套接字的本地IP地址。 public int getLocalPort() 获取此套接字侦听的端口。 String toString() 作为String返回此套接字的实现IP地址和实现端口。,46,建立数据输入流过程,服务器端程序。建立数据输入流dis和输出流过程类似。以创建和使用输入流dis为例。,ServerSocket s=new ServerSocket(PORT);,DataInputStream dis=:,侦听

15、PORT端口,获得客户端套接字 Socket ss=s.accept();,new DataInputStream(ss.getInputStream();,while(true) /从客户端中读数据 String str=dis.readUTF(); ,创建捆绑客户端套接字的数据输入流,建立服务器 ServerSocket套接字,通过数据 输入流操作 读取数据,47,例程 服务器端程序DS_Server.java,import java.io.*; import .*; public class DS_Server public static final int PORT=8888; pub

16、lic static void main(String args) throws IOException ServerSocket s=new ServerSocket(PORT); /建立服务器ServerSocket套接字 System.out.println(服务器套接字信息:+s); try /程序阻塞,等待连接。即直到有一个客户请求到达,程序方能继续执行 Socket ss=s.accept(); /侦听PORT端口,获得客户端套接字 System.out.println(套接字接收到的信息:+ss); /连接成功,建立相应的数据输入输出流 DataInputStream dis=n

17、ew DataInputStream(ss.getInputStream(); DataOutputStream dos=new DataOutputStream(ss.getOutputStream(); /在死循环中,来与客户端通信 while(true)/ String str=dis.readUTF();/从客户端中读数据 if(str.equals(end)break;/当读到end时,程序终止 System.out.println(str); dos.writeUTF(服务器应答:+str);/向客户端中写数据 dos.close(); /关闭输出流对象dos dis.close(

18、); /关闭输入流对象dis ss.close(); /关闭套接字 finallySystem.out.println(服务器结束); s.close(); /关闭服务器套接字 ,48,异常处理,IOException异常 Socket类出现异常:在创建套接字时、在连接期间发生错误时、关闭套接字时、绑定操作失败或者已经绑定了套接字时、在创建输入流时或没有关闭套接字或没有连接套接字或关闭了套接字输入、创建输出流时或者没有连接套接字时,系统均会抛出IOException异常。 ServerSocket类也会发生I/O错误,出现异常:在打开套接字时、关闭套接字时、绑定操作失败或者已经绑定了套接字、等

19、待连接时,系统则会抛出IOException异常。 这类通用的异常,采用try/catch/finally结构来抛出、捕捉和处理。,49,异常处理,BindException 试图将套接字绑定到本地地址和端口时发生错误,通常是端口正在使用或无法分配所请求的本地地址。 ConnectException 试图将套接字连接到远程地址和端口时发生错误,通常是远程拒绝连接。 NoRouteToHostException 试图将套接字连接到远程地址和端口时发生错误,通常是无法到达远程主机。 InterruptedIOException I/O操作已中断。 UnKnownHostException 无法确定

20、主机的IP地址。 IllEgalArgumentException 方法参数错误。,50,TCP网络通信实例,在上例中,为单线程通信。用多线程机制实现服务器能同时处理多个客户端的请求。 常用的方法是在服务器程序中,accept()返回一个socket后,就用它新建一个线程,令一个线程只为它特定的客户服务。然后再调用accept(),等待下一次新的连接请求,同时产生下一个新的客户线程。,51,public class SingleThreadEchoServer public static void main(String args) throws IOException static priv

21、ate final int DEFAULT_PORT = 8189; static private final String SIGN_OFF_TOKEN = BYE; ServerSocket serverSocket = null; Socket clientSocket = null; System.out.println(Creatin ServerSocket on + DEFAULT_PORT); serverSocket = new ServerSocket(DEFAULT_PORT); while (true) System.out.println(Looking for a

22、client. ); clientSocket = serverSocket.accept(); / blocks until client connects handleRequest(clientSocket); ,单线程服务器实现,52,private static void handleRequest(Socket clientSocket) throws IOException System.out.println(A client connected.); Scanner in = new Scanner(clientSocket.getInputStream(); PrintWr

23、iter out = new PrintWriter(clientSocket.getOutputStream(), true); out.println(Hello! Enter BYE to exit.);,53,String line; while (true) line = in.nextLine(); System.out.println(line); / Prints on server side if (line.trim().toUpperCase().startsWith(SIGN_OFF_TOKEN) out.println(Bye bye, See you later!)

24、; / client side output System.out.println(Client signed off); break; ,54,public class EchoClient public static void main(String args) throws IOException Socket echoSocket = new Socket(DEFAULT_SERVER, DEFAULT_PORT); PrintWriter out = new PrintWriter(echoSocket.getOutputStream(), true); Scanner in = n

25、ew Scanner(echoSocket.getInputStream(); Scanner sin = new Scanner(System.in); System.out.println(Creating Socket on + DEFAULT_PORT);,55,String line = in.nextLine(); System.out.println(line); String userInput = null; while (true) System.out.print(PROMPT); / Prompt String userInput = sin.nextLine(); /

26、 Reading line of keyboard input if (userInput.trim().toUpperCase().startsWith(SIGNOFF_TOKEN) out.println(userInput); / Write it to Server via socket line = in.nextLine(); / Read servers reply from socket System.out.println(Server reply: + line); break; else out.println(userInput); / Write it to Serv

27、er via socket static private final int DEFAULT_PORT = 8189; static private final String DEFAULT_SERVER = localhost; static private final String PROMPT = ; static private final String SIGNOFF_TOKEN = BYE; ,56,每请求每线程的服务器,public class UnboundedServer public static void main(String args) throws IOExcept

28、ion ServerSocket serverSocket = null; System.out.println(Creatin ServerSocket on + DEFAULT_PORT); serverSocket = new ServerSocket(DEFAULT_PORT);,57,while (true) System.out.println(Looking for a client. ); / blocks until client connects final Socket clientSocket = serverSocket.accept(); / one request

29、, one executor; one executor on thread. ExecutorService ec = Executors.newSingleThreadExecutor(); Runnable response = new Runnable() public void run() try handleRequest(clientSocket); catch (IOException ex) System.err.println(ex.getMessage(); ; ec.execute(response);/launch and manage the thread ec.s

30、hutdown();/shutdown the thread ,58,private static void handleRequest(Socket clientSocket) throws IOException System.out.println(A client connected.); Scanner in = new Scanner(clientSocket.getInputStream(); PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); out.println(Hello! En

31、ter BYE to exit.); String line; while (true) line = in.nextLine(); System.out.println(line); / Prints on server side if (line.trim().toUpperCase().startsWith(SIGN_OFF_TOKEN) out.println(Bye bye, See you later!); / client side output System.out.println(Client signed off); break; static private final

32、int DEFAULT_PORT = 8189; static private final String SIGN_OFF_TOKEN = BYE; ,59,每请求每线程特点,1main线程只负责监听客户连接请求; 一旦有客户请求连接,main线程创建一个新的线程专门处理该连接; 用以处理客户请求的代码(handleRequest)必须设计为线程安全的。,60,线程池服务器实现,使用线程池可以控制稳定性。线程池管理一定数目的线程,当并发线程数目达到上限后,将停止创建新的线程,阻塞创建请求直到有线程终止,61,public class PooledServer public static voi

33、d main(String args) throws IOException ServerSocket serverSocket = null; System.out.println(Creatin ServerSocket on + DEFAULT_PORT); serverSocket = new ServerSocket(DEFAULT_PORT); ExecutorService ec = Executors.newFixedThreadPool(THREADS_THRESHOLD);,62,while (true) System.out.println(Looking for a c

34、lient. ); / blocks until client connects final Socket clientSocket = serverSocket.accept(); / one request, one executor; one executor on thread. Runnable response = new Runnable() public void run() try handleRequest(clientSocket); catch (IOException ex) System.err.println(ex.getMessage(); ; ec.execu

35、te(response); ec.shutdown(); ,63,private static void handleRequest(Socket clientSocket) throws IOException System.out.println(A client connected.); Scanner in = new Scanner(clientSocket.getInputStream(); PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); out.println(Hello! Ente

36、r BYE to exit.); String line; while (true) line = in.nextLine(); System.out.println(line); / Prints on server side if (line.trim().toUpperCase().startsWith(SIGN_OFF_TOKEN) out.println(Bye bye, See you later!); / client side output System.out.println(Client signed off); break; ,64, static private fin

37、al int DEFAULT_PORT = 8189; static private final String SIGN_OFF_TOKEN = BYE; private static final int THREADS_THRESHOLD = 128; ,65,线程池优点,线程池大小的参数防范了系统崩溃的风险,仔细地调整线程池大小的参数,也可以对性能调优,66,基于UDP协议的数据报和套接字,用户数据报协议UDP与TCP协议相反,它并不刻意追求数据报会完全发送出去,也不能担保它们抵达的顺序与它们发出时是一样的,是一种不可靠数据传输协议。比TCP协议具有开销少、传输速度快。,67,UDP概述,

38、Java中实现UDP协议的两个类 DatagramPacket数据包类:将数据打成UDP数据包,也可将接收的UDP数据包解包成数据; DatagramSocket数据报套接字类:用于发送和接收UDP数据报。不分客户端和服务器套接字。 用户接收数据时,从DatagramSocket接收DatagramPacket对象,并读取数据包的内容。,68,DatagramPacket类,数据包DatagramPacket类所定义的对象表示为一个数据包,依据设定可确定数据包的大小。 每个数据包中应该包含:源和目标地址、源和目标端口这些信息。才能在网络上通过路由器选定的路径传输,从始发源主机传送到目的主机。,

39、69,1DatagramPacket的定义和构造函数,定义:public final class DatagramPacket extends Object 构造函数: public DatagramPacket(byte buf,int length): buf表示接收数据的缓冲区;length表示接收数据的最大长度,它必须小于等于buf.length,通常为buf的长度。 public DatagramPacket(byte buf,int offset,int length): offset为在缓冲区中指定了偏移量。 public DatagramPacket(byte buf,int

40、length,InetAddress address,int port): 创建数据报包。buf中存放发送的数据;length表示发送数据的长度;address表示目的地址;port表示目的端口号。 DatagramPacket(byte buf,int offset, int length,InetAddress address,int port): offset为在缓冲区中指定了偏移量。,70,2常用方法,public InetAddress getAddress():发送数据包时,返回接收数据包的主机的IP地址;接收数据包时,返回发出数据包的主机IP地址。 public int getP

41、ort():发送数据包时,返回接收数据包的主机端口号;接收数据包时,返回发出数据包的主机端口号。 public int getLength():返回被接收或发送的数据的长度。 public byte getData():返回被接收或发送的缓冲区数据。 public int getOffset():返回被接收或发送的数据的偏移量。 public void setAddress(InetAddress iaddr): 发送数据包时,设置返回接收数据包的主机IP地址;接收数据包时,设置返回发出数据包的主机IP地址。 public void setPort(int iport):远程主机上的端口号。

42、public void setLength(int length):为此包设置长度。 public void setData(byte buf):数据缓冲区。,71,DatagramSocket类,在客户端和服务器都需要建立一个DatagramSocket对象,然后通过receive()方法接收数据包,通过send()方法发送数据包。无须像TCP协议套接字一样,还要建立会话流来传送数据。 1DatagramSocket的定义和构造函数 2常用方法,72,1DatagramSocket的定义和构造函数,定义:public class DatagramSocket extends Object 构

43、造函数: public DatagramSocket() throws SocketException:创建数据报套接字,系统自动将它与本地主机上的某个可使用的端口绑定在一起。 public DatagramSocket(int port) throws SocketException:创建数据报套接字,并将它与本地主机的一个指定的端口(port) 绑定在一起。 public DatagramSocket(int port,InetAddress laddr) throws SocketException:创建数据报套接字,将其绑定到指定的本地laddr地址和端口port。 抛出异常Socke

44、tException:如果数据报套接字不能被创建或不能与本地端口联系起来,就抛出异常。,73,2常用方法,public void receive(DatagramPacket p) throws IOException:从数据报套接字接收一个数据包。本方法返回时,数据包p中存放被接收的数据,且数据包中也含有发送地的IP地址和端口号。如果发生IO错误,就抛出异常IOException。 public void send(DatagramPacket p) throws IOException:发送数据包DatagramPacket将包括数据内容、数据长度、目的IP地址和端口的信息。抛出异常IOE

45、xception。 public void close():关闭套接字。 public InetAddress getLocalAddress():获取套接字绑定的本地地址。 public int getLocalPort():获取此套接字绑定的本地主机上的端口号,74,构建UDP客户端/服务器,服务器: 建立数据包DatagramPacket的对象,未知客户端的IP和Port,但需要设置数据缓冲区的大小。 建立数据报套接字DatagramSocket的对象时,需要确定和绑定服务器端口Port,以便由此端口接收客户端数据包。服务器先接收客户端发来的数据包,然后发送数据包。 客户端 : 建立数据

46、包DatagramPacket的对象时,必须已知目的(服务器)InetAddress地址和端口Port,并设置,以便数据包发送至目的地,确定数据包缓冲区大小。 建立数据报套接字Datagram Socket的对象时,可不设定端口,系统自动获取客户端端口Port。客户端先发送数据包,后接收数据包。,75,例程:UDP协议服务器程序UDPServer.java,import .*; public class UDPServer public static final int PORT=8765; /服务器端口 public static void main(String args ) try /建

47、立指定端口Port的数据报套接字对象 DatagramSocket dgs = new DatagramSocket(PORT byte buf=new byte1024; DatagramPacket p=new DatagramPacket(buf, buf.length); System.out.println(服务器启动!);,76,例:UDP协议服务器程序UDPServer.java,for(int i=0;i3;i+) dgs.receive(p); /服务器收到数据包,带有客户端的IP和Port System.out.println(服务器收到数据报:#+i+; +new Str

48、ing(p.getData(),0,p.getLength(); dgs.send(p); /向客户端发送带有客户端的IP和Port的数据包p catch(Exception e) e.printStackTrace( ); ,77,例:UDP协议客户端程序UDPClient.java,import .*; public class UDPClient4_10 extends Object public static InetAddress ia; public static final int PORT=8765; /服务器端口 public static String str=你好!; /发送内容 public static void main(String args ) try/服务器主机IP地址 ia=InetAddress.getLocalHost(); /数据报套接字对象,自动分配端口号 DatagramS

温馨提示

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

评论

0/150

提交评论