一、URL编程
1、URL
URL(Uniform Resource Locator)是一致资源定位器的简称,它表示Internet上某一资源的地址。通过URL我们可以访问Internet上的各种网络资源,比如最常见的WWW,FTP站点。浏览器通过解析给定的URL可以在网络上查找相应的文件或其他资源。
URL地址格式:(Protocol)(Host)[:Port][File][#Reference]
示例:
http://www.ncsa.uiuc.edu:8080/demoweb/urlprimer.html#INSTALL
http://localhost:8080/index.html
2、URL类及其常用方法
类java.net.URL的实例对象表示具体的 URL,类 java.net.URL 具有五个成员方法,可以用来获取URL的五个部分:
import java.net.*;
import java.io.*;
public class ParseURL {
public static void main(String[] args) throws Exception {
URL aURL = new URL("http://java.sun.com:80/docs/books/" + "tutorial/index.html#DOWNLOADING");
System.out.println("protocol = " + aURL.getProtocol());
System.out.println("host = " + aURL.getHost());
System.out.println("filename = " + aURL.getFile());
System.out.println("port = " + aURL.getPort());
System.out.println("ref = " + aURL.getRef());
}
}
结果:
3、从URL读取万维网资源
当我们得到一个URL对象后,就可以通过它读取指定的WWW资源。这时我们将使用URL的方法openStream(),其定义为:
InputStream openStream();
方法openSteam()与指定的URL建立连接并返回InputStream类的对象以从这一连接中读取数据。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
public class TestWeb {
public static void main(String[] args) { //声明抛出所有异常
try {
//构建一URL对象
URL tirc = new URL("http://www.tup.tsinghua.edu.cn/index.html");
BufferedReader in = new BufferedReader(new InputStreamReader(tirc.openStream(),"UTF-8"));
//使用openStream得到一输入流并由此构造一个BufferedReader对象,指定和网站相同的编码格式,解决中文乱码问题
String inputLine;
//从输入流不断的读数据,直到读完为止
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine); //把读入的数据输出到屏幕上
}
in.close(); //关闭输入流
} catch (Exception e) {
e.printStackTrace();
}
}
}
二、socket编程
1、基本概念
网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket,又称“套接字”。生成Socket,主要有3个参数:通信的目的IP地址、使用的传输层协议(TCP或UDP,在JAVA环境下,Socket编程主要是指基于TCP/IP协议的网络编程)和使用的端口号。
图:服务器端和客户端通信示意图
类java.net.Socket允许如下的四种基本操作
1. 连接到远程的机器
2. 发送数据
3. 接收数据
4. 关闭连接
2、支持多客户的C/S程序步骤
①服务器端主程序
(1)创建ServerSocket对象;
(2)循环侦听客户端的请求,若监听到客户请求,根据得到的Socket对象和客户端连接数创建服务线程,并启动该线程;
(3)关闭ServerSocket对象。
import java.io.*;
import java.net.*;
public class MultiTalkServer{
static int clientnum=0;//静态成员变量,记录当前客户的个数
public static void main(String args[ ]) {
ServerSocket serverSocket=null;
boolean listening=true;
try{
serverSocket=new ServerSocket(4700);
System.out.println("Server is running...");
//创建一个ServerSocket在端口4700监听客户请求
}catch(IOException e) {
System.out.println("Could not listen on port:4700.");
System.exit(-1); //退出
}
try{
while(listening){//永远循环监听
new ServerThread(serverSocket.accept(),++clientnum).start();
//监听到客户请求,根据得到的Socket对象和
//客户计数创建服务线程,并启动之
System.out.println("Client-"+(clientnum)+" is connected...");
}
serverSocket.close(); //关闭ServerSocket
}catch(IOException e){
System.out.println("连接客户端失败");
}
}
}
②服务器端通信的线程程序
(1)定义一个线程类
(2)通过构造方法将服务器端程序传递的Socket对象和客户端连接数赋值给相应的变量
(3)线程体run方法:通过得到的Socket对象获取输入输出流对象,通过循环与客户端发送和接收数据。若循环结束,关闭Socket对象和输入输出流对象
import java.io.*;
import java.net.*;
public class ServerThread extends Thread{
Socket socket=null; //保存与本线程相关的Socket对象
int clientnum; //保存本进程的客户计数
public ServerThread(Socket socket,int num) { //构造函数
this.socket=socket;//初始化socket变量
clientnum=num+1;//初始化clientnum变量
}
public void run() {//线程主体
try{
String line;
//由Socket对象得到输入流,并构造相应的BufferedReader对象
BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//由Socket对象得到输出流,并构造PrintWriter对象
PrintWriter os=new PrintWriter(socket.getOutputStream());
//由系统标准输入设备构造BufferedReader对象
BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));
//在标准输出上打印从客户端读入的字符串
System.out.println("Client-"+ clientnum +":" +is.readLine());
//从标准输入读入一字符串
line=sin.readLine();
while(!line.equals("bye")){ //如果该字符串为 "bye",则停止循环
os.println(line); //向客户端输出该字符串
os.flush(); //刷新输出流,使Client马上收到该字符串
System.out.println("Server:"+line);
//从Client读入一字符串,并打印到标准输出上
System.out.println("Client-"+ clientnum +":" +is.readLine());
line=sin.readLine(); //从系统标准输入读入一字符串
} //继续循环
os.close(); //关闭Socket输出流
is.close(); //关闭Socket输入流
socket.close(); //关闭Socket
}catch(Exception e){
System.out.println("Error:"+e);
}
}
}
③客户端程序
(1)创建与服务器连接的socket对象
(2) 通过Socket对象获取输入输出流对象,通过循环与客户端发送和接收数据。若循环结束,关闭Socket对象和输入输出流对象。
import java.io.*;
import java.net.*;
public class TalkClient {
public static void main(String args[]) {
try{
//向本机的4700端口发出客户请求
Socket socket=new Socket("127.0.0.1",4700);
System.out.println("已连接服务器,请发消息给服务器处理...");
//由系统标准输入设备构造BufferedReader对象
BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));
//由Socket对象得到输出流,并构造PrintWriter对象
PrintWriter os=new PrintWriter(socket.getOutputStream());
//由Socket对象得到输入流,并构造相应的BufferedReader对象
BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String readline;
readline=sin.readLine(); //从系统标准输入读入一字符串
while(!readline.equals("bye")){ //若输入字符串为 "bye"则停止循环
//将从系统标准输入读入的字符串输出到Server
os.println(readline);
//刷新输出流,使Server马上收到该字符串
os.flush();
//在系统标准输出上打印读入的字符串
System.out.println("Client:"+readline);
//从Server读入一字符串,并打印到标准输出上
System.out.println("Server:"+is.readLine());
//从系统标准输入读入一字符串
readline=sin.readLine();
} //继续循环
os.close(); //关闭Socket输出流
is.close(); //关闭Socket输入流
socket.close(); //关闭Socket
}catch(Exception e) {
System.out.println("Error"+e); //出错,则打印出错信息
}
}
}
运行结果:
服务端:
客户端: