欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

CoreJava学习心得14

程序员文章站 2022-07-13 21:36:58
...
ObjectInputStream和ObjectOutputStream(对象流)

对象流是过滤流,需要节点流作参数来构造对象。用于直接把对象写入文件和从文件读取对象。只有实现了Serializable接口的类型的对象才可以被读写,Serializable接口是个标记接口,其中没有定义方法。对象会序列化成一个二进制代码。

writeObject(o), Object readObject()这两个是对象读写操作时用的方法。

Object o = new Object();	
	FileOutputStream fos=new FileOutputStream("Object.txt");
	ObjectOutputStream oos=new ObjectOutputStream(fos);
	oos.writeObject(o);
	oos.close();

	FileInputStream fis =new FileInputStream(“Object.txt”);
	ObjectInputStream ois =new ObjectInputStream(fis);
	Object o = (Object)Ois.readObject();
	ois.close();


对象流读取结束返回 EOFException异常对象。
一个类中有其他类型的对象,那么,这个类实现了Serializable接口,在对象序列化时,也同样要求这个类中属性都能够对象序列化(基本类型除外)。

注意:对于对象流的操作,在写对象时要一次写入完毕,如果使用追加模式写入,只会读取到上一次写入的对象,使用对象流写入时,会先写入一个头部,然后写入数据,最后加上结束符号,如果使用追加方式写入的话,那就会在结束符号继续向下写入,但是在读取时只会读到结束符为止,以后再次写入的数据就会丢失。

注意:在使用对象流写入对象时要一次向文件写入,不能够采用追加方式。

serialver命令判断是否一个属性或对象可序列化,
serialver TestObject(TestObject必须为已经编译,也就是.class)
执行结果:如果不可序列化;则出现不可序列化的提示。如果可以序列化,那么就会出现序列化的ID:UID。

Externalizable这是Serializable的子接口,他可以让用户自定义如何序列化对象。
readExternal(ObjectInput in),writeExternal(ObjectOutput out)这是这个接口中的两个方法,通过这两个方法可以定制序列化过程。这个方法不安全,可以调用以上两个方法改变对象的状态。

transient只能用来修饰属性。表示这个属性在对象序列化时将被忽略。
transient int num;
表示当我们对属性序列化时忽略这个属性(即忽略不使之持久化)。所有属性必须都是可序列化的,特别是当有些属性本身也是对象的时候,要尤其注意这一点。


java.util.StringTokenizer类,这个类是用于字符串截取的。
StringTokenizer(参数1,参数2)按某种符号隔开文件
StringTokenizer(s,”:”) 用“:”隔开字符,s为对象。

补充:字节流结束返回-1,字符流结束返回null,对象流结束返回 EOFException
引申---------〉异常经常被用在流程控制, 异常也是方法的一种返回形式。
例:
import java.io.*;
public class TestObjectStream {
	public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub
		FileOutputStream fo=new FileOutputStream("student.dat");
		ObjectOutputStream out=new ObjectOutputStream(fo);
		Student s=new Student(20,"Liucy");
		out.writeObject(s);
		
		out.close();
		
		FileInputStream fi=new FileInputStream("student.dat");
		ObjectInputStream in=new ObjectInputStream(fi);
		Object o=in.readObject();
		
		System.out.println(o);
		

	}

}

class Student implements Serializable {
	transient int age;
	String name;
	public Student(int age, String name) {
		super();
		// TODO Auto-generated constructor stub
		this.age = age;
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String toString(){
		return "Student "+this.name+" age="+this.age;
	}
}


JAVA网络编程

网络基础知识

网络编程的目的就是指直接或间接地通过网络协议与其他计算机进行通讯。
计算机网络形式多样,内容繁杂。网络上的计算机要互相通信,必须遵循一定的协议。目前使用最广泛的网络协议是Internet上所使用的TCP/IP协议。
IP地址:计算机在网络中唯一标识,相对于internet,IP为逻辑地址。

IP地址分类

A类地址
A类地址第1字节为网络地址,其它3个字节为主机地址。另外第1个字节的最高位固定为0。
A类地址范围:1.0.0.1到126.155.255.254。
A类地址中的私有地址和保留地址:
10.0.0.0到10.255.255.255是私有地址(所谓的私有地址就是在互联网上不使用,而被用在局域网络中的地址)。
127.0.0.0到127.255.255.255是保留地址,用做循环测试用的。

B类地址

B类地址第1字节和第2字节为网络地址,其它2个字节为主机地址。另外第1个字节的前两位固定为10。
B类地址范围:128.0.0.1到191.255.255.254。
B类地址的私有地址和保留地址
172.16.0.0到172.31.255.255是私有地址
169.254.0.0到169.254.255.255是保留地址。如果你的IP地址是自动获取IP地址,而你在网络上又没有找到可用的DHCP服务器,这时你将会从169.254.0.0到169.254.255.255中临得获得一个IP地址。

C类地址

C类地址第1字节、第2字节和第3个字节为网络地址,第4个个字节为主机地址。另外第1个字节的前三位固定为110。
C类地址范围:192.0.0.1到223.255.255.254。
C类地址中的私有地址:
192.168.0.0到192.168.255.255是私有地址。

D类地址
D类地址不分网络地址和主机地址,它的第1个字节的前四位固定为1110。
D类地址范围:224.0.0.1到239.255.255.254

Mac地址:每个网卡专用地址,也是唯一的。
端口(port):应用程序(进程)的标识(网络通信程序)OS中可以有65536(2^16)个端口,进程通过端口交换数据。连线的时候需要输入IP也需要输入端口信息。
计算机通信实际上的主机之间的进程通信,进程的通信就需要在端口进行联系。
192.168.0.23:21
协议:为了进行网络中的数据交换(通信)而建立的规则、标准或约定,协议是为了保证通信的安全。
不同层的协议是完全不同的。

网络层:寻址、路由(指如何到达地址的过程)
传输层:端口连接
TCP模型:应用层/传输层/网络层/网络接口
层与层之间是单向依赖关系,上层依赖于下层,下层不依赖于上层,层与层之间的连接是虚连接。对等层之间建立协议。
端口是一种抽象的软件结构,与协议相关:TCP23端口和UDT23端口为两个不同的概念。
端口应该用1024以上的端口,以下的端口都已经设定功能。

TCP/IP模型

Application
(FTP,HTTP,TELNET,POP3,SMPT)
Transport
(TCP,UDP)
Network
(IP,ICMP,ARP,RARP)
Link
(Device driver,….)

注:
IP:寻址和路由
ARP(Address Resolution Protocol)地址解析协议:将IP地址转换成Mac地址
RARP(Reflect Address Resolution Protocol)反相地址解析协议:与上相反
ICMP(Internet Control Message Protocol)检测链路连接状况。利用此协议的工具:ping , traceroute

TCP Socket

TCP是Tranfer Control Protocol的简称,是一种面向连接的保证可靠传输的协议。通过TCP协议传输,得到的是一个顺序的无差错的数据流。发送方和接收方的成对的两个socket之间必须建立连接,以便在TCP协议的基础上进行通信,当一个socket(通常都是server socket)等待建立连接时,另一个socket可以要求进行连接,一旦这两个socket连接起来,它们就可以进行双向数据传输,双方都可以进行发送或接收操作。
   1) 服务器分配一个端口号,服务器使用accept()方法等待客户端的信号,信号一到打开socket连接,从socket中取得OutputStream和InputStream。
   2) 客户端提供主机地址和端口号使用socket端口建立连接,得到OutputStream和InputStream。
TCP/IP的传输层协议

      

建立TCP服务器端

一般,我们把服务器端写成是分发Socket的,也就是总是在运行,
创建一个TCP服务器端程序的步骤:
   
    1). 创建一个ServerSocket
    2). 从ServerSocket接受客户连接请求
    3). 创建一个服务线程处理新的连接
    4). 在服务线程中,从socket中获得I/O流
    5). 对I/O流进行读写操作,完成与客户的交互
    6). 关闭I/O流
    7). 关闭Socket
ServerSocket server = new ServerSocket(post)
Socket connection = server.accept();
ObjectInputStream put=new ObjectInputStream(connection.getInputStream());
ObjectOutputStreamo put=newObjectOutputStream(connection.getOutputStream());  
处理输入和输出流;
关闭流和socket。
典型的服务器端。
public class Server1 {
	public static void main(String[] args) throws Exception {
		ServerSocket ss=new ServerSocket(9000);
		while(true){
			Socket s=ss.accept();//获得一个Socket对象。
			Thread t=new Thread1(s);//分发Socket。
			t.start();
		}
	}
}
class Thread1 extends Thread{
	Socket s;
	public Thread1(Socket s){
		this.s=s;
	}
	public void run(){
		try {
			OutputStream o=s.getOutputStream();
			PrintWriter out=new PrintWriter(o);
			out.println("Hello Client");
			out.flush();
			s.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
	}
} 

建立TCP客户端

创建一个TCP客户端程序的步骤:

    1).创建Socket
    2). 获得I/O流
    3). 对I/O流进行读写操作
    4). 关闭I/O流
    5). 关闭Socket
Socket connection = new Socket(127.0.0.1, 7777);
ObjectInputStream input=new ObjectInputStream(connection.getInputStream());
ObjectOutputStream utput=new ObjectOutputStream(connection.getOutputStream());
处理输入和输出流;
关闭流和socket。
例:
服务器端:
import java.net.*;
import java.io.*;
public class Server1 {
	public static void main(String[] args) throws Exception {
		ServerSocket ss=new ServerSocket(9000);
		while(true){
			Socket s=ss.accept();
			Thread t=new Thread1(s); //为每个线程分配的Socket
			t.start();
		}
	}
}
class Thread1 extends Thread{
	Socket s;	
public Thread1(Socket s){
		this.s=s;
	}
	public void run(){
		try {
			OutputStream o=s.getOutputStream();
			PrintWriter out=new PrintWriter(o);
			out.println("Hello Client");
			out.flush();
			s.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
	}
}

客户端:
import java.net.*;
import java.io.*;
public class Client1 {

	public static void main(String[] args) throws Exception{
		Socket s=new Socket("127.0.0.1",9000);
		InputStream i=s.getInputStream();
		InputStreamReader ir=new InputStreamReader(i);
		BufferedReader in=new BufferedReader(ir);
		String str=in.readLine();
		System.out.println(str);
		s.close();

	}

}

UDP socket
这种信息传输方式相当于传真,信息打包,在接受端准备纸。
特点:
1) 基于UDP无连接协议
2) 不保证消息的可靠传输
3) 它们由Java技术中的DatagramSocket和DatagramPacket类支持
DatagramSocket(邮递员):对应数据报的Socket概念,不需要创建两个socket,不可使用输入输出流。
DatagramPacket(信件):数据包,是UDP下进行传输数据的单位,数据存放在字节数组中,其中包括了目标地址和端口以及传送的信息(所以不用建立点对点的连接)。
DatagramPacket的分类:
用于接收:DatagramPacket(byte[] buf,int length)
  DatagramPacket(byte[] buf,int offset,int length)
用于发送:DatagramPacket(byte[] buf,int length, InetAddress address,int port )
  DatagramPacket(byte[] buf,int offset,int length,InetAddress address,int port)

注:InetAddress类网址用于封装IP地址
没有构造方法,通过
InetAddress.getByAddress(byte[] addr):InetAddress
InetAddress.getByName(String host):InetAddress
等。

建立UDP 发送端

创建一个UDP的发送方的程序的步骤:

    1). 创建一个DatagramPacket,其中包含发送的数据和接收方的IP地址和端口
号。
    2). 创建一个DatagramSocket,其中包含了发送方的IP地址和端口号。
    3). 发送数据
4). 关闭DatagramSocket

byte[] buf = new byte[1024];
//1。
DatagramPackage outputPackage = new DatagramPackage(buf,buf.length,
inetAddress,port);
//2。
DatagramSocket datagramSocket = new DatagramSocket(13);// set port
//3。
datagramSocket.send(outputPackage);

datagramSocket.close

注意:没建立流所以不用断开。

建立UDP 接受端

创建一个UDP的接收方的程序的步骤:

    1). 创建一个DatagramPacket,用于存储发送方发送的数据及发送方的IP地址和端口号。
    2). 创建一个DatagramSocket,其中指定了接收方的IP地址和端口号。
    3). 接收数据
    4). 关闭DatagramSocket
byte[] buf = new byte[1024];
//不用设端口,因为发送的包中端口
//1。
DatagramPackage inputPackage=new DatagramPackage(buf,buf.length);
//2.
DatagramSocket datagramSocket = new DatagramSocket();
//3。
datagramSocket.receive(inputPackage);
//4.
datagramSocket.close();

例:
import java.net.*;
public class UDPServer {
	public static void main(String[] args) throws Exception {
		DatagramSocket socket=new DatagramSocket(3000);
		while(true){
			//收信
			byte[] bs2=new byte[20];
			DatagramPacket letter2=new DatagramPacket(bs2,0,bs2.length);
			socket.receive(letter2);
			
			//写回信
			InetAddress address=letter2.getAddress();
			int port=letter2.getPort();
			String str="唐亮结婚了!!!";
			byte[] bs=str.getBytes();
		    DatagramPacket letter
=new DatagramPacket(bs,0,bs.length,address,port);
			socket.send(letter);	
		}
		
	}
}



import java.net.*;
public class UDPClient {
	public static void main(String[] args) throws Exception {
		DatagramSocket socket=new DatagramSocket();
		//发信
		String str="Hi,I am here";
		byte[] bs=str.getBytes();
		DatagramPacket letter1
=new DatagramPacket(bs,0,bs.length,InetAddress.getLocalHost(),3000);
		socket.send(letter1);
		//收信
		byte[] bs2=new byte[20];
		DatagramPacket letter2=new DatagramPacket(bs2,0,bs2.length);
		socket.receive(letter2);
		bs2=letter2.getData();
		int off=letter2.getOffset();
		int length=letter2.getLength();
		String str2=new String(bs2,off,length);
		System.out.println(str2);
		
		socket.close();
		
	}

}