1、第第12章章 Java的网络编程的网络编程 12.1 网络编程基础网络编程基础12.2 Socket通信通信 12.3 无连接的数据报无连接的数据报12.4 URL访问访问12.1.1 网络协议网络协议 TCP UDP12.1.2 InetAddress类类 InetAddress对象用如下格式表示主机的信息:对象用如下格式表示主机的信息: InetAddress的主要方法的主要方法 static InetAddress getByName(String host)static InetAddress getLocalHost()String getHostAddress()String ge
2、tHostName()如何得到当前计算机的如何得到当前计算机的IP地址地址1、Socket类类 Socket(String,int)-构造一个连接指定主机、指构造一个连接指定主机、指定端口的流定端口的流Socket。Socket(String,int,boolean)-构造一个连接指定构造一个连接指定主机、指定端口的主机、指定端口的Socket类,类,boolean类型的参数类型的参数用来设置是流用来设置是流Socket还是数据报还是数据报Socket。Socket(InetAddress,int)-构造一个连接指定构造一个连接指定Internet地址、指定端口的流地址、指定端口的流Socke
3、t。Socket(InetAddress,int,boolean)-构造一个连构造一个连接指定接指定Internet地址、指定端口的地址、指定端口的Socket类,类,boolean类型的参数用来设置是流类型的参数用来设置是流Socket还是数据还是数据报报Socket。2、ServerSocket类类 ServerSocket(int)在指定端口上构造一个在指定端口上构造一个ServerSocket类。类。ServerSocket(int,int)在指定端口上构造一个在指定端口上构造一个ServerSocket类,并进入监类,并进入监听状态,第二个听状态,第二个int类型的参数是监听时间长度
4、。类型的参数是监听时间长度。3、建立连接与数据通信、建立连接与数据通信 例例12-1 一个最简单的一个最简单的Socket通信演示程序通信演示程序 程序程序1:服务方程序:服务方程序 import .*;import java.io.*;public class SimpleServer public static void main(String args)ServerSocket s=null;try s=new ServerSocket(5432);/规定服务端口规定服务端口 catch(IOException e)程序程序1:服务方程序(续):服务方程序(续)while(true)tr
5、y Socket s1=s.accept();OutputStream s1out=s1.getOutputStream();DataOutputStream dos=new DataOutputStream(s1out);dos.writeUTF(Hello World!);System.out.println(a client is conneted.);s1.close();catch(IOException e)无连接请求时阻塞无连接请求时阻塞程序程序2:客户方程序:客户方程序import .*;import java.io.*;public class SimpleClient pu
6、blic static void main(String args)throws IOException Socket s1;DataInputStream dis;s1=new Socket(localhost,5432);InputStream s1In=s1.getInputStream();DataInputStream dis=new DataInputStream(s1In);String message=new String(dis.readUTF();System.out.println(message);s1.close();请求连接请求连接简单的多用户聊天程序简单的多用户聊
7、天程序 import .*;import java.io.*;public class SimpleTalkServer public static Client allclient=new Client20;/存放所有通信线程存放所有通信线程 public static int clientnum=0;/连接客户数连接客户数 public static void main(String args)try ServerSocket s=new ServerSocket(5432);while(true)Socket s1=s.accept();/等待客户连接等待客户连接 DataOutputS
8、tream dos=new DataOutputStream(s1.getOutputStream();DataInputStream din=new DataInputStream(s1.getInputStream();allclientclientnum=new Client(clientnum,dos,din);/创建与客户对应的通信线程创建与客户对应的通信线程 allclientclientnum.start();clientnum+;catch(IOException e)class Client extends Thread int id;/客户标识客户标识 DataOutput
9、Stream dos;/去往客户的输出流去往客户的输出流 DataInputStream din;/来自客户的输入流来自客户的输入流 public Client(int id,DataOutputStream dos,DataInputStream din)this.id=id;this.dos=dos;this.din=din;public void run()while(true)try String message=din.readUTF();int m=SimpleTalkServer.clientnum;for(int i=0;im;i+)SimpleTalkServer.allcl
10、ienti.dos.writeUTF(message);catch(IOException e)聊天客户端聊天客户端 import .*;import java.io.*;import java.awt.event.*;import java.awt.*;public class SimpleTalkClient public static void main(String args)throws IOException Socket s1=new Socket(args0,5432);DataInputStream dis=new DataInputStream(s1.getInputStr
11、eam();final DataOutputStream dos=new DataOutputStream(s1.getOutputStream();Frame myframe=new Frame(client);Panel panelx=new Panel();final TextField input=new TextField(20 TextArea display=new TextArea(5,20);panelx.add(input);panelx.add(display);myframe.add(panelx);new receiveThread(dis,display);/创建一
12、个接收数据线程创建一个接收数据线程 input.addActionListener(new ActionListener()public void actionPerformed(ActionEvent e)try dos.writeUTF(client:+input.getText();catch(IOException z);myframe.setSize(300,300);myframe.setVisible(true);class receiveThread extends Thread DataInputStream dis;TextArea displayarea;public r
13、eceiveThread(DataInputStream dis,TextArea m)this.dis=dis;displayarea=m;this.start();public void run()for(;)try String str=new String(dis.readUTF();/读取其他读取其他客户经服务器转发的消息客户经服务器转发的消息 displayarea.append(str+n);/将消息添加到文本将消息添加到文本域显示域显示 catch(IOException e)1、DatagramPacket类类 构造方法构造方法 DatagramPacket(byte,int
14、)构造一个用于构造一个用于接收数据报接收数据报的的DatagramPacket类,类,byte 类型的参数是接收数据报的缓冲,类型的参数是接收数据报的缓冲,int类型类型的参数是接收的字节数。的参数是接收的字节数。DatagramPacket(byte,int,InetAddress,int)构造一个用于构造一个用于发送数据发送数据的的DatagramPacket类,类,byte 类型参数是发送数据的缓冲区,类型参数是发送数据的缓冲区,int类型参类型参数是发送的字节数,数是发送的字节数,InetAddress类型参数是接收类型参数是接收机器的机器的Internet地址,最后一个参数是接收的端
15、口地址,最后一个参数是接收的端口号。号。2、DatagramSocket类类 DatagramSocket()构造一个用于构造一个用于发送数据报发送数据报的的DatagramSocket类。类。DatagramSocket(int)构造一个用于构造一个用于接收数据报接收数据报的的DatagramSocket类,类,参数为接收端口号。参数为接收端口号。3、发送和接收过程、发送和接收过程 接收端先建立一个接收的接收端先建立一个接收的DatagramSocket,在指,在指定端口上监听,定端口上监听,构造一个构造一个DatagramPacket类类指定指定接收的缓冲区接收的缓冲区 发送端需要首先构造
16、发送端需要首先构造DatagramPacket类类,指定要,指定要发送的数据、数据长度、接收主机地址及端口号,发送的数据、数据长度、接收主机地址及端口号,然后然后使用使用DatagramSocket类来发送数据报类来发送数据报。接收端接收到后,将数据保存到缓冲区接收端接收到后,将数据保存到缓冲区.接收端的程序接收端的程序byte inbuffer=new byte1024;DatagramPacket inpacket=new DatagramPacket(inbuffer,inbuffer.length);DatagramSocket insocket=new DatagramSocket(
17、80);insocket.receive(inpacket);String s=new String(inbuffer,0,0,inpacket.getLength();缓冲区用来存放数据缓冲区用来存放数据报报发送端的程序发送端的程序DatagramPacket outpacket=new DatagramPacket(message,200,192.168.0.3,80);DatagramSocket outsocket=new DatagramSocket();outsocket.send(outpacket);要发送的数据要发送的数据例例12-3 利用数据包发送信息或文件利用数据包发送信
18、息或文件程序程序1:发送程序:发送程序import java.io.*;import .*;public class UDPSend public static final String usage=用法用法:java UDPSend .n+或或 java UDPSend -f;public static void main(String args)try if(args.length 3)throw new IllegalArgumentException(参数个数不对参数个数不对);String host=args0;int port=Integer.parseInt(args1);byt
19、e message;if(args2.equals(-f)File f=new File(args3);int len=(int)f.length();message=new bytelen;FileInputStream in=new FileInputStream(f);int bytes_read=0;in.read(message,bytes_read,len);/从文件读数据到字节数组从文件读数据到字节数组 else String msg=args2;for(int i=3;i args.length;i+)msg+=+argsi;message=msg.getBytes();Ine
20、tAddress address=InetAddress.getByName(host);DatagramPacket packet=new DatagramPacket(message,message.length,address,port);DatagramSocket dsocket=new DatagramSocket();dsocket.send(packet);dsocket.close();catch(Exception e)System.err.println(e);System.err.println(usage);程序程序2:接收程序:接收程序import java.io.
21、*;import .*;public class UDPReceive public static final String usage=用法:java UDPReceive;public static void main(String args)try if(args.length!=1)throw new IllegalArgumentException(参数个数不足);int port=Integer.parseInt(args0);DatagramSocket dsocket=new DatagramSocket(port);byte buffer=new byte2048;Datag
22、ramPacket packet=new DatagramPacket(buffer,buffer.length);for(;)dsocket.receive(packet);/接收数据报 String msg=new String(buffer,0,packet.getLength();System.out.println(packet.getAddress().getHostName()+:+msg);catch(Exception e)System.err.println(e);System.err.println(usage);测试程序时,要首先运行接收程序,接收程序运测试程序时,要首
23、先运行接收程序,接收程序运行时需要提供一个行时需要提供一个端口号端口号,该程序将无限循环反,该程序将无限循环反复复等待等待接收来自发送方的数据报。接收来自发送方的数据报。发送程序需要的参数较多,首先要给定发送程序需要的参数较多,首先要给定目标主机目标主机地址、地址、端口号端口号,接下来如果要发送文件内容,则,接下来如果要发送文件内容,则-f 后接文件名;否则,剩下的所有参数均作为后接文件名;否则,剩下的所有参数均作为发发送内容送内容。12.3.4 数据报多播数据报多播 所谓多播就是发送一个数据报文,所有组内成员均可接收所谓多播就是发送一个数据报文,所有组内成员均可接收到。多播通信使用到。多播通
24、信使用D类类IP地址,地址范围为:地址,地址范围为:224.0.0.1239.255.255.255。发送广播的主机给指定多播地址的特定。发送广播的主机给指定多播地址的特定端口发送消息。接收广播的主机必须加入到同一多播地址端口发送消息。接收广播的主机必须加入到同一多播地址指定的多播组中,并从同样端口接收数据报。指定的多播组中,并从同样端口接收数据报。MulticastSocket是是DataPacketSocket的子类。常用构造方法的子类。常用构造方法如下:如下:MulticastSocket():创建一个多播:创建一个多播Socket,可用于发送多,可用于发送多播消息;播消息;Multic
25、astSocket(int port):创建一个与指定端口捆绑的多:创建一个与指定端口捆绑的多播播Socket,可用于收发多播消息。,可用于收发多播消息。()接收多播数据()接收多播数据 接收方首先通过使用发送方数据报指定的端口号接收方首先通过使用发送方数据报指定的端口号创建一个创建一个MulticastSocket对象,通过该对象调用对象,通过该对象调用joinGroup(InetAddress group)方法将自己登记到方法将自己登记到一个多播组中。然后,就可用一个多播组中。然后,就可用MulticastSocket对对象的象的receive方法接受数据报。在不需要接收数据方法接受数据报
26、。在不需要接收数据时,可调用时,可调用leaveGroup(InetAddress group)方法方法离开多播组。离开多播组。()发送多播数据()发送多播数据用用MulticastSocket对象的对象的send方法发送数据报。由于在发送方法发送数据报。由于在发送数据报中已指定了多播地址和端口,发送方创建数据报中已指定了多播地址和端口,发送方创建MulticastSocket对象时可用不指定端口的构造方法。对象时可用不指定端口的构造方法。以下为实现数据报多播的关键代码:以下为实现数据报多播的关键代码:String msg=Hello;InetAddress group=InetAddress
27、.getByName(228.5.6.7);MulticastSocket s=new MulticastSocket(6789);s.joinGroup(group);/加入多播组加入多播组DatagramPacket hi=new DatagramPacket(msg.getBytes(),msg.length(),group,6789);/创建要发送的数据报创建要发送的数据报s.send(hi);/发送发送接收多播数据报接收多播数据报 byte buf=new byte1000;DatagramPacket recv=new DatagramPacket(buf,buf.length);
28、s.receive(recv);实际应用中,发送数据是主动的动作,而接收实际应用中,发送数据是主动的动作,而接收数据是被动的动作,为了不至于阻塞应用,接收数据是被动的动作,为了不至于阻塞应用,接收可以创建一个专门的线程,让其循环等待接收数可以创建一个专门的线程,让其循环等待接收数据。据。例例12-4 基于数据报多播技术的简单讨论区基于数据报多播技术的简单讨论区public class Talk extends Frame implements Runnable MulticastSocket mSocket;/用于接收的用于接收的MulticastSocket对象对象 TextArea dis
29、play;/显示消息的文本域显示消息的文本域 TextField input;/发送信息的文本框发送信息的文本框 public Talk()super(多播测试多播测试);try mSocket=new MulticastSocket(7777);InetAddress inetAddress=InetAddress.getByName(230.0.0.1);receiveSocket.joinGroup(inetAddress);catch(Exception)display=new TextArea(5,40);input=new TextField(20);add(South,input
30、);add(Center,display);setSize(200,400);setVisible(true);input.addActionListener(new ActionListener()public void actionPerformed(ActionEvent e)try byte data=input.getText().getBytes();/将文本框的将文本框的输入串转化为字节输入串转化为字节 input.setText();InetAddress inetAddress=InetAddress.getByName(230.0.0.1);DatagramPacket d
31、atagramPacket=new DatagramPacket(data,data.length,inetAddress,7777);mSocket.send(datagramPacket);catch(Exception e);public static void main(String args)Talk s=new Talk();new Thread(s).start();public void run()/循环读取用户发送的消息循环读取用户发送的消息.try while(true)byte data=new byte 200;/定义一个字节定义一个字节缓冲区用于存放接收数据缓冲区用于
32、存放接收数据 DatagramPacket datagramPacket=new DatagramPacket(data,data.length);mSocket.receive(datagramPacket);/接收数据接收数据报报 display.append(new String(data);/将数据添将数据添加到文本域中加到文本域中 display.append(n);catch(Exception e)12.4 URL以下为以下为URL的几个构造方法及说明:的几个构造方法及说明:URL(String,String,int,String)第第1个个String类型的参数是协议的类型,可
33、以是类型的参数是协议的类型,可以是http,ftp,file等。第等。第2个个String类型参数是主机名,类型参数是主机名,int类型参数是指类型参数是指定端口号,最后一个参数是给出文件名或路径名。定端口号,最后一个参数是给出文件名或路径名。URL(String,String,String)参数含义与上相同,使用协议默认端口号。参数含义与上相同,使用协议默认端口号。URL(URL,String)利用给定利用给定URL中的协议、主机,加上中的协议、主机,加上String参数中文件的相参数中文件的相对路径拼接新对路径拼接新URL。URL(String)使用使用URL字符串构造一个字符串构造一个U
34、RL类。类。URL类提供的典型方法如下:类提供的典型方法如下:String getFile():取得:取得URL的文件名,它是带路径的文件名,它是带路径的文件标识。的文件标识。String getHost():取得:取得URL的主机名的主机名 String getPath():取得:取得URL的路径部分的路径部分 int getPort():取得:取得URL的端口号的端口号 URLConnection openConnection():返回代表与返回代表与URL进行连接的进行连接的URLConnection对象对象 InputStream openStream():打开与:打开与URL的连接,
35、的连接,返回来自连接的输入流返回来自连接的输入流 Object getContent():获取:获取URL的内容的内容12.4.2 URLConnection类类URLConnection类的构造方法是类的构造方法是URLConnection(URL)URLConnection类的几个主要方法如下:类的几个主要方法如下:void connect():打开:打开URL所指资源的通信链路;所指资源的通信链路;int getContentLength():返回:返回URL的内容长度值;的内容长度值;InputStream getInputStream():返回来自连接的输入流;:返回来自连接的输入流;OutputStream getOutputStream():返回写往连接的输出:返回写往连接的输出流;流;void setDoOutput(boolean):设置是否往设置是否往URL写数据;写数据;void setDoInput(boolean):设置是否读设置是否读URL数据。数据。