一.网络基础知识
1.1 TCP/IP
TCP:(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能,用户数据报协议(UDP)是同一层内;另一个重要的传输协议。在因特网协议族(Internet protocol suite)中,TCP层是位于IP层之上,应用层之下的中间层。不同主机的应用层之间经常需要可靠的、像管道一样的连接,但是IP层不提供这样的流机制,而是提供不可靠的包交换。应用层向TCP层发送用于网间传输的、用8位字节表示的数据流,然后TCP把数据流分区成适当长度的报文段(通常受该计算机连接的网络的数据链路层的最大传输单元(MTU)的限制)。之后TCP把结果包传给IP层,由它来通过网络将包传送给接收端实体的TCP层。TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。TCP用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。
IP:网络之间互连的协议(IP)是Internet Protocol的外语缩写,中文缩写为“网协”,网络之间互连的协议也就是为计算机网络相互连接进行通信而设计的协议。在因特网中,它是能使连接到网上的所有计算机网络实现相互通信的一套规则,规定了计算机在因特网上进行通信时应当遵守的规则。任何厂家生产的计算机系统,只要遵守IP协议就可以与因特网互连互通。IP地址具有唯一性,根据用户性质的不同,可以分为5类。另外,IP还有进入防护,知识产权,指针寄存器等含义。
1.2 UDP
UDP:User Datagram Protocol的简称,中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联)参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,IETF RFC 768是UDP的正式规范。UDP在IP报文的协议号是17。UDP协议全称是用户数据报协议,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。在OSI模型中,在第四层——传输层,处于IP协议的上一层。UDP有不提供数据包分组、组装和不能对数据包进行排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。UDP用来支持那些需要在计算机之间传输数据的网络应用。包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都需要使用UDP协议。UDP协议从问世至今已经被使用了很多年,虽然其最初的光彩已经被一些类似协议所掩盖,但是即使是在今天UDP仍然不失为一项非常实用和可行的网络传输层协议。与所熟知的TCP(传输控制协议)协议一样,UDP协议直接位于IP(网际协议)协议的顶层。根据OSI(开放系统互连)参考模型,UDP和TCP都属于传输层协议。UDP协议的主要作用是将网络数据流量压缩成数据包的形式。一个典型的数据包就是一个二进制数据的传输单位。每一个数据包的前8个字节用来包含报头信息,剩余字节则用来包含具体的传输数据。
1.3 URL
URL:统一资源定位符是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。基本URL包含模式(或称协议)、服务器名称(或IP地址)、路径和文件名,如“协议://授权/路径?查询”。完整的、带有授权部分的普通统一资源标志符语法看上去如下:协议://用户名:密码@子域名.域名.顶级域名:端口号/目录/文件名.文件后缀?参数=值#标志。
1.4 URI
统一资源标识符(Uniform Resource Identifier,或URI)是一个用于标识某一互联网资源名称的字符串。 该种标识允许用户对任何(包括本地和互联网)的资源通过特定的协议进行交互操作。URI由包括确定语法和相关协议的方案所定义。Web上可用的每种资源HTML文档、图像、视频片段、程序等由一个通用资源标识符(Uniform Resource Identifier, 简称"URI")进行定位。
1.5 Http
超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。1960年美国人Ted Nelson构思了一种通过计算机处理文本信息的方法,并称之为超文本(hypertext),这成为了HTTP超文本传输协议标准架构的发展根基。
二.URL编程
import java.net.*;
import java.io.*;
import java.util.regex.*;
class cuthtml{
public void geturl(String line){
Pattern pa=Pattern.compile("/html/dhxw/(mtsj|xydt|bmxx|tpxw|jqyw|ztxw)/[0-9]*.html");
Matcher ma=pa.matcher(line);
String str=null;
try{
BufferedWriter writer=new BufferedWriter(new FileWriter("url.txt",true));
while(ma.find()){
writer.write(ma.group());
writer.newLine();
writer.flush();
}
writer.close();
}
catch(IOException e){
System.out.println(e.getMessage());
}
}
public void gettxt(String line){
try
{
Pattern title=Pattern.compile("<title>.*</title>");
Matcher name=title.matcher(line);
name.find();
String filename=name.group();
title=Pattern.compile("<title>|</title>");
name=title.matcher(filename);
name.find();
filename=name.replaceAll("");
System.out.println(filename+"\n");
Pattern pt=Pattern.compile("<td style=\" font-size: 16px; COLOR: #ff0000; line-height: 200%\" valign=\"center\" align=\"middle\" width=\"649\" height=\"46\"><span class=\"STYLE8\">.*</p></td>",Pattern.MULTILINE|Pattern.DOTALL);
Matcher ma=pt.matcher(line);
while(ma.find())
{
Pattern nbsp=Pattern.compile("<[^>]*>");
Matcher bsp=nbsp.matcher(ma.group());
String string=bsp.replaceAll("");
Pattern ldquo=Pattern.compile("&[lr]dquo;");
Matcher dquo=ldquo.matcher(string);
string=dquo.replaceAll("\"");
Pattern mdash=Pattern.compile("—");
Matcher dash=mdash.matcher(string);
string=dash.replaceAll("-");
Pattern lsquo=Pattern.compile("&[lr]squo;");
Matcher squo=lsquo.matcher(string);
string=squo.replaceAll("\'");
Pattern rubsh=Pattern.compile("(function ContentSize.*|.document.getElementById.*| )");
Matcher ubsh=rubsh.matcher(string);
string=ubsh.replaceAll("");
Pattern sp=Pattern.compile("\\n[\\s| ]*\\r");
Matcher sn=sp.matcher(string);
string=sn.replaceAll("");
BufferedWriter Writer=new BufferedWriter(new FileWriter("namelist.txt",true));
Writer.write(filename);
Writer.newLine();
Writer.flush();
Writer.close();
Writer=new BufferedWriter(new FileWriter(filename.concat(".txt")));
Writer.write(string);
Writer.newLine();
Writer.flush();
Writer.close();
}
}catch(PatternSyntaxException e)
{
System.out.println("regex error\n");
}catch(IllegalStateException e)
{
System.out.println("string error\n");
}catch(IOException e){
System.out.println(e.getMessage());
}
}
}
public class connect
{
public String GetHtml(String Url,int i){
String line=null;
try{
URL url=new URL(Url);
BufferedReader reader=new BufferedReader(new InputStreamReader(url.openStream(),"gb2312"));
StringBuffer str=new StringBuffer();
while((line=reader.readLine())!=null){
str.append(line+"\r\n");
}
reader.close();
line=str.toString();
cuthtml cut=new cuthtml();
if(i==0)
cut.geturl(line);
else
cut.gettxt(line);
}
catch(MalformedURLException e){
System.out.println("open "+Url+" error");
}
catch(IOException e){
System.out.println(e.getMessage());
}
return line;
}
public static void main(String[] args)throws IOException {
String rine=null,line=null;
connect get= new connect();
StringBuffer url=null;
for(int i=0;i<118;i++){
if(i!=0){
url=new StringBuffer("http://2011.wdu.edu.cn/html/dhxw/index_.html");
url.insert(39,Integer.toString(i));
}
else{
url=new StringBuffer("http://2011.wdu.edu.cn/html/dhxw/index.html");
}
get.GetHtml(url.toString(),0);
}
BufferedReader reader=new BufferedReader(new FileReader("url.txt"));
while((line=reader.readLine())!=null){
String Url=new String("http://2011.wdu.edu.cn");
rine=get.GetHtml(Url.concat(line),1);
}
}
}
三.Socket编程
3.1 Socket编程相关的类
InetAddress:与IP地址相关的类
Inet4Address:与IPV4协议相关的类
Inet6Address:与IPV6协议相关的类
InetSocketAddress:此类实现IP套接字地址(IP地址+端口号)。它还可以是一个对(主机名+端口号),在此情况下,将尝试解析主机名。如果解析失败,则该地址将被视为未解析 地址,但是其在某些情形下仍然可以使用,比如通过代理连接。
SocketAddress:此类表示不带任何协议附件的Socket Address。作为一个抽象类,应通过特定的、协议相关的实现为其创建子类。它提供不可变对象,供套接字用于绑定、连接或用作返回值。
Socket:此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点。套接字的实际工作由SocketImpl类的实例执行。应用程序通过更改创建套接字实现的套接字工厂可以配置它自身,以创建适合本地防火墙的套接字。
ServerSocket:此类实现服务器套接字。服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。服务器套接字的实际工作由SocketImpl 类的实例执行。应用程序可以更改创建套接字实现的套接字工厂来配置它自身,从而创建适合本地防火墙的套接字。
3.2 编程实例
/*
* 客户端程序
*/
public class SocketClient {
public static void main(String[] args) throws Exception {
InetSocketAddress inet=new InetSocketAddress("localhost", 1688);//远程连接地址
Socket client=new Socket();
client.connect(inet, 1000);//连接到远程地址,并且在1秒内连接成功,否则将抛出连接失败
InputStream in=client.getInputStream();//获取服务器端所发送,客户端所接收到的流
OutputStream out=client.getOutputStream();//客户端向服务器端的输出流
PrintWriter writer=new PrintWriter(out,true);
Scanner sc=new Scanner(System.in);
Scanner data=new Scanner(in);
while(data.hasNextLine())
{
String line=sc.nextLine();
writer.println(line);
String from=data.nextLine();
System.out.println(from);
if(from.equalsIgnoreCase("bye"))//如果服务端向客户端发送bye字符串,则关闭连接
{
System.out.println("失去连接");
break;
}
}
client.close();
}
}
/*
* 服务器端的程序
*/
public class SocketServer {
public static void main(String[] args) throws Exception {
ServerSocket server=new ServerSocket(1688);
Socket socket=server.accept();
System.out.println("连接到客户端");
InputStream in=socket.getInputStream();
OutputStream out=socket.getOutputStream();
PrintWriter writer=new PrintWriter(out,true);
writer.println("输入quit结束");
Scanner sc=new Scanner(in);
while(sc.hasNextLine())
{
String line =sc.nextLine();
if(line.equalsIgnoreCase("quit"))//如果接收到客户端所发送的quit则停止连接
{
server.close();
writer.println("Bye");//向客户端发送bye,使客户端失去连接
break;
}
System.out.println(line);
writer.println(line);
}
}
}
四.Datagram编程
4.1 Datagram编程相关类
DatagramSocket:此类表示用来发送和接收数据报包的套接字。数据报套接字是包投递服务的发送或接收点。每个在数据报套接字上发送或接收的包都是单独编址和路由的。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。在DatagramSocket上总是启用UDP广播发送。为了接收广播包,应该将 DatagramSocket 绑定到通配符地址。在某些实现中,将 DatagramSocket 绑定到一个更加具体的地址时广播包也可以被接收。示例:DatagramSocket s =new DatagramSocket(null);s.bind(new InetSocketAddress(8888));这等价于:DatagramSocket s = new DatagramSocket(8888);两个例子都能创建能够在UDP 8888端口上接收广播的 DatagramSocket。
DatagramPacket:此类表示数据报包。数据报包用来实现无连接包投递服务。每条报文仅根据该包中包含的信息从一台机器路由到另一台机器。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达不对包投递做出保证。
4.2 编程实例
/*
* 面向无连接的客户端的程序
*/
public class DatagramClient {
public static void main(String[] args) throws Exception {
byte[] buf=new byte[256];
DatagramSocket socket=new DatagramSocket();
InetAddress address=InetAddress.getByName("localhost");//获取本地的地址
sending(socket,buf,address,1688); //发送到指定地址和端口
String data=receiving(socket,buf);
System.out.println(data);
Scanner sc=new Scanner(System.in);
while(sc.hasNextLine())
{
String line=sc.nextLine();
if(!line.trim().equalsIgnoreCase("quit"))
{
buf=new byte[256];
buf=line.getBytes();
sending(socket,buf,address,1688);
data=receiving(socket,buf);
System.out.println(data);
buf=new byte[256];
sending(socket,buf,address,1688);
data=receiving(socket,buf);
System.out.println(data);
}
else
break;
}
socket.close();
}
public static void sending(DatagramSocket socket,byte[] buf,InetAddress address,int port) throws Exception
{
DatagramPacket send=new DatagramPacket(buf, buf.length, address, port);
socket.send(send);
}
public static String receiving(DatagramSocket socket,byte[] buf) throws Exception
{
DatagramPacket receive=new DatagramPacket(buf, buf.length);
socket.receive(receive);
String data=new String (receive.getData());
return data;
}
}
/*
* 面向无连接的用户数据包,此程序为服务器端
*/
public class DatagramServer {
public static void main(String[] args) throws Exception {
System.out.println("Welcome! The Server is Running.....");
String line="Datagram packet from server: I love Java programming.\n";
String promptString=line.toUpperCase()+"Enter quit to Stop";
byte[] buf=new byte[256];
DatagramSocket socket=new DatagramSocket(1688);//创建数据包套接字,接收1688端口的请求
DatagramPacket receive=new DatagramPacket(buf, buf.length);//创建接收的用户数据包
socket.receive(receive);//接收客户端的数据包
buf=promptString.getBytes();
InetAddress address=receive.getAddress();//获取客户端的地址
int port=receive.getPort();//获取客户端的端口
sending(socket,buf,address,port);//向客户端发送消息
while(true)
{
buf=new byte[256];
receive=new DatagramPacket(buf, buf.length);
socket.receive(receive);
String data=new String(receive.getData());
buf=data.toUpperCase().getBytes();
sending(socket,buf,address,port);
buf=new byte[256];
String wordCount="(converting from server and packet length:"+data.trim().length()+")";
receive=new DatagramPacket(buf,buf.length);
socket.receive(receive);
buf=wordCount.getBytes();
sending(socket,buf,address,port);
}
}
public static void sending(DatagramSocket socket,byte[] buf,InetAddress address,int port) throws Exception
{
DatagramPacket send=new DatagramPacket(buf, buf.length, address, port);
socket.send(send);
}
}
五.数据广播通信
/*
* 多播的客户端
*/
public class MulticastClient {
public static void main(String[] args) throws IOException {
MulticastSocket socket=new MulticastSocket(8089);
InetAddress address=InetAddress.getByName("230.0.0.1");
socket.joinGroup(address);
DatagramPacket packet=null;
for(int i=0;i<5;i++)
{
byte[] buf=new byte[256];
packet=new DatagramPacket(buf,buf.length);
socket.receive(packet);
String data=new String(packet.getData());
System.out.println("Quotes of theMoment:"+data);
socket.leaveGroup(address);
socket.close();
}
}
}
/*
* 多播的客户端
*/
public class MulticastClient {
public static void main(String[] args) throws IOException {
MulticastSocket socket=new MulticastSocket(8089);
InetAddress address=InetAddress.getByName("230.0.0.1");
socket.joinGroup(address);
DatagramPacket packet=null;
for(int i=0;i<5;i++)
{
byte[] buf=new byte[256];
packet=new DatagramPacket(buf,buf.length);
socket.receive(packet);
String data=new String(packet.getData());
System.out.println("Quotes of theMoment:"+data);
socket.leaveGroup(address);
socket.close();
}
}
}
public class MulticastServerThread extends QuoteServerThread {
private long FIVE_SECONDS=5000;
public MulticastServerThread() throws SocketException,
FileNotFoundException {
super("MulticastServerThread");
}
public void run()
{
while(moreQuotes)
{
try{
byte[] buf=new byte[256];
String dString=null;
if(in==null)
{
dString=new Date().toString();
}
else
{
dString=getNextQuotes();
}
buf=dString.getBytes();
InetAddress group=InetAddress.getByName("230.0.0.1");
DatagramPacket packet=new DatagramPacket(buf, buf.length,group, 8089);
socket.send(packet);
try{
Thread.sleep((long) (Math.random()*FIVE_SECONDS));
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
catch(IOException e)
{
e.printStackTrace();
moreQuotes=false;
}
}
socket.close();
}
}
public class QuoteServerThread extends Thread {
protected DatagramSocket socket=null;
protected BufferedReader in=null;
protected boolean moreQuotes=true;
public QuoteServerThread() throws SocketException, FileNotFoundException
{
this("QuoteServerThread");
}
public QuoteServerThread(String name) throws SocketException, FileNotFoundException
{
super(name);
socket=new DatagramSocket(8088);
FileReader f=new FileReader("MulticastInfo.txt");
in=new BufferedReader(f);
}
public void run()
{
System.out.println("server is Running");
while(moreQuotes)
{
byte[] buf=new byte[256];
DatagramPacket packet=new DatagramPacket(buf,buf.length);
try {
socket.receive(packet);
String dString=null;
if(in==null)
dString=new Date().toString();
else dString=getNextQuotes();
buf=dString.getBytes();
InetAddress address=packet.getAddress();
int port=packet.getPort();
packet=new DatagramPacket(buf,buf.length,address,port);
socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
}
}
protected String getNextQuotes()
{
String data=null;
try {
if((data=in.readLine())==null)
{
in.close();
moreQuotes=false;
data="NO More Quotes. goodbye";
}
} catch (IOException e) {
data=e.getMessage();
}
return data;
}
}