3、高级应用:
3.1:集合
程序运行过程中,需要临时存放数据时,可以用集合存放数据
-
可以当作容器(存放数据)
-
可以存放不同数据类型的数据,但是用的时候还是会放相同类型的数据
-
没有长度限制(数组有长度限制)(企业级应用都用集合)
和集合相关的东西在:java . util 中
Collection
List Set
ArrayList HashSet
LinkedList TreeSet
Map(key,value)
-
HashMap TreeMap HashTable
3.2:List List:数据可以重复 ArrayList:底层是用数组实现的;遍历快,插入、删除比较慢 LinkedList:底层是用链表实现的;插入删除比较快,查询比较慢 Vector:线程安全的
3.3:Set Set: HashSet:数据不能重复 两个对象的hashCode和equals都相同;HashSet把这两个对象看成是相同的 对象;在hashSet中放时,只能放一个。
TreeSet:数据是会排序的
1、 向TreeSet中放的对象的类实现java.lang.Comparable接口;实现接口中的compareTo方法,在compareTo方法中进行排序
2、 在创建TreeSet对象时,在构造器中传入java.util.Comparator接口的对象;要重写java.util.Comparator接口的compare方法进行排序
3.4:Map
Map(key/value)
HashMap:key值不能重复
TreeMap:key值进行排序
HashTable:线程安全的
3.5:集合案例代码
package com.briup.bt3.day27;
import java.util.*;
import java.util.Map.Entry;
public class TreeSetTest{
static class MyComparator2 implements Comparator{
public int compare(Object o1,Object o2){
//......
return 0;
}
}
public static void main(String[] args){
test2();
}
public static void test1(){
//传参,自定义比较器
Set set=new TreeSet(new MyComparator());
set.add("ArrayList");
set.add("TreeMap");
set.add("HashMap");
set.add("TreeSet");
set.add("LinkedList");
set.add("HashSet");
print(set);
}
public static void test2(){
Set set=new TreeSet(new Comparator(){
//1,2,3,4,5
public int compare(Object o1,Object o2){
int n1=(int)o1;
int n2=(int)o2;
// System.out.println(n1+"-----"+n2);
if(n1%2==0&&n2%2==0){
return -1;
}
if(n1%2==0&&n2%2==1){
return 1;
}
if(n1%2==1&&n2%2==0){
return -1;
}
if(n1%2==1&&n2%2==1){
return 1;
}
return 0;
}
});
for(int i=1;i<11;i++){
set.add(i);
}
print(set);
}
public static void test3(){
Map map=new HashMap();
//key - value
//l - 7
//map
String str="ljkdklajfdkjfldkajfkklqaag";
//将字符串转换成字符数组
char[] arr=str.toCharArray();
for(int i=0;i<arr.length;i++){
//当map集合中存在我们要添加的key时
//使key对应value+1保存到map
if(map.containsKey(arr[i])){
map.put(arr[i],((int)map.get(arr[i]))+1);
}else{
//当map中不存在key值时,直接添加
map.put(arr[i],1);
}
}
print(map);
}
public static void print(Collection coll){
Iterator iter=coll.iterator();
while(iter.hasNext()){
System.out.println(iter.next());
}
}
public static void print(Map map){
Set set=map.entrySet();
for(Object o:set){
Entry en=(Entry)o;
System.out.println(en.getKey()+":"+en.getValue());
}
}
}
//定义比较器
class MyComparator implements Comparator{
public int compare(Object o1,Object o2){
String s1=(String)o1;
String s2=(String)o2;
//默认升序,加上-,变成降序
return -s1.compareTo(s2);
}
}
3.6:增强for
jdk1.5以后可用
//遍历集合和数组
for((数组|集合的)数据类型 变量名b:数组 | 集合){
//b变量名(集合|数组中的每一个元素)
}
-
所有的数组都可以被增强for遍历。
-
属于java.lang.Iterator的集合才可以直接使用增强for遍历。
-
普通for能做的事情,增强for不一定能做,增强for能做的事情,普通for都能做
For each
for(dataType var:array | Collection){
var
}3.7:泛型
泛型:T E K V
Point<T1,T2>{
T1 x
T2 y
public void test( T t ){ }
}Point<type,Type>
List<?> list=new xx;
上限和下限
3.8:枚举
1、 什么时候用到枚举
2、 怎么定义枚举
enum enumName{
value(){ },value(){ };
//属性 方法 (private)构造器
}
3、 定义的枚举类型都隐含的继承了java . lang . Enum
4、 枚举中定义的每一个值,就是枚举类型的一个实例(对象)
需求:TrafficLight
Red Yellow Green
3.9:反射
最重要的几个类:
Class:
所有类的类
类名.class;
对象.getClass();
Class.forName(“packageName.ClassName”);
Field:属性
Method
Constructor
3.10:镜像
1、获取类的Class对象
Class c=Student.class;
Class c=new Student().getClass();
2、获取类中的属性
3、获取方法
4、获取构造器
5、如果构造的镜像里面有无参的构造器可以直接创造对象
c.newInstance
3.11:异常
异常:
1、 错误:
2、 异常:
1、 处理异常的方式
1)try{
//可能出现异常的代码
}catch(xxException e){
//处理异常的方法(在出现异常时执行)
}finally{
//不管抛步抛异常,都会被执行
}
2)在可能出现异常的代码所在的方法上面throws xxException;异常抛给调用者(谁调用该方法,异常就抛给谁)如果一直向调用者抛,最终回抛给java虚拟机。
2、异常的分类
Throwable
Error
Exception
1) 编译时异常(checked exception):直接或间接继承了Exception的异常;编译时异常在编译阶段必须被处理
2) 运行时异常(uncheck exception):直接或间接继承了RuntimeException的异常,异常可以不用处理
3、自定义异常
1)自定义类直接或间接继承Exception,这个类就是编译时异常
2)自定义类直接或间接继承RuntimeExce
3.12:GUI
(java)
GUI(图形化界面):
java.awt.*;
容器
组件
布局管理器
事件处理模型:
事件源:(组件)
事件对象:(对事件源所做的操作)
事件监听:(接口(抽象方法))
3.13:进程
一个进程中有多个线程,一个线程只能在一个进程中
进程:内存分配的最小单位
线程:程序执行的最小单位
多进程:
3.14:线程
Java.lang.Thread
1、 class A extends Thread{
public void run(){
//线程的代码
}
}
A a=new A();
a.start();
2、 class B implements Runnable{
public void run(){
//线程的代码
}
}
B b=new b();
Thread t=new Thread(b);
t.start();
Thread t1=new thread(new Runnable(){
public void run(){
线程的代码
}
});
t1.start();
状态转换:
新建状态——》调用start()方法——》就绪状态——》CPU——》运行状态——》run ——》死亡状态
sleep() | join---->block---->interrupt
Account
balance
withdraw
deposit
多线程的同步问题:
对共享资源互斥的问题
synchronized
多线程之间的通信:
wait
notify
notifyall
死锁问题
3.15:IO流
IO流:用来做数据传输、浏览器会封装IO,有方向的信息传输过程
(1)字节流:
InputStream OutputStream
FileInputStream FileOutputStream
1、 创建或获取流的对象
2、 调用read | write写的方法去读写数据
int r=read( ) write®
int r=read(buf) write(buf)
int r=read(buf,0,length) write(buf,0,length)
3、关闭资源
close()
(2)常用到的字节输入流和输出流
in:输入流
1. ByteArrayInputStream: 读取byte类型的数组中的数据
2. FileInputStream: 从文件中读取数据;
3. PipedInputStream: (管道流)连接一个PipedOutputStream;
4. ObjectInputStream: 对象输入流;
5. StringBufferInputStream: 可以读取一个字符串,在API中已经过时
6. SequenceInputStream: 把几个输入流转换为一个输入流;
out: 输出流
1.ByteArrayOutputStream:
2.FileOutputStream
3.PipedoutputStream:
4.ObjectoutputStream
(3)FileInputStream and FileOutputStream
1. 当创建一个FileInputStream对象的时候,文件必须存在以及是可读的
FileInputStream(File file) 读取文件的数据
FileInputStream(String name)读取字符串路径所表示文件的数据
2. 当创建一个FileOutputStream对象的时候,可以创建一个新的文件,也可以覆盖一个已经存在的同名文件。
FileOutputStream(File file)
FileOutputStream(File file, boolean append)
如果要创建的文件已经存在,可以选择向旧文件添加新的内容(append为true)或者新的内容覆盖旧文件的内容(append为false)。
特点:当使用构造器创建好FileOutputStream对象时,如果是覆盖,那么就会创建个新文件把以前文件的内容覆盖掉。
(4) BufferedInputStream类和BufferedOutputStream类
BufferedInputStream类覆盖了被过滤的输入流的读数据行为,利用缓冲区来提高读数据的效率。BufferedInputStream类先把一批数据读入到缓冲区,接下来 read()方法只需要从缓冲区内获取数据,就能减少物理性读取数据的次数。
. BufferedInputStream(InputStream in)——参数in指定需要被过滤的输入流。
. BufferedInputStream(InputStream in, int size)
——参数in指定需要被过滤的输入流。参数size指定缓冲区的大小,以字节为单位。
特点:
1,具有缓冲区,减少读取数据和硬盘的io操作,从而加快速度。
2,可以标记,可以复位(标记的位置重新读取)
BufferedOutputStream有缓冲区的字节输出流,会先把数据写到缓冲区中,如果缓冲区中的数据没有被flush()出去则一直在缓冲区中,当关闭该流的时候会将流中所有数据都flush出去。
. BufferedOutputStream(OutputStream out) 创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
. BufferedOutputStream(OutputStream out, int size)创建一个新的缓冲输出流,以便以指定的缓冲区大小将数据写入指定的底层输出流。
(5) DataInputStream 类 和 DataOutputStream类
数据输入流允许应用程序以独立于机器的方式从底层输入流读取原始Java数据类型。
数据输出流使应用程序以便携式方式将原始Java数据类型写入输出流
注意:使用DataOutputStream写出去的需要用DataInputStream读取。
使用DataOutputStream写出去的数据基本看不懂。
DataInputStream 实现了DataInput接口,用于读取基本类型数据,如int, float, long, double和boolean等。
. readByte()——从输入流中读取1个字节,指它转换为byte类型的数据;
. readLong()——从输入流中读取8个字节,指它转换为long类型的数据;
. readFloat()——从输入流中读取4个字节,指它转换为float类型的数据;
. readUTF()—— 从输入流中读取1到3个字节,指它转换为UTF-8字符编码的字符串;
FileOutputStream fos = new FileOutputStream("src/a.txt");
DataOutputStream bos = new DataOutputStream(fos);
bos.writeInt(10); 写出一个数字
bos.writeBoolean(true); 写出一个true
bos.writeLong(103L); 写出一个103L
bos.writeChar(97); 写出一个97对应的字符
bos.writeDouble(30.23); 写出一个30.23
bos.writeFloat(40.02f); 写出一个40.02f
(6)管道输入和输出类:PipedInputStream 类 和 PipedOutputStream 类
管道输入流从一个管道输出流中读取数据。通常由一个线程向管道输出流写数据,由另一个线程从管道输入流中读取数据,两个线程可以用管道来通信。
两个管道需要联通。联通方式:
1,构造器联通
测试代码:
PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream(pis);
2,调用方法connect(管道流) 联通
PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream();
pis.connect(pos);
注意:两个管道只能联通一次。
(7) PrintStream**
可以输出基本数据类型、对象、字符(字符数组)和字符串,能输出字节流。
PrintStream类既可以输出字节流也可以输出字符流或者字符串。
PrintStream类的输出功能非常强大。
3.16:序列化和反序列化
对象的序列化和反序列化
对象的序列化: 把对象写到一个输出流;
对象的反序列化:从一个输入流中读取一个对象;
1. 对象的持久化
2. 仅仅是一个对象的数据被序列化(将对象的数据序列化成字节流)
3. 标识为transit的数据不能被序列化,transit 字段,只能用于修饰实例变量
4. 要序列化的对象必须实现java.io.Serializable标记接口
对象的序列化主要用于:
1. 网络中传输的是字节流的数据,网络中对象的传输,是将对象的数据经过序列化后转换成字节流。
2. 将对象数据序列化到文件中,将对象数据转换成字节流存储到文件中。
从文件中读取字节流数据并转换成对象叫做对象的反序列化。
序列化Serializable
JAVA对象--------------------->IO流
JAVA对象<---------------------IO流
反序列号Deserializable
ObjectInputStream 和ObjectOutputStream(对象输入和输出流,可以读写基本数据类型和对象)
1. ObjectInputStream 和ObjectOutputStream为应用程序提供对象的持久化存储
2. 一个ObjectInputStream 可以反序列化通过ObjectOutputStream写入的基本数据类型和对象
3. 构造器
ObjectInputStream(InputStream in)
ObjectOutputStream(OutputStream out)
4. 方法
readObject()/writeObject() 将对象写入到输出流中或者从输入流中读取对象
readXXX()/writeXXX() 注:如果文件中放的是long的对象那么必须readLong才能成功。
注:
1. 如果输出的是javaBean这个bean需要实现Serializable 接口,
如果输出的是集合,那么集合中的对象也是需要实现Serializable 接口。
可以输入一个对象,这个对象可以是javaBean,集合,数组。
2. 反序列化读取的仅仅是JAVA对象的数据,而不是JAVA类,
必须提供该JAVA对象所属类的class文件,否则引发ClassNotFound异常。
3. 如果使用序列化机制向文件中写入了多个JAVA对象,
使用反序列化机制恢复对象时必须按实际写入的顺序读取。
4. 当一个可序列化类有多个父类时(包括直接父类和间接父类),
这些父类要么有无参数的构造器,要么也是可序列化的,否则反序列化时将抛出InvalidClassException异常。如果父类是不可序列化的,只是带有无参数构造器,则该父类中定义的成员变量值不会序列化到流中。
5. 递归序列化:如果某个类的成员变量的类型是一个引用类型,
那么这个引用类型必须是可序列化的,否则拥有该类型成员变量的类也是不可序列化的。
6. JAVA序列化机制采用了一种特殊的序列化算法,
要注意,只有第一次调用writeObject()方法输出对象时才会将对象转换成字节序列,并写入到ObjectOutputStream;在后面程序中即使该对象的实例变量发生了改变,再次调用writeObject()方法输出该对象时,改变后的实例变量也不会被输出。
7. 对象的类名、实例变量都会被序列化;方法、类变量、transient实例变量都不会被序列化。
要归档或者序列化的对象必须实现Serializable接口才能被序列化
Serializable 中有个id,但ID不是一定有加的
SerialVersionUid,简言之,其目的是序列化对象版本控制,有关各版本反序列化时是否兼容。
如果在新版本中这个值修改了,新版本就不兼容旧版本,反序列化时会抛出InvalidClassException异常。
如果修改较小,比如仅仅是增加了一个属性,我们希望向下兼容,老版本的数据都能保留,那就不用修改;
如果我们删除了一个属性,或者更改了类的继承关系,必然不兼容旧数据,这时就应该手动更新版本号,即SerialVersionUid。
3.17网络编程
客户端和服务器
如何创建客户端和服务器,为了信息交流,(IO)
网络编程
基本概念:
1、计算机网络
计算机网络是相互连接的独立自主的计算机的集合,最简单的网络形式由两台计算机组成。计算机网络提供以下一些主要功能:资源共享、信息传输与集中处理、均衡负载与分布处理、综合信息服务。
每台计算机在网络中都有唯一标识,这个标识是ip。
IP地址:
1)IP网络中每台主机都必须有一个惟一的IP地址;
2)IP地址是一个逻辑地址;
3)因特网上的IP地址具有全球唯一性;
4)ipconfig/ifconfig:查看本机IP
5)ping:测试连接
6)本地回路地址:127.0.0.1 255.255.255.255是广播地址
7)IPv4:32位,4个字节组成,4个0-255。大概42亿,30亿都在北美,亚洲4亿。2011年初已经用尽。常用点分十进制的格式表示,例如:192.168.0.16。
8)IPv6:8组,每组4个16进制数。例如:1a2b::aaaa:0000:0000:0000:aabb:1f2f
9)java.net.InetAddress类代表IP地址对象
static InetAddress getByName(String host):根据主机获取对应的InetAddress对象。
static InetAddress getByAddress(byte[] addr):根据原始IP地址来获取对应的InetAddress对象。
String getCanonicaHostName():获取此IP地址的全限定域名
String getHostAddress():获取字符串形式的IP地址
String getHostName():获取此IP地址的主机名
2、网络通信
协议:
1)为进行网络中的数据交换(通信)而建立的规则、标准或约定;(=语义+语法+规则) ;
2)不同层具有各自不同的协议。负责对传输速率、传输代码、代码结构、传输控制步骤、出错控制等制定处理标准。
3)语义:用于决定双方对话的类型;语法:用于决定双发对话的格式;变换规则:用于决定通信双方的应答关系。
两台或者多台计算机在网络中交互数据,就是网络通信,网络通信需要按照一定的协议传输数据。
注意数据是计算机上的某一个程序和另一个计算机上的程序交互,所有在在网络中找到计算机,然后找到这个计算机下的某个程序,使用端口号就可以找到计算机下某段程序。
端口号:
端口使用一个16位的数字来表示,它的范围是0--65535,0--1023是公认端口,1024--49151是注册端口,49152--65535是动态或私有端口。
计算机下的程序会都是运行在某个端口号下,并且一个端口号只能运行一个程序。
常用端口:
mysql: 3306
oracle: 1521
http: 80
https:443
tomcat: 8080
QQ: 4000
feiQ: 2425
3、OSI(Open System Interconnection)参考模型
应用层:为用户的应用程序提供网络通信服务;
表示层:处理被传送数据的表示问题,也就是信息的语法和语义,如有必要将使用一种通用的格式在多种格式中进行转换;
会话层:在两个相互通信的应用进程之间建立、组织和协调其相互之间的通信;
传输层:传输层为源端计算机到目的端计算机提供可靠的数据传输服务,隔离网络的上下层协议,使得上层网络应用的协议与下层无关;
网络层:在网络中数据到达目的地有很多线路,网络层就是负责找出最佳的传输线路;
数据链路层:加强物理层的传输功能,建立一条无差错的传输线路;
物理层:二进制传输,确定如何在通信信道上传递比特流;
OSI(Open System Interconnection)参考模型并不是物理实体上存在这七层,这只是功能的划分,是一个抽象的参考模型。进行网络通信时,每层提供本层对应的功能;
1)通信实体的对等层之间不允许直接通信,它们之间是虚拟通信,实际通信在最底层完成;
2)各层之间是严格单向依赖;
3)上层使用下层提供的服务 — Service user;
4)下层向上层提供服务 — Service provider。
5)对等层实体之间虚拟通信;
6)下层向上层提供服务,实际通信在最底层完成。
4、OSI各层所使用的协议
1)应用层:远程登录协议Telnet、文件传输协议FTP(网上下载一个软件或者资料的时候就会使用该协议)、 超文本传输协议HTTP(使用较多,通过IE浏览一个网页的时候就使用该协议)、域名服务DNS(使用较多,通过网络访问一个计算机一般不使用该主机的IP地址,而是通过该主机的域名访问)、简单邮件传输协议SMTP(通过Foxmail发送邮件)、邮局协议POP3等(通过Foxmail收邮件);
2)传输层:传输控制协议TCP、用户数据报协议UDP;
TCP:面向连接的可靠的传输协议;在利用TCP协议进行通信的时候,首先要经过三步握手建立起通信双方的连接,一旦连接建立后就可以通信了。TCP协议提供数据确认和重传的机制,保证数据一定能够到达数据接收端。像打电话。
三次握手:
* 第一次握手:建立连接时,客户端发送syn包到服务器,并进入SYN_SEND状态,等待服务器确认;
* 第二次握手:服务器收到syn包,确认客户的SYN,同时发送一个SYN包,即SYN+ACK包到客户端,此时服务器进入SYN_RECV状态;
* 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK,此包发送完毕,客户端和服务器进入ESTABLISHED[建立]状态,完成三次握手。
* 完成三次握手后,客户端与服务器开始传送数据。
UDP:是无连接的,不可靠的传输协议;采用UDP协议进行通信时,不需要建立连接,可以直接向一个IP地址发送数据,
至于是不是能够收到不能保证,发送过程中数据有可能丢失、IP地址可能不存在、再者IP地址代表的主机没有运行等原因都可能导致不能接收到数据。
3)网络层:网际协议IP、Internet互联网控制报文协议ICMP、Internet组管理协议IGMP。
5、Socket套接字概述:
1)网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。
2)通信的两端都有Socket。
3)网络通信其实就是Socket间的通信。
4)数据在两个Socket间通过IO流传输。
5)Socket在应用程序中创建,通过一种绑定机制与驱动程序建立关系,告诉自己所对应的IP和port。
6、基于TCP的Socket编程步骤:
1)服务器程序编写:
①调用ServerSocket(int port)创建一个服务器端套接字,并绑定到指定端口上;
②调用accept(),监听连接请求,如果客户端请求连接,则接受连接,返回通信套接字;
③调用Socket类的getOutputStream()和getInputStream获取输出流和输入流,开始网络数据的发送和接收;
④最后关闭通信套接字。
2)客户端程序编写:
①调用Socket()创建一个流套接字,并连接到服务器端;
②调用Socket类的getOutputStream()和getInputStream获取输出流和输入流,开始网络数据的发送和接收;
③最后关闭通信套接字。
测试代码:
服务器端:
public static void main(String[] args) throws Exception {
//创建服务器对象,指定运行在8099端口下,这句执行完成以后会占用8099端口,
//在当前代码执行完毕之前8099端口都会被本程序占用
ServerSocket server = new ServerSocket(8099);
System.out.println("服务器启动...");
while(true) {
//监听客户端的连接,如果没有客户端连接代码会阻塞
Socket socket = server.accept();
socket.getInetAddress();//获得客户端的ip
socket.getOutputStream();//获得和客户端连接的输出流
socket.getInputStream();//获得和客户端连接的输入流
socket.close();//关闭连接
}
}
客户端:
public static void main(String[] args) throws Exception {
//参数1: 连接的ip
//参数2: 连接程序所在的端口号
Socket socket = new Socket("127.0.0.1", 8099);
socket.getOutputStream();//获得和服务器连接的输出流
socket.getInputStream();//获得和服务器连接的输入流
socket.close();
}
linux查看命令:
netstat -na | grep port
7、代码优化
1)流进行了优化
InputStream BufferedReader DataInputStream ObjectInputStream
OutputStream PrintStream DataOutputStream ObjectOutputStream
InputStream is = socket.getInputStream(); //获取输入流
OutputStream os = socket.getOutputStream(); //获取输出流
BufferedReader br = new BufferedReader(new InputStreamReader(is));
PrintStream ps = new PrintStream(os);
2)服务端多线程
聊天室应用
8、使用URLDecoder和URLEncoder
当URL地址里包含非西欧字符的字符串时,系统会将其转换成特殊字符串。
中文字符转换方法是根据指定的字符集,每个中文字符占X个字节,每个字节可以转换成两个十六进制的数字,数字前面使用百分号。
URLDecoder.decode(String s,String enc):将特殊字符串转换成普通字符串
URLEncoder.encode(String s,String enc):将普通字符串转换成application/x-www-form-urlencoded MIME字符串
9、URL和URLConnection
1)使用ServerSocket模拟实现WEB服务器
HTTP响应头格式:
HTTP/1.1 200 OK \r\n
accept-ranges: bytes \r\n
Content-Type:text/html;charset=UTF-8 \r\n
Content-Type:image/jpeg \r\n
Content-Length:65535 \r\n
\r\n
业务处理的响应数据
2)URL(Uniform Resource Locator)对象代表同意资源定位器,资源可以是简单的文件或目录,也可以是对更为复杂对象的引用,例如对数据库或搜索引擎的查询。
URL可以由协议名、主机、端口和资源组成,即满足如下格式:
protocol://host:port/resourcename
java.net.URL
URL(...):构造器
String getFile():获取该URL的资源名
String getHost():获取该URL的主机名
String getPath():获取该URL的路径部分
int getPort():获取该URL的端口号
String getProtocol():获取该URL的协议名称
String getQuery():获取该URL的查询字符串部分
InputStream openStream():打开与此URL的连接,并返回一个用于读取该URL资源的InputStream
URLConnection openConnection():返回一个URLConnection对象,它代表了与URL所引用的远程对象的链接
设置HttpURLConnection的参数和普通请求属性
void setConnectTimeout(int timeout)设置连接超时时间
void setRequestMethod(String method)设置请求方式:GET、POST等等
void setDoInput(boolean doinput)发送POST请求时必须设置,且值为true
void setDoOutput(boolean dooutput)发送POST请求时必须设置,且值为true
void setRequestProperty(String key, String value)设置请求头字段的键值对。
void addRequestProperty(String key, String value)增加请求头字段的键值对。
void connect()建立实际的连接
Map<String,List<String>> getHeaderFields()获取所有的响应头字段
Object getContent()获取该URLConnection的内容
InputStream getInputStream()返回该URLConnection对应的输入流,用于获取响应的内容
OutputStream getOutputStream()返回该URLConnection对应的输出流,用于发送请求参数
如果既要使用输入流读取URLConnection响应的内容,又要使用输出流发送请求参数,则一定要先使用输出流,再使用输入流
HTTP请求头格式示例:
GET /test?a=b HTTP/1.1 \r\n
Host: 127.0.0.1:8888 \r\n
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:52.0) Gecko/20100101 Firefox/52.0 \r\n
Accept: */* \r\n
Connection: keep-alive \r\n
\r\n
10、基于UDP的Socket编程步骤:
1)接收端程序编写:
①调用DatagramSocket(int port)创建一个数据报套接字,并绑定到指定端口上;
②调用DatagramPacket(byte[] buf, int length),建立一个字节数组以接收UDP包 ;
③调用DatagramSocket类的receive(),接收UDP包;
④最后关闭数据报套接字。
2)发送端程序编写:
①调用DatagramSocket()创建一个随机端口号的数据报套接字;
②调用DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port),建立要发送的UDP包;
③调用DatagramSocket类的send(),发送UDP包;
④最后关闭数据报套接字。
接收方获取ip和端口号
* String ip = packet.getAddress().getHostAddress();
* int port = packet.getPort();
测试代码:
接收端:
public static void main(String[] args) throws Exception {
//此类表示用于发送和接收数据报数据包的套接字,指定了端口号 就是服务器端
DatagramSocket datagramSocket = new DatagramSocket(8099);
System.out.println("udp开启...");
byte[] buf = new byte[31];
/*
构造一个DatagramPacket用于接收长度的数据包length 。
length参数必须小于或等于buf.length 。
参数
buf - 用于保存传入数据报的缓冲区。
length - 要读取的字节数。
*/
DatagramPacket pack = new DatagramPacket(buf, 31);
datagramSocket.receive(pack);
System.out.println("接收到的数据为 : "+new String(buf));
datagramSocket.close();
}
发送端:
public static void main(String[] args) throws Exception {
//此类表示用于发送和接收数据报数据包的套接字
DatagramSocket ds = new DatagramSocket();
byte[] buf = new byte[31];
for(int i = 0;i<buf.length;i++) {
buf[i] = (byte) i;
}
/**
DatagramPacket的构造器参数:
buf - 数据包数据。
offset - 分组数据偏移量。
length - 分组数据长度。
address - 目的地址。
port - 目的端口号。
* */
//构建数据包
DatagramPacket datagramPacket = new DatagramPacket(
buf, 0,31,InetAddress.getByName("127.0.0.1"),8099);
//发送数据包
ds.send(datagramPacket);
System.out.println("发送完毕...");
ds.close();
}