一,教材学习内容(13.Java网络编程)
1、URL类
使用URL创建对象的应用程序称为客户端程序。
URL的组成:
协议名:指明获取资源所使用的传输协议,如HTTP,FTP,Gopher,File等
端口号:可选,表示连接的端口号,如默认将连接到协议默认的端口
资源名:是资源的完整地址,包括主机名,端口号,文件名或文件内部的一个引用。
标记:可选,指文件内的有特定标记的位置
1.1 URL类的构造方法
为表示URL,Java.net中实现了URL类,可通过下面的构造方法来初始化一个URL对象。
1)public URL(String spec);//通过一个表示URL地址的字符串可以构造一个URL对象,如:URL urlbase=new URL(“http://www.163.com/”)
2)public URL(URL context,String spec);//通过基URL构造一个URL对象,如: URL com163=new URL(“http://www.163.com/”)
URL index163=new URL(com163,”index.html”)
3)public URL(String protocol,String host,String file);//通过协议,域名及文件名构造一个url对象,如:URL gamelan=new URL(“http”,”www.gamelan.com”,”/pages/Gamelan.net.html”);
4)public URL(String protocol,String host,int port,String file);//通过协议,域名,端口号及文件名构造一个url对象,如:URL gamelan=new URL(“http”,”www.gamelan.com”,80,”/pages/Gamelan.net.html”);
注意:类URL的构造方法都可能会抛出异常,因此生成URL对象时,必须要对这个Exception进行处理,通常使用try catch语句进行捕获。
1.2 URL部分方法
String getPotocol() 获取该URL的协议名
String getHost() 获取该URL的主机名
Int getPort() 获取该URL的端口号,如果没有设置端口,返回-1
String getFile() 获取该URL的文件名,如果没有返回空串
String getRef() 获取该URL中记录的引用,如果URL不含引用,返回null
String getQuery() 获取该URL的查询信息
String getPath() 获取该URL的路径
String getAuthority() 获取该URL的权限信息
String getUserInfo() 获得使用者的信息
1.3 InetAddress类(主要用于其他类的方法参数)
具体使用:
import java.net.*;
public class Example13_2 {
public static void main(String args[]) {
try{ InetAddress address_1=InetAddress.getByName("www.sina.com.cn");
System.out.println(address_1.toString());
InetAddress address_2=InetAddress.getByName("166.111.222.3");
System.out.println(address_2.toString());
}
catch(UnknownHostException e) {
System.out.println("无法找到 www.sina.com.cn");
}
}
}
1.3 套接字(IP+Port)
其中端口号(Port)规定为一个十六位的0~65535之间的整数,其中0~1023被预先定义的服务通信占用。
当两个程序需要通信时,它们可以通过Socket类建立套接字对象并连接在一起。
1.3.1 客户端套接字(Socket类)
try{Socket clientSocket=new Socket("http://192.168.0.78",2010);
}
catch(IOExeception){}
当客户端套接字对象建好后,可以使用getInputStream()和getOutputStream()方法向客户端输入输出数据。
1.3.2 服务器端套接字与ServerSocket对象
为了能使客户成功连接到服务器,服务器必须建立一个ServerSocket对象,该对象的作用在于将客户端和服务器端的套接字连接在一起。
使用try-catch语句块建立ServerSocket对象。
try{ServerSocket Serverforclient=new ServerSocket(2010);
}
catch(IOExeception){}
建立完毕后,就可以使用accept()方法连接两边的套接字。
需要注意的是,accept()也会造成程序阻塞。
import java.io.*;
import java.net.*;
public class Client {
public static void main(String args[]) {
String [] mess ={"2010世界杯在哪举行?","巴西进入世界杯了码?","中国进入世界杯了码?"};
Socket mysocket;
DataInputStream in=null;
DataOutputStream out=null;
try{ mysocket=new Socket("127.0.0.1",2010);
in=new DataInputStream(mysocket.getInputStream());
out=new DataOutputStream(mysocket.getOutputStream());
for(int i=0;i<mess.length;i++) {
out.writeUTF(mess[i]);
String s=in.readUTF(); //in读取信息,堵塞状态
System.out.println("客户收到服务器的回答:"+s);
Thread.sleep(500);
}
}
catch(Exception e) {
System.out.println("服务器已断开"+e);
}
}
}
import java.io.*;
import java.net.*;
public class Server {
public static void main(String args[]) {
String [] answer ={"南非","进入世界杯了","哈哈...问题真逗!"};
ServerSocket serverForClient=null;
Socket socketOnServer=null;
DataOutputStream out=null;
DataInputStream in=null;
try { serverForClient = new ServerSocket(2010);
}
catch(IOException e1) {
System.out.println(e1);
}
try{ System.out.println("等待客户呼叫");
socketOnServer = serverForClient.accept(); //堵塞状态,除非有客户呼叫
out=new DataOutputStream(socketOnServer.getOutputStream());
in=new DataInputStream(socketOnServer.getInputStream());
for(int i=0;i<answer.length;i++) {
String s=in.readUTF(); // in读取信息,堵塞状态
System.out.println("服务器收到客户的提问:"+s);
out.writeUTF(answer[i]);
Thread.sleep(500);
}
}
catch(Exception e) {
System.out.println("客户已断开"+e);
}
}
}
1.4 使用多线程技术
目的:为每个客户端启动一个线程,以满足每个客户的需要。
import java.io.*;
import java.net.*;
import java.util.*;
public class Client {
public static void main(String args[]) {
Scanner scanner = new Scanner(System.in);
Socket mysocket=null;
DataInputStream in=null;
DataOutputStream out=null;
Thread readData ;
Read read=null;
try{ mysocket=new Socket();
read = new Read();
readData = new Thread(read);
System.out.print("输入服务器的IP:");
String IP = scanner.nextLine();
System.out.print("输入端口号:");
int port = scanner.nextInt();
if(mysocket.isConnected()){}
else{
InetAddress address=InetAddress.getByName(IP);
InetSocketAddress socketAddress=new InetSocketAddress(address,port);
mysocket.connect(socketAddress);
in =new DataInputStream(mysocket.getInputStream());
out = new DataOutputStream(mysocket.getOutputStream());
read.setDataInputStream(in);
readData.start();
}
}
catch(Exception e) {
System.out.println("服务器已断开"+e);
}
System.out.print("输入园的半径(放弃请输入N):");
while(scanner.hasNext()) {
double radius=0;
try {
radius = scanner.nextDouble();
}
catch(InputMismatchException exp){
System.exit(0);
}
try {
out.writeDouble(radius);
}
catch(Exception e) {}
}
}
}
import java.io.*;
public class Read implements Runnable {
DataInputStream in;
public void setDataInputStream(DataInputStream in) {
this.in = in;
}
public void run() {
double result=0;
while(true) {
try{ result=in.readDouble();
System.out.println("圆的面积:"+result);
System.out.print("输入园的半径(放弃请输入N):");
}
catch(IOException e) {
System.out.println("与服务器已断开"+e);
break;
}
}
}
}
import java.io.*;
import java.net.*;
import java.util.*;
public class Server {
public static void main(String args[]) {
ServerSocket server=null;
ServerThread thread;
Socket you=null;
while(true) {
try{ server=new ServerSocket(2010);
}
catch(IOException e1) {
System.out.println("正在监听"); //ServerSocket对象不能重复创建
}
try{ System.out.println(" 等待客户呼叫");
you=server.accept();
System.out.println("客户的地址:"+you.getInetAddress());
}
catch (IOException e) {
System.out.println("正在等待客户");
}
if(you!=null) {
new ServerThread(you).start(); //为每个客户启动一个专门的线程
}
}
}
}
class ServerThread extends Thread {
Socket socket;
DataOutputStream out=null;
DataInputStream in=null;
String s=null;
ServerThread(Socket t) {
socket=t;
try { out=new DataOutputStream(socket.getOutputStream());
in=new DataInputStream(socket.getInputStream());
}
catch (IOException e){}
}
public void run() {
while(true) {
try{ double r=in.readDouble();//堵塞状态,除非读取到信息
double area=Math.PI*r*r;
out.writeDouble(area);
}
catch (IOException e) {
System.out.println("客户离开");
return;
}
}
}
}
2、UDP数据包
套接字是基于TCP协议的网络通信,而基于UDP的网络通信方式的信息传递更快,但不提供可靠性的保证。
import java.net.*;
import java.util.*;
public class LiSi {
public static void main(String args[]) {
Scanner scanner = new Scanner(System.in);
Thread readData ;
ReceiveLetterForLi receiver = new ReceiveLetterForLi();
try{ readData = new Thread(receiver);
readData.start(); //负责接收信息的线程
byte [] buffer=new byte[1];
InetAddress address=InetAddress.getByName("127.0.0.1");
DatagramPacket dataPack=
new DatagramPacket(buffer,buffer.length, address,888);
DatagramSocket postman=new DatagramSocket();
System.out.print("输入发送给张三的信息:");
while(scanner.hasNext()) {
String mess = scanner.nextLine();
buffer=mess.getBytes();
if(mess.length()==0)
System.exit(0);
buffer=mess.getBytes();
dataPack.setData(buffer);
postman.send(dataPack);
System.out.print("继续输入发送给张三的信息:");
}
}
catch(Exception e) {
System.out.println(e);
}
}
}
import java.net.*;
public class ReceiveLetterForLi implements Runnable {
public void run() {
DatagramPacket pack=null;
DatagramSocket postman=null;
byte data[]=new byte[8192];
try{ pack=new DatagramPacket(data,data.length);
postman = new DatagramSocket(666);
}
catch(Exception e){}
while(true) {
if(postman==null) break;
else
try{ postman.receive(pack);
String message=new String(pack.getData(),0,pack.getLength());
System.out.printf("%25s\n","收到:"+message);
}
catch(Exception e){}
}
}
}
import java.net.*;
public class ReceiveLetterForZhang implements Runnable {
public void run() {
DatagramPacket pack=null;
DatagramSocket postman=null;
byte data[]=new byte[8192];
try{ pack=new DatagramPacket(data,data.length);
postman = new DatagramSocket(888);
}
catch(Exception e){}
while(true) {
if(postman==null) break;
else
try{ postman.receive(pack);
String message=new String(pack.getData(),0,pack.getLength());
System.out.printf("%25s\n","收到:"+message);
}
catch(Exception e){}
}
}
}
import java.net.*;
import java.util.*;
public class ZhangSan {
public static void main(String args[]) {
Scanner scanner = new Scanner(System.in);
Thread readData ;
ReceiveLetterForZhang receiver = new ReceiveLetterForZhang();
try{ readData = new Thread(receiver);
readData.start(); //负责接收信息的线程
byte [] buffer=new byte[1];
InetAddress address=InetAddress.getByName("127.0.0.1");
DatagramPacket dataPack=
new DatagramPacket(buffer,buffer.length, address,666);
DatagramSocket postman=new DatagramSocket();
System.out.print("输入发送给李四的信息:");
while(scanner.hasNext()) {
String mess = scanner.nextLine();
buffer=mess.getBytes();
if(mess.length()==0)
System.exit(0);
buffer=mess.getBytes();
dataPack.setData(buffer);
postman.send(dataPack);
System.out.print("继续输入发送给李四的信息:");
}
}
catch(Exception e) {
System.out.println(e);
}
}
}