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
// public URL(String spec)  throws MalformedURLException
try
{
url=new URL("http://yahoo.com.cn"); //使用字符串初始化一个URL对象 是http协议
}
catch(MalformedURLException e)
{
System.out.println("Bad URL:"+url);
}

// public URL(String protocol, String host, String file) throws MalformedURLException
// URL对象的协议、地址和资源分别由参数protocol、host和file指定。

读取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
• 后两个构造方法使用参数initialPageurl指定最初的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。
0
1023被预先定义的服务通信占用(如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
//step1:服务器建立ServerSocket对象
try
{
ServerSocket waitSocketConnection = new ServerSocket(1880);//构造ServerSocket
//ServerSocket对象负责等待客户端的请求,进而建立套接字连接
}
catch(IOException e){}
//接收客户端的套接字连接请求
Socket socketAtServer = waitSocketConnection.accept();
//“接收”客户的套接字请求,就是accept()方法会返回一个Socket对象(即socketAtServer),称作服务器端的套接字对象。

//step2:客户端创建Socket对象
//使用Socket类创建对象 Socket(String host, int port)
Socket socketAtClient = new Socket(localhost, 1880);
//使用Socket类不带参数的构造方法
public Socket()
//,再调用public void connect(InetSocketAddress endpoint) throws IOException请求和参数InetSocketAddress指定地址的套接字建立连接

//客户端建立Socket对象(即socketAtClient)的过程就是向服务器发出套接字连接请求

//step3:流连接
// 服务器端的这个Socket对象(即socketAtServer)使用方法getOutputStream()获得的输出流,将指向客户端Socket对象(即socketAtClient)使用方法getInputStream()获得的那个输入流。
// 服务器端的这个Socket对象(即socketAtServer)使用方法getInputStream()获得的输入流,将指向客户端Socket对象(即 socketAtClient)使用方法getOutputStream()获得的那个输出流。
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
// MutiServer.java 
import java.io.*;
import java.net.*;
import java.util.*;

public class MutiServer
{
public static void main(String args[])
{
ServerSocket server = null;
// ServerThread thread;
Socket socketAtServer = null;
while(true) // !!
{
try
{
server = new ServerSocket(4332);
}
catch(IOException e1)
{
System.out.println("正在监听"); //ServerSocket对象不能重复创建
}
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;
}
}
}
}

// ClientFrame.java
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
// A.java
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();
}
}

//B.java
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
//BroadCast.java
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"); // 设置组播组为239.255.8.0
socket = new MulticastSocket(port); // 多点广播套接字将在port端口广播
socket.setTimeToLive(0); // 多点广播套接字发送数据报范围为本地主机
socket.joinGroup(group); // 加入组播组,加入group后,socket发送的数据报可以被加入到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();
}
}

// Receive.java
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的设计细节

1

!!!