收获总结
- 加深了流用法的理解,字节字符流之间输入输出已经转换流的用法示意图
- 缓冲流是对普通流的再次包装,增加了缓冲区以增加每次读取的数据的数量。
- 因为缓冲流是对底层流的再次封装,在缓冲流数据输出时每输出一次要使用flush()方法将缓冲区的数据强制冲入底层流中否则数据不能被写入。
- Java的网络通讯客户端使用Socket类,生成类时需要指定服务器的IP地址和端口号,服务端使用的类为ServerSocket只需要指定端口号。
- 网络通讯所使用的流区别于普通的流使用getInputStream()或者getOutputstream()来构造流。
- getbyName方法的使用
确定主机名称的IP地址,主机名称可以是字符或者文本格式的IP地址如果输入文本格式的IP地址只会检查IP地址的有效性 - getAddress和getHostAddress的区别
getAddress是获取主机的IP返回此InetAddress对象的原始IP地址。用于寻址。
getHostAddress返回文本显示中的IP地址字符串。 用于输出文本。 - bind方法的用法
DatagramSocket datagramSocket = new DatagramSocket(null);
datagramSocket.bind(new InetSocketAddress(5000));//使用时DatagramPacket要赋值为null
/*
public void bind(SocketAddress addr)
throws SocketException将此DatagramSocket绑定到特定的地址和端口。
如果地址为null ,则系统将接收临时端口和有效的本地地址来绑定套接字。
//InetSocketAddress是SocketAddress的子类
InetSocketAddress(int port) 创建一个套接字地址,其中IP地址为地址标识符,端口号为指定值。
其他的构造方法
InetSocketAddress(String hostname, int port) 从主机名和端口号创建套接字地址。
InetSocketAddress(InetAddress addr, int port) 从IP地址和端口号创建套接字地址。
*/
学习笔记整理
IP地址
- IP地址:计算机在网络上的唯 一标识符,是计算机的一种身份识别的形式。
IP地址:
查看本机IP地址:ifconfig
查看网络是否连接:ping IP地址或主机名或域名
4类:4字节,32位 , 01010101001
6类:16节字,128位,010101010010101010 - 本机回路地址:
127.0.0.1 :代表当前主机
localhost:代表当前主机
端口
- IP地址主要用来标识网络上的唯一的一台计算机,端口是计算机中用来标识不同的应用程序,进行数据传输。
端口的值在0-65535之间,占2个字节;一般在计算机中0-1023的端口大部分已经被操作系统或其它网络程序所占用。
InetAddress
- Java中用来表示网络地址、端口、主机标识符等信息的一个类
static InetAddress getLocalHost ():返回本地主机地址的InetAddress对象
String getHostAddress( ):返回本地主机IP
String getHostName( ):返回本地主机名称。
Java中的网络协议
TCP协议下的网络编程:
4.1、TCP协议的通讯原理
TCP协议:面向连接,稳定的一种通讯协议,在连接之前向服务器端发送确认连接,等待服务器的响应。建立连接之后再传输数据,可靠、无数据差异的一种通讯协议。
TCP的协议,每次连接前,都 需要经过三次握手,以保证连接的可靠性。
典型的采用TCP协议的应用有:
浏览网页,
4.2、TCP协议的特点:
1、面向连接
2、可靠
3、占有用资源多,资源开源大
4.3、TCP协议下的网络编程的实现
需要服务器端,也要有客户端,服务器端实现服务器端的通讯接口,客户端实现客户端的通讯接口。
都是实现不同的套接字,实现了TCP协议下的数据传输的端点。
服务器端:
ServerSocket类用来支持TCP协议下的服务器端的编程。
ServerSocket() :创建服务器端的套接字对象。
ServerSocket(int port) :创建服务器端的套接字对象,并邦字指定的监听端口。
ServerSocket(int port, int backlog)
ServerSocket(int port, int backlog, InetAddress bindAddr)
注意:
1、要邦定监听的端口。
2、accept()方法,用来接收客户端的请求。 在执行时,处于阻塞状态,当监听到客户端的套接对象连接时,接收客户端的套接对对象。
3、通过套接字对象提供的IO进行数据的传输。传输底层是IO的对象进行数据的读写。
4、注意结束后,关闭相关资源(IO和Socket对象)。
常用方法:
Socket accept()
bind(SocketAddress endpoint)
ServerSocketChannel getChannel()
- 通讯实例
服务器端的实现过程:
/*
TCP协议下的服务器端的程序:
实现步骤:
1、创建服务器端的套接字对象
2、调用accept()方法,等待客户端的连接
3、通过Socket对象创建 IO输入与输出流对象
4、将数据写入输入与输出流。
5、关闭相关对象。
*/
public static void main(String[] args) {
try {
//1、创建服务器端的套接字对象
ServerSocket serversk = new ServerSocket(4001);
System.out.println("服务器端running .........");
// 2、
Socket socket= serversk.accept();//服务器在此行代码处,一直阻塞直到有客户端的套接字连接。
// 服务器端向客户端发送数据。
//3、通过Socket创建输出流
OutputStream outputStream = socket.getOutputStream();
String serstr = "hello Huike";
//创建字节输出缓冲流
BufferedOutputStream buffer = new BufferedOutputStream(outputStream);
//4、将服务器端传入至客户端的数据写入输出流
buffer.write(serstr.getBytes());
// 5、关闭相关对象。
buffer.close();
outputStream.close();
socket.close();
serversk.close();
} catch (IOException e) {
e.printStackTrace();
}
}
客户端端:
Socket类用来支持TCP协议下的客户端的编程。
构造方法:
Socket()
Socket(InetAddress address, int port)
Socket(InetAddress host, int port, boolean stream)
Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
Creates a socket and connects it to the
常用方法:
bind(SocketAddress bindpoint)
void close()
void connect(SocketAddress endpoint)
void connect(SocketAddress endpoint, int timeout)
SocketChannel getChannel()
InetAddress getInetAddress()
InputStream getInputStream()
OutputStream getOutputStream()
注意:
1、指定连接的服务器端地址
2、要指定通讯的端口号。
客户端的实现过程:
/*
客户端的实现过程:
1、创建客户端的套接对象,(Socket对象)并指定服务器端的地址和通讯的端口号。
2、通过Socket对象,创建输入与输出流
3、发送或接收数据
4、关闭相关资源
*/
public static void main(String[] args) {
try {
// 1、创建客户端的套接对象,(Socket对象)并指定服务器端的地址和通讯的端口号。
Socket socket = new Socket(InetAddress.getLocalHost(),4001);
//2、创建输入流,从输入流中读取服务器端发过的数据
InputStream inputStream = socket.getInputStream();
byte b [] = new byte[1024];
//将输入流转换成缓冲流
BufferedInputStream buffer= new BufferedInputStream(inputStream);
// 3、发送或接收数据
int i =buffer.read(b);
System.out.println(new String(b,0,i));
// 4、关闭相关资源
buffer.close();
inputStream.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
UDP协议
UDP协议:是一种数据包协议,无状态(非连接型),不可靠,可能存在数据丢包的情况。协议简单、对资源开销较少
只有发达方和接受方的概念,一般应用的场景是:如聊天、视频。
每个是数据包64KB每个数据包单独寻址
- UDP协议的网络编程:
- 在java.net包中提供了两个类DatagramSocket和来支持数据包通信
- DatagramSocket类:数据包套接字类,主要是为每个数据包单独寻址和路由。
DatagramSocket()
//构造数据报套接字并将其绑定到本地主机上的任何可用端口。
DatagramSocket(int port)
//构造数据报套接字并将其绑定到本地主机上的指定端口。
DatagramSocket(int port, InetAddress laddr)
//创建一个数据报套接字,绑定到指定的本地地址。
protected DatagramSocket(DatagramSocketImpl impl)
//使用指定的DatagramSocketImpl创建一个未绑定的数据报套接字。
DatagramSocket(SocketAddress bindaddr)
//创建一个数据报套接字,绑定到指定的本地套接字地址。
3. DatagramPacket类:数据报包,主要是为UDP协议封装数据包。
DatagramPacket(byte[] buf, int length) 构造一个 DatagramPacket用于接收长度为 length数据包。
DatagramPacket(byte[] buf, int offset, int length) 构造一个 DatagramPacket用于接收长度为 length数据包,指定缓冲区的偏移量。
DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port) 构造一个数据包,发送长度为 length的数据包,其中偏移量为 ioffset到指定主机上的指定端口号。
DatagramPacket(byte[] buf, int offset, int length, SocketAddress address) 构造一个数据报包,发送长度为 length的数据包,偏移量为 ioffset到指定主机上的指定端口号。
DatagramPacket(byte[] buf, int length, InetAddress address, int port) 构造一个数据包,发送长度为 length的数据包到指定主机上的指定端口号。
DatagramPacket(byte[] buf, int length, SocketAddress address) 构造一个数据包,发送长度为 length的数据包到指定主机上的指定端口号。
- 实现步骤
发送方:
1. 创建DatagramSocket数据包套接字对象
2. 创建要发送的数据、并转换成可发送的数据、目标地址和端口号
3. 创建DatagramPacket数据包对象,并制定发送的数据、目标地址和端口号。
4. 通过DatagramSocket对象的send()芳芳发送数据报包对象。
5. 关闭相关对象
接收方:
1. 创建DatagramSocket数据包套接字。
2. 创建要接受的byte数组。
3. 创建DatagramPacket数据报包对象,从套接字对象中接受发送方发送过来的数据报包。
4. 通过receive()方法接收。
5. 关闭相关对象
- 实现方法
//发送方
try {
//创建DatagramSocket对象
DatagramSocket datagramSocket = new DatagramSocket();//默认是0
String sentmsg = "hello world";
byte[] data = sentmsg.getBytes();
//创建DatagramPacket对象指定打包的数据和发送的地址端口号
DatagramPacket datagramPacket = new DatagramPacket(data,data.length, InetAddress.getLocalHost(),5000);
//将要发送的数据丢出
datagramSocket.send(datagramPacket);
System.out.println("发送完成!");
//关闭相关端口
datagramSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
//接收方
try {
//创建数据包的对象确定端口号
DatagramSocket datagramSocket = new DatagramSocket(5000);
//创建要接受的byte数组
byte[] data = new byte[1024];
//创建数据包对象
DatagramPacket datagramPacket = new DatagramPacket(data,data.length);
System.out.println("准备就绪准备接包!");
//准备接包
datagramSocket.receive(datagramPacket);//在此处出于阻塞状态,等待数据。
System.out.println("接受到来自其他人的数据"+new String(data));
//关闭相关对象
datagramSocket.close();;
} catch (IOException e) {
e.printStackTrace();
}
- 循环发送实例
- 针对发送方发送的消息,接收方给当前的发送方回复“收到”
- 解决接收方获取发送方的地址(IP地址) 、端口号。
while (true) {
//2、创建要接收数据的byte数组
byte data[] = new byte[1024];
//3、创建数据报包对象
DatagramPacket datagramPacket = new DatagramPacket(data, data.length);
System.out.println("等待接包:");
//4、DatagramPacket数据报包对象,从套接字对象中接收发送方发送过来的数据报包。
datagramSocket.receive(datagramPacket);//处于阻塞
String ip= datagramPacket.getAddress().getHostAddress();//发送方的IP地址
int port = datagramPacket.getPort();//发送方的端口号
String receMsg = new String(data);
System.out.println(ip+","+port+":"+getDateToString()+" 说:"+receMsg);
if ("end".equals(receMsg.trim())) break;
}
- 根据发送方的IP地址和端口,给发送回复消息
public static void main(String[] args) throws IOException , SocketException{
// 1、 创建DatagramSocket数据包套接字对象
DatagramSocket datagramSocket = new DatagramSocket(null);
//邦定端口号
datagramSocket.bind(new InetSocketAddress(5000));
while (true) {
//2、创建要接收数据的byte数组
byte data[] = new byte[1024];
//3、创建数据报包对象
DatagramPacket datagramPacket = new DatagramPacket(data, data.length);
System.out.println("等待接包:");
//4、DatagramPacket数据报包对象,从套接字对象中接收发送方发送过来的数据报包。
datagramSocket.receive(datagramPacket);//处于阻塞
String ip= datagramPacket.getAddress().getHostAddress();//发送方的IP地址
int port = datagramPacket.getPort();//发送方的端口号
String receMsg = new String(data);
System.out.println(ip+","+port+":"+getDateToString()+" 说:"+receMsg);
//给指定的发送方回复“已读”
String ok = "已读";
byte okdata [] = ok.getBytes();
//创建新的数据报包对象
DatagramPacket sendPack = new
DatagramPacket(okdata,okdata.length,datagramPacket.getAddress(),port);
datagramSocket.send(sendPack);//将已读的数据报包对象发送至发送方
if ("end".equals(receMsg.trim())) break;
}
//5关闭相关对象
datagramSocket.close();
System.out.println("程序退出");
}