URL类 URL对象-最基本的三部分信息:协议、地址、资源
http、ftp、file协议都是JVM支持的协议
地址必须是能连接的有效的IP地址或域名(host name)
资源可以是主机上的任何一个文件
IP: Internet Protocol
DNS: Domain Name Servers,用来把host name转换成IP地址
URL的构造方法 1 2 3 4 5 6 7 8 9 10 11 12 13 try { url=new URL ("http://yahoo.com.cn" ); } catch (MalformedURLException e) { System.out.println("Bad URL:" +url); }
读取URL中的资源 URL对象调用 InputStream openStream()
该方法可以返回一个输入流,该输入流指向URL对象所包含的资源。 通过该输入流可以将服务器上的资源信息读入到客户端。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.net.*; import java.io.*; public class Example11_1 { public static void main (String args[]) { new NetWin (); } } class NetWin extends JFrame implements ActionListener , Runnable { JButton button; URL url; JTextField text; JTextArea area; byte b[] = new byte [118 ]; Thread thread; NetWin() { text = new JTextField (20 ); area = new JTextArea (12 ,12 ); add(new JScrollPane (area), BorderLayout.CENTER); button = new JButton ("确定" ); button.addActionListener(this ); JPanel p = new JPanel (); p.add(new JLabel ("输入网址:" )); p.add(text); p.add(button); add(p, BorderLayout.NORTH); setBounds(60 , 60 , 360 , 300 ); setVisible(true ); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); thread = new Thread (this ); } public void actionPerformed (ActionEvent e) { if ( !(thread.isAlive()) ) { thread = new Thread (this ); } try { thread.start(); } catch (Exception ee){} } public void run () { try { url = new URL (text.getText().trim()); int n = -1 ; area.setText(null ); InputStream in = url.openStream(); while ( (n=in.read(b)) != -1 ) { String s = new String (b,0 ,n); area.append(s); } } catch (MalformedURLException e1) { text.setText( "" + e1 ); return ; } catch (IOException e1) { text.setText( "" + e1 ); return ; } } }
显示URL资源中的HTML文件 javax.swing包中的JEditorPane类可以解释执行html文件 把html文件读入到JEditorPane,该html文件就会被解释执行,显示在JEditorPane中JEditorPane类的构造方法: public JEditorPane()
public JEditorPane(URL initialPage) throws IOException
public JEditorPane(String url) throws IOException
• 后两个构造方法使用参数initialPage
或url
指定最初的URL中的资源。 • JEditorPane
对象调用public void setPage(URL page) throws IOException
可以显示新的URL中的资源。
1 2 3 4 url = new URL (text.getText().trim()); int n=-1 ; editPane.setText(null ); editPane.setPage(url);
处理超链接 通过处理HyperlinkEvent事件,来显示新的URL中的资源 JEditorPane对象调用addHyperlinkListener(HyperlinkListener listener)获得监视器。 监视器需要实现HyperlinkListener接口,该接口中的方法是 void hyperlinkUpdate(HyperlinkEvent e)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 editPane.addHyperlinkListener(new HyperlinkListener () { public void hyperlinkUpdate (HyperlinkEvent e) { if (e.getEventType()==HyperlinkEvent.EventType.ACTIVATED) { try { editPane.setPage(e.getURL()); } catch (IOException e1) { editPane.setText("" +e1); } } } }
InetAddress类 InetAddress类的对象含有一个Internet主机地址的域名 和IP地址 ,例如:www.sina.com.cn
/157.255.224.244
域名容易记忆,当你在连接网络时输入一个主机地址的域名后,域名服务器(Domain Name Servers, DNS)负责将域名转化为IP地址,这样我们才能和主机建立连接。
获取Internet上主机的地址 InetAddress类的静态方法: getByName(String s);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.net.*; public class Example11_4 { public static void main (String args[]) { try { InetAddress address_1 = InetAddress.getByName("www.sina.com.cn" ); System.out.println( address_1.toString() ); System.out.println( address_1.getHostName() ); System.out.println( address_1.getHostAddress() ); } catch (UnknownHostException e) { System.out.println("无法找到www.sina.com.cn" ); } } }
套接字Socket 端口号 与IP地址 的组合得到一个网络套接字 。 端口号被规定为一个16位的整数065535。 01023被预先定义的服务通信占用(如telnet占用端口23,http占用端口80等)。 除非我们需要访问这些特定的服务,否则,就应该使用1024~65535这些端口中的某一个进行通信,以免发生端口冲突。
套接字连接 客户端的套接字对象 和 服务器端的套接字对象 通过 输入流和输出流 连接在一起
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 try { ServerSocket waitSocketConnection = new ServerSocket (1880 ); } catch (IOException e){} Socket socketAtServer = waitSocketConnection.accept(); Socket socketAtClient = new Socket (localhost, 1880 ); public Socket ()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 import java.io.*; import java.net.*; public class Server { public static void main (String args[]) { ServerSocket server = null ; Socket socketAtServer = null ; DataOutputStream out = null ; DataInputStream in = null ; try { server = new ServerSocket (4333 ); } catch (IOException e1) { System.out.println("ERRO:" +e1); } try { socketAtServer = server.accept(); in = new DataInputStream (socketAtServer.getInputStream()); out = new DataOutputStream (socketAtServer.getOutputStream()); while (true ) { int m = 0 ; m = in.readInt(); out.writeInt(m*2 ); System.out.println("Server received: " + m); Thread.sleep(500 ); } } catch (IOException e) { System.out.println("" +e); } catch (InterruptedException e){} } } import java.io.*; import java.net.*; public class Client { public static void main (String args[]) { Socket socketAtClient; DataInputStream in = null ; DataOutputStream out = null ; try { socketAtClient = new Socket ("localhost" , 4333 ); in = new DataInputStream (socketAtClient.getInputStream()); out = new DataOutputStream (socketAtClient.getOutputStream()); out.writeInt(1 ); while (true ) { int m2 = 0 ; m2 = in.readInt(); out.writeInt(m2); System.out.println("Client received: " + m2); Thread.sleep(500 ); } } catch (IOException e) { System.out.println("Unable to connect to the server" ); } catch (InterruptedException e){} } }
使用多线程处理套接字连接 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 import java.io.*; import java.net.*; import java.util.*; public class MutiServer { public static void main (String args[]) { ServerSocket server = null ; Socket socketAtServer = null ; while (true ) { try { server = new ServerSocket (4332 ); } catch (IOException e1) { System.out.println("正在监听" ); } try { socketAtServer = server.accept(); System.out.println("客户的地址:" + socketAtServer.getInetAddress()); } catch (IOException e) { System.out.println("正在等待客户" ); } if (socketAtServer!=null ) { new ServerThread (socketAtServer).start(); } else { continue ; } } } } class ServerThread extends Thread { Socket socket; DataOutputStream out = null ; DataInputStream in = null ; String s = null ; ServerThread(Socket t) { socket = t; try { in = new DataInputStream (socket.getInputStream()); out = new DataOutputStream (socket.getOutputStream()); } catch (IOException e){} } public void run () { while (true ) { double a=0 ,b=0 ,c=0 ,root1=0 ,root2=0 ; try { a = in.readDouble(); b = in.readDouble(); c = in.readDouble(); double disk=b*b-4 *a*c; root1 = (-b+Math.sqrt(disk))/(2 *a); root2 = (-b-Math.sqrt(disk))/(2 *a); out.writeDouble(root1); out.writeDouble(root2); } catch (IOException e) { System.out.println("客户离开" ); break ; } } } } import java.net.*; import java.io.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class ClientFrame extends JFrame implements Runnable , ActionListener { JButton connection,computer; JTextField inputA,inputB,inputC; JTextArea showResult; Socket socket = null ; DataInputStream in = null ; DataOutputStream out = null ; public ClientFrame () { socket = new Socket (); connection = new JButton ("连接服务器" ); connection.addActionListener(this ); computer = new JButton ("求方程的根" ); computer.setEnabled(false ); computer.addActionListener(this ); inputA = new JTextField ("0" ,12 ); inputB = new JTextField ("0" ,12 ); inputC = new JTextField ("0" ,12 ); Box boxV1 = Box.createVerticalBox(); boxV1.add(new JLabel ("输入2次项系数" )); boxV1.add(new JLabel ("输入1次项系数" )); boxV1.add(new JLabel ("输入常数项" )); Box boxV2 = Box.createVerticalBox(); boxV2.add(inputA); boxV2.add(inputB); boxV2.add(inputC); Box baseBox = Box.createHorizontalBox(); baseBox.add(boxV1); baseBox.add(boxV2); showResult = new JTextArea (8 ,18 ); showResult = new JTextArea (8 ,18 ); Container con = getContentPane(); con.setLayout(new FlowLayout ()); con.add(connection); con.add(baseBox); con.add(computer); con.add(new JScrollPane (showResult)); setBounds(100 ,100 ,360 ,310 ); setVisible(true ); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } while (true ) { try { double root1 = in.readDouble(); double root2 = in.readDouble(); showResult.append("\n两个根:\n" +root1+"\n" +root2); showResult.setCaretPosition((showResult.getText()).length()); } catch (IOException e) { showResult.setText("与服务器已断开" ); computer.setEnabled(false ); break ; } } public void actionPerformed (ActionEvent e) { if (e.getSource()==connection) { try { if (socket.isConnected()) { } else { InetAddress address = InetAddress.getByName("127.0.0.1" ); InetSocketAddress socketAddress = new InetSocketAddress (address,4332 ); socket.connect(socketAddress); in=new DataInputStream (socket.getInputStream()); out=new DataOutputStream (socket.getOutputStream()); computer.setEnabled(true ); thread.start(); } } catch (IOException ee) { System.out.println(ee); socket=new Socket (); } } if (e.getSource()==computer) { try { double a = Double.parseDouble(inputA.getText()), b = Double.parseDouble(inputB.getText()), c = Double.parseDouble(inputC.getText()); double disk=b*b-4 *a*c; if (disk>=0 ) { out.writeDouble(a); out.writeDouble(b); out.writeDouble(c); double root1 = in.readDouble(); double root2 = in.readDouble(); showResult.append("\n两个根:\n" +root1+"\n" +root2); showResult.setCaretPosition((showResult.getText()).length()); } else { inputA.setText("此2次方程无实根" ); } } catch (Exception ee) { inputA.setText("请输入数字字符" ); } } } public static void main (String args[]) { ClientFrame win = new ClientFrame (); } }
UDP数据报 基于UDP通信的基本模式是 (1) 将数据打包,称为数据包,然后将数据包发往目的地。 (2) 接收别人发来的数据包,然后查看数据包中的内容。
发送数据 构造DatagramPacket(byte data[], int length, InetAddress address, int port)
DatagramPacket(byte data[], int offset, int length, InetAddress address, int port)
eg byte data[ ]=”近来好吗”.getByte(); InetAddress address = InetAddtress.getName(“www.sina.com.cn “); DatagramPacket data_pack = new DatagramPacket(data, data.length, address, 5678); 发送 用DatagramSocket类的不带参数的构造方法DatagramSocket()
创建一个对象,负责发送数据包。DatagramSocket mail_out = new DatagramSocket();
mail_out.send(data_pack);
接收数据 如果发送方发送的数据包的端口号是5678:DatagramSocket mail_in = new DatagramSocket(5678);
预备一个数据包以便收取数据包DatagramPack(byte data[], int length)
eg 该数据包pack将接收长度为length的数据放入data。 byte[] data = new byte[100]; int length = 90; DatagramPacket pack = new DatagramPacket(data, length); mail_in.receive(pack);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 import java.net.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class A extends JFrame implements Runnable , ActionListener { JTextField outMessage = new JTextField (12 ); JTextArea inMessage = new JTextArea (12 ,20 ); JButton b = new JButton ("发送数据" ); A() { super ("I AM A" ); b.addActionListener(this ); setSize(320 ,200 ); setVisible(true ); JPanel p = new JPanel (); p.add(outMessage); p.add(b); Container con = getContentPane(); con.add(new JScrollPane (inMessage), BorderLayout.CENTER); con.add(p, BorderLayout.NORTH); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); validate(); Thread thread = new Thread (this ); thread.start(); } public void actionPerformed (ActionEvent event) { byte b[] = outMessage.getText().trim().getBytes(); try { InetAddress address = InetAddress.getByName("127.0.0.1" ); DatagramPacket data = new DatagramPacket (b,b.length,address,1234 ); DatagramSocket mail = new DatagramSocket (); mail.send(data); } catch (Exception e){} } public void run () { DatagramPacket pack = null ; DatagramSocket mail = null ; byte b[] = new byte [8192 ]; try { pack = new DatagramPacket (b,b.length); mail = new DatagramSocket (5678 ); } catch (Exception e){} while (true ) { try { mail.receive(pack); String message = new String (pack.getData(),0 ,pack.getLength()); inMessage.append("收到数据来自:" + pack.getAddress()); inMessage.append("\n收到数据是:" + message+"\n" ); inMessage.setCaretPosition(inMessage.getText().length()); } catch (Exception e){} } } public static void main (String args[]) { new A (); } } import java.net.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class B extends JFrame implements Runnable , ActionListener { JTextField outMessage = new JTextField (12 ); JTextArea inMessage = new JTextArea (12 ,20 ); JButton b = new JButton ("发送数据" ); B() { super ("I AM B" ); b.addActionListener(this ); setBounds(350 ,100 ,320 ,200 ); setVisible(true ); JPanel p = new JPanel (); p.add(outMessage); p.add(b); Container con=getContentPane(); con.add(new JScrollPane (inMessage),BorderLayout.CENTER); con.add(p,BorderLayout.NORTH); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); validate(); Thread thread = new Thread (this ); thread.start(); } public void actionPerformed (ActionEvent event) { byte b[]=outMessage.getText().trim().getBytes(); try { InetAddress address = InetAddress.getByName("127.0.0.1" ); DatagramPacket data = new DatagramPacket (b,b.length,address,5678 ); DatagramSocket mail = new DatagramSocket (); mail.send(data); } catch (Exception e){} } public void run () { DatagramPacket pack = null ; DatagramSocket mail = null ; byte b[]=new byte [8192 ]; try { pack = new DatagramPacket (b,b.length); mail = new DatagramSocket (1234 ); } catch (Exception e){} while (true ) { try { mail.receive(pack); String message=new String (pack.getData(),0 ,pack.getLength()); inMessage.append("收到数据来自:" +pack.getAddress()); inMessage.append("\n收到数据是:" +message+"\n" ); inMessage.setCaretPosition(inMessage.getText().length()); } catch (Exception e){} } } public static void main (String args[]) { new B (); } }
广播数据报 广播数据包涉及到地址和端口 Internet的地址是a.b.c.d 的形式。该地址的一部分代表用户自己的主机,而另一部分代表用户所在的网络。
当a:0-127,那么b.c.d就用来表示主机,这类地址称做A类地址。
当a:128-191,则a.b表示网络地址,而c.d表示主机地址,这类地址称做B类地址。
当a:192-223,则网络地址是a.b.c,d表示主机地址,这类地址称做C类地址。
当a:224-239,这类地址称做D类地址,D类地址并不代表某个特定主机的位置。
一个具有A类、B类或C类地址的主机要广播数据或接收广播,都必须加入到同一个D类地址 。 一个D类地址也称做一个组播地址 ,加入到同一个组播地址的主机可以在某个端口上广播信息,也可以在某个端口上接收信息。
准备广播或接收的主机需经过下列步骤: step1:设置组播地址 用InetAddress类创建组播地址 InetAddress group = InetAddress.getByName("239.255.8.0");
step2:创建多点广播套接字 用MulticastSocket类创建一个多点广播套接字对象 创建的多点广播套接字可以在参数指定的端口上广播 public MulticastSocket(int port) throws IOException
step3:设置广播的范围 多点广播套接字 (MulticastSocket)对象调用 public void setTimeToLive(int ttl) throws IOException
即多播数据包的默认生存时间 step4:加入组播组 多点广播套接字 (MulticastSocket)对象调用 public void joinGroup(InetAddress mcastaddr) throws IOException
多点广播套接字 (MulticastSocket)对象调用 public void leaveGroup(InetAddress mcastaddr) throws IOException
方法可离开已经加入的组播组。 step5:广播数据和接收数据 进行广播的主机可以让多点广播套接字 (MulticastSocket)对象调用 public void send(DatagramPacket p) throws IOException
将参数p指定的数据包广播到组播组中的其它主机。 接收广播的主机可以让多点广播套接字 (MulticastSocket)对象调用 public void receive(DatagramPacket p) throws IOException
方法来接收数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 import java.net.*; public class BroadCast extends Thread { String s = "捋起袖子加油干!" ; int port = 5858 ; InetAddress group = null ; MulticastSocket socket = null ; BroadCast() { try { group = InetAddress.getByName("239.255.8.0" ); socket = new MulticastSocket (port); socket.setTimeToLive(0 ); socket.joinGroup(group); } catch (Exception e){} } public void run () { while (true ) { try { DatagramPacket packet = null ; byte data[] = s.getBytes(); packet = new DatagramPacket (data, data.length, group, port); System.out.println(new String (data)); socket.send(packet); sleep(2000 ); } catch (Exception e){} } } public static void main (String args[]) { new BroadCast ().start(); } } import java.net.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Receive extends JFrame implements Runnable ,ActionListener { int port; InetAddress group = null ; MulticastSocket socket = null ; JButton startReceive, stopReceive; JTextArea showArea; Thread thread; boolean stop = false ; public Receive () { super ("定时接收信息" ); thread = new Thread (this ); startReceive = new JButton ("开始接收" ); startReceive.addActionListener(this ); stopReceive = new JButton ("停止接收" ); stopReceive.addActionListener(this ); showArea = new JTextArea (10 ,10 ); JPanel north = new JPanel (); north.add(startReceive); north.add(stopReceive); Container con = getContentPane(); con.add(north,BorderLayout.NORTH); con.add(new JScrollPane (showArea),BorderLayout.CENTER); port=5858 ; try { group = InetAddress.getByName("239.255.8.0" ); socket = new MulticastSocket (port); socket.joinGroup(group); } catch (Exception e){} setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(320 ,300 ); validate(); setVisible(true ); } public void actionPerformed (ActionEvent e) { if (e.getSource()==startReceive) { if (!(thread.isAlive())) { thread=new Thread (this ); stop=false ; } try { thread.start(); } catch (Exception ee){} } if (e.getSource()==stopReceive) { stop=true ; } } public void run () { while (true ) { byte data[] = new byte [8192 ]; DatagramPacket packet = null ; packet = new DatagramPacket (data,data.length,group,port); try { socket.receive(packet); String message = new String (packet.getData(),0 ,packet.getLength()); showArea.append("\n" +message); showArea.setCaretPosition(showArea.getText().length()); } catch (Exception e){} if (stop==true ) { break ; } } } public static void main (String args[]) { new Receive (); } }
Java远程调用 Java远程调用(Remote Method Invocation, RMI)是一种分布式技术 ,使用RMI可以让一个虚拟机上的应用程序请求调用位于网络上另一处虚拟机上的对象。
发出调用请求的虚拟机为 (本地)客户机 接受并执行请求的虚拟机为 (远程)服务器
远程对象及其代理 远程对象 驻留在(远程)服务器上的对象是客户要请求的对象,称作远程对象 客户程序请求远程对象调用方法,然后远程对象调用方法并返回必要的结果。
代理与存根(Stub) 客户应用程序–RMI中转–远程对象
RMI与远程对象实现相同的接口,当用户请求代理调用这样的方法时,如果代理确认远程对象能调用相同的方法,就把实际的方法调用委派给远程对象。
RMI会帮助生成一个存根(Stub):一种特殊的字节码,并让这个存根产生的对象作为远程对象的代理。代理需要驻留在客户端。
在RMI中,用户实际上是在和远程对象的代理直接打交道,用户想请求远程对象调用某个方法,只需向远程对象的代理发出同样的请求即可
Remote接口 实现Remote接口 接口的类的实例才被RMI认为是一个远程对象。 Remote接口中没有方法,该接口仅仅起到一个标识 作用,因此,必须扩展(extends)Remote接口,以便规定远程对象的哪些方法是客户可以请求的方法。
RMI的设计细节
完 结 撒 花 !!!