java 基础知识(网络编程)

网络编程:
网络编程的基础知识:
计算机网络是现代通信技术与计算机技术相吻合的产物,计算机可以提供以下一些功能:
1.资源共享
2.信息传输与资源处理
3.均衡负荷与分布处理
4.综合信息服务
计算机网络通常是按照规模大小和延申范围来分类的,常见的划分为:局域网(LAN),城域网(MAN),广域网(WAN)。INTERNET可以视为世界上最大的广域网。
如果网络按照拓扑结构来划分,可以分为星型网络,总线网络,环线网络,树形网络,星型环线网络等;如果按照网络的传输介质来分,可以分为双绞线网,同轴电缆网,光纤网和卫星网等
按照规模分类:
局域网(LAN):指在一个较小地理范围内的各种计算机网络设备互联在一起的通信网络,可以包含一个或多个子网,通常局限在几千米范围之内。
城域网(MAN):主要是由城域范围内的各局域网之间互联而构成。
广域网(WAN):是由相距较远的局域网或城域网互联而成,通常是除了计算机设备以外,还要涉及一些电信通信方式。
接口包括两部分:一是硬件装置,功能是实现节点之间的信息传送;二是软件装置,功能是规定双方进行通信的约定协议。
计算机网络协议通常由三部分组成:一是语义部分,用于决定双方对话的类型;二是语法部分,用于决定双方对话的格式。三是变换规则,用于决定通信双方的应答关系。
开放系统互连参考模型(OSI)力求将网络简化,并以模块化的方式来设计网络。
开放系统互联参考模型把计算机网络分为物理层,数据链路层,网络层,传输层,会话层,表示层,应用层等七层。
通信协议是网络通信的基础,而IP协议是一种非常重要的协议。IP(InternetProtocol)协议又称互联网协议,是支持网间互联的数据报协议。它提供了网间连接完善的功能,包括IP数据报规定互联网络范围内的地址格式。
TCP(Transmission Control Protocol)协议,即传输控制协议,它规定一定可靠的数据信息传递服务,虽然IP和TCP这两个协议不尽相同,也可以分开单独使用,但他们是在同一个时期作为一个协议来设置的,并在功能上也是互补的。因此在实际使用中常常把这两个协议统称为TCP/IP协议。TCP/IP协议也是Internet中最常用的协议。
按TCP/IP协议模型,网络通常被分为一个四层模型,这个四层模型和前面的OSI七层模型有对应关系:
在这里插入图片描述
IP地址和端口号:
Ip地址用于标志网路中的一个通信实体,这个通信实体可以是一台主机,也可以是打印机,或者是路由器。而在基于Ip协议网路中传输的数据包,都必须使用IP地址来进行标识。
Ip地址是数字型的,IP地址是一个32位(32bit)整数,但通常为了更加便于记忆,通常也把它分成四个8位的二进制数组成,每个8位之间用圆点隔开,每个8位整数可以换成一个0~255的十进制整数,因此我们看到的Ip地址通常是如:202.9.128.88
NIC(Internet Network Information Center)统一负责全球的InternetIP地址的规划,管理。
IP地址被分为A,B,C,D,E五类,每个类别的网络标识和住居标识各有规则:
A类:10.0.0.0~10.255.255.255
B类:172.16.0.0~172.31.255.255
C类:192.168.0.0~192.168.255.255
Ip地址可以唯一的确定网络上的一个通信实体,但一个通信实体可以有多个通信程序同时提供网络服务,此时还需要使用端口。
端口是一个16位的整数,用于标识数据交给哪个通信程序处理。因此,端口就是应用程序与外界交流的出入口,它是一种抽象的软件结构,包括一些数据结构和I/O(基本输入/输出)缓冲区。
不同的应用程序处理不同端口上的数据,同一台机器不能有两个程序使用同一个端口,端口号可以从0到65535,通常分为三类:
公认端口号(Well Known Ports):从0到1023,他们紧密绑定(BInding)一些服务
注册端口号(Registered Ports):从1024到49151.他们松散的绑定一些服务
动态和/或私有端口号(Dynamic and/or Private Ports):从49152到65535,这些端口号是应用程序使用的动态端口,应用程序一般不会主动使用这些端口。
Java的基本网络支持
Java为网络支持提供了Java.net包,该包下的URL和URLConnection等类提供了以编程方式访问Web服务功能,而URLDecoder和URLEncoder则提供了普通字符串和Application/x-www-from-urlencoded MIME字符串相互转换的静态方法。
使用InetAddress
Java提供了InetAddress类来代表IP地址,InetAddress下还有两个子类:Inet4Address,Inet6Address他们分别代表Internet Protocol version4(IP v4)地址和Internet Protocol version6(IP v6)地址。
InetAddress类没有提供构造器,而是提供了如下两个静态方法来获取InetAddress实例
getByName(String host):根据主机获取对应的InetAddress对象
getByAddress(byte[] addr):根据原始IP地址来获取对应的InetAddress对象
InetAddress还提供了如下三个方法来获取InetAddress实例对应的IP地址和主机名
String getCanonicalHostName():获取此IP地址的全限定域名
String getHostAddress():返回该InetAddress实例对应的IP地址字符串(以字符串形式)
String getHostName():获取此IP地址的主机名。
InetAddress类还提供了一个getLocalHost()方法来获取本机IP地址对应的InetAddress实例。InetAddress提供了一个isReachable()方法,用于测试是否可以达到该地址,该方法的实现将尽最大努力试图到达主机,但防火墙和服务器配置可能阻塞请求,使其在某些特定的端口可以访问时处于不可达的状态。如果可以获得权限,则典型实现将使用ICMP ECHO REQUEST;否则他将试图在目标主机的端口7上建立TCP连接。
如:public class InetAddressTest {
public static void main(String[] args) throws Exception {
//根据主机名来获取对应的InetAddress实例
InetAddress ip=InetAddress.getByName(“www.crazyit.org”);
//判断是否可达
System.out.println(“crazyit是否可达”+ip.isReachable(2000));
//获取该InetAddress实例的IP字符串
System.out.println(ip.getHostAddress());
//根据原始的IP地址来获取对应的InetAddress实例
InetAddress local=InetAddress.getByAddress(new byte[] {127,0,0,1});
System.out.println(“本机是否可达:”+local.isReachable(5000));
//获取InetAddress实例对应的全限定域名
System.out.println(local.getCanonicalHostName());
}
}
使用URLDecoder和URLEncoder
URLDecoder和URLEncoder用于完成普通字符串和application/x-www-form-urlencoded MIME字符串之间的相互转化。
当URL地址里包含非西欧字符的字符串将转换成特殊字符。如果编程过程中可能涉及将普通字符串系和这种特殊字符串的相关转换,这就需要URLDecoder和URLEncoder类,其中:
URLDecoder类包含一个decode(String s,String enc)静态方法,他可以将看上去是乱码的特殊字符串转成普通字符串。
URLEncoder类包含一个encode(String s,String enc)静态方法,他可以将普通字符串转换成application/x-www-form-urlencoded MIME字符串(特殊字符)。
public class URLDecoderTest {
public static void main(String[] args) throws Exception {
//将特殊字符转化成普通字符串
String keyWord=URLDecoder.decode("%E6%9D%8E%E5%88%9A+j2ee",“UTF-8”);
System.out.println(keyWord);
//将字符串转化成特殊字符
String urlstr=URLEncoder.encode(“爸爸”,“GBK”);
System.out.println(urlstr);
}
}
使用URL和URLConnection
URL(Uniform Resource Locator):对象代表统一资源定位器,它是指向互联网资源的指针。资源可以是简单的文件或目录,也可以是对更为复杂的对象引用。通常而言,URL可以由协议名,主机,端口和资源组成,既满足如下格式:
Protocol://host:port/resourceName
如:URL地址
http://www.baidu.org/Index.php
JDK 中还提供了一个URI(Uniform Resource Identifiers)类,其实实例代表一个统一的资源标识符,Java的URL不能用于定位任何资源,他的唯一作用就是解析。与此对应的是,URL则包含一个可打开到达该资源的输入流,因此我们可以将URL理解成URI的特例。
URL类提供了多个构造器用于创建URL对象,一旦获得了URL对象之后,可以调用如下方法来访问URL对应的资源:
String getFile():获取此URL的资源名。
String getHost():获取此URL的主机名
String getPath():获取此URL的路径部分
Int getPort():获取此URL的端口号。
String getProtocol():获取此URL的协议名称。
String getQuery():获取此URL的查询字符串部分
URLConnection openConnection():返回一个URLConnection对象,他表示到URL所引用的远程对象的连接。
InputStream openStream():打开与此URL的连接,并返回一个用于读取该URL资源的InputStream
URL对象提供的openStream()可以读取该URL资源的Input Stream,通过该方法可以读取远程资源——甚至实现多线程下载。如:
public class DownThread extends Thread{
//定义字节数组的长度
private final int BUFF_LEN=32;
//定义下载起始点
private long start;
//结束点
private long end;
//下载资源对应的输入流
private InputStream is;
//下载到字节输出到raf中
private RandomAccessFile raf;
//构造器,输入输入流,输出流和下载起始点,结束点
public DownThread(long start, long end, InputStream is, RandomAccessFile raf) {
System.out.println(start+"---------->"+end);
this.start = start;
this.end = end;
this.is = is;
this.raf = raf;
}
public void run() {
try {
is.skip(start);
raf.seek(start);
//定义读取输入流内容的缓存数组
byte[] buff =new byte[BUFF_LEN];
//本线程负责下载资源的大小
long contentLen=end-start;
//定义最多需要读取几次就可以完成本线程下载
long times=contentLen/BUFF_LEN+4;
//实际读取字节数
int hasRead=0;
for (int i = 0; i < times; i++) {
hasRead=is.read(buff);
//如果读取的字节数小于0,则退出循环
if(hasRead<0)
{
break;
}
raf.write(buff,0,hasRead);
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
//使用Finally来关闭当前线程的输入流,输出流
finally {
try {
if(is!=null)
is.close();
if(raf!=null)
raf.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class MutilDown {

public static void main(String[] args) {
	final int DOWN_THREAD_NUM=4;
	final String OUT_FILE_NAME="down.jpg";
	InputStream[] isArr=new InputStream[DOWN_THREAD_NUM];
	RandomAccessFile[] outArr=new RandomAccessFile[DOWN_THREAD_NUM];
	try {
		//创建一个URL对象
		URL url=new URL("http://images,china-pub.com/ebook35001-40000/35850/shupi.jpg");
		//以此URL对象打开第一个输入流
		isArr[0]=url.openStream();
		long fileLen=getFileLength(url);
		System.out.println("网络资源的大小:"+fileLen);
		outArr[0]=new RandomAccessFile(OUT_FILE_NAME, "rw");
		//创建一个与下载资源相同大小的空文件
		for (int i = 0; i < fileLen; i++) {
			outArr[0].write(0);
		}
		//每个线程应该下载的字节数
		long numPerThred=fileLen/DOWN_THREAD_NUM;
		//整个下载资源整出后剩下的余数
		long left=fileLen%DOWN_THREAD_NUM;
		for (int i = 0; i < DOWN_THREAD_NUM; i++) {
			//为每个线程打开一个输入流,一个Random Access File对象
			//让每个线程分别负责下载资源的不同部分
			if(i!=0)
			{
				//以URL打开多个输入流
				isArr[i]=url.openStream();
				//以指定输出文件创建多个RandomAccess File对象
				outArr[i]=new RandomAccessFile(OUT_FILE_NAME, "rw");
			}
			//分别启动多个线程来下载网络资源
			if(i==DOWN_THREAD_NUM-1)
			{
				new DownThread(i*numPerThred, (i+1)*numPerThred+left, isArr[i], outArr[i]).start();
			}
			else
			{
				new DownThread(i*numPerThred, (i+1)*numPerThred, isArr[i], outArr[i]).start();
			}
		}
		
		
	} catch (Exception e) {
		// TODO: handle exception
		e.printStackTrace();
	}
}
//定义获取指定网络资源的长度方法
public static long getFileLength(URL url) throws Exception
{
	long length=0;
	//打开URL对应的URLCOnnectin
	URLConnection con=url.openConnection();
	//获取连接URL资源长度
	long size=con.getContentLengthLong();
	length=size;
	return length;
}

}
URL的openConnection()方法将返回一个URLConnection对象,该对象表示应用程序和URL之间的通信连接。程序可以通过URLConnection实例向该URL发送请求,读取URL引用资源
通常创建一个和URL的连接,并发送请求,读取此URL引用的资源需要如下几个步骤:
1.通过调用URL对象openConnection()方法来创建URLConnection对象
2.设置URLConnection的参数和普通请求属性
3.如果只是发送GET方式请求,使用connect方法建立和远程资源之间的实际连接即可;如果需要发送POST方式的请求,需要获取URLConnection实例对应的输入流来发送请求参数
4.远程资源变为可用,程序可以访问远程资源的头字段或通过输入流读取远程资源的数据
在建立和远程资源的实际连接之前,程序可以通过如下方法来来设置请求头字段的值。
setAllowUserInteraction:设置URLConnection的allowUserInteraction请求头字段的值。
SetDoInput:设置URLConnection的doInput请求头字段的值
SetDoOutput:设置URLConnection的doOutput请求头字段的值
SetlfModifiedSince:设置该URLConnection的ifModifiedSince请求头字段的值
SetUseCaches:设置该URLConnection的useCaches请求头字段
除此之外,还可以使用如下方法来设置或增加通用头字段:
SetRequestProperty(String key,String value):设置该URLConnection的key请求头字段的值为value。如:
Conn.setRequestProperty(“accept”,”/”)
addRequestProperty(String key,String value):为该URLConnection的key请求头字段的增加value值,该方法并不会覆盖原请求的头字段的值,而是将新值追加到原请求头字段中。
当远程资源可用之后,程序可以使用以下方法用于访问头字段和内容:
Object getContent():获取该URLConnection的内容
String getHeaderField(String name):获取指定响应头字段的值
GetInputStream():返回该URLConnection对应的输入流,用于获取URLConnection响应的内容
GetOutputStream():返回该URLConnection对应的输出流,用于向URLConnection发送请求参数。
如果既要使用输入流读取URLConnection响应的内容,也要使用输出流发送请求参数,一定要先使用输出流,再使用输入流。
GetHeaderFiled方法用于根据响应头字段来返回对应的值,而某些头字段由于经常需要访问所以Java提供了以下方法来访问特定响应头字段的值
GetContentEncoding:获取content-encoding响应头字段的值
GetDate():获取date响应头字段的值
GetExpiration :获取expires响应头字段的值
GetLastModifiex():获取last-modified响应头字段的值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值