网络通信
/*
* 网络通信:三大要素:IP,端口号,协议
* 1.IP:可以在网络中唯一的标记一台主机 127.0.0.1(本地地址/本机地址/保留地址) java中将IP面向对象了--InetAddress
* 2.端口:用来区分一台主机上的多个服务器(不可以重复) 取值范围:(0,65535) 注意点:在通信时两边的端口号要一致
* 3.网络协议:相当于指定的一个统一的标准
*
* 七层协议: 了解
* 应用层
与其它计算机进行通讯的一个应用,它是对应应用程序的通信服务的。
例如,一个没有通信功能的字处理程序就不能执行通信的代码,
从事字处理工作的程序员也不关心OSI的第7层。但是,如果添加了一个
传输文件的选项,那么字处理器的程序员就需要实现OSI的第7层。
示例:TELNET,HTTP,FTP,NFS,SMTP等。
表示层
这一层的主要功能是定义数据格式及加密。例如,FTP允许你选择以二进制
或ASCII格式传输。如果选择二进制,那么发送方和接收方不改变文件的内容。
如果选择ASCII格式,发送方将把文本从发送方的字符集转换成标准的ASCII后
发送数据。在接收方将标准的ASCII转换成接收方计算机的字符集。示例:加密,ASCII等。
会话层
它定义了如何开始、控制和结束一个会话,包括对多个双向消息的控制和管理,
以便在只完成连续消息的一部分时可以通知应用,从而使表示层看到的数据是连续的,
在某些情况下,如果表示层收到了所有的数据,则用数据代表表示层。示例:RPC,SQL等。
传输层
这层的功能包括是否选择差错恢复协议还是无差错恢复协议,及在同一主机上对不同
应用的数据流的输入进行复用,还包括对收到的顺序不对的数据包的重新排序功能。
示例:TCP,UDP,SPX。
网络层
这层对端到端的包传输进行定义,它定义了能够标识所有结点的逻辑地址,还定义了
路由实现的方式和学习的方式。为了适应最大传输单元长度小于包长度的传输介质,
网络层还定义了如何将一个包分解成更小的包的分段方法。示例:IP,IPX等。
数据链路层
它定义了在单个链路上如何传输数据。这些协议与被讨论的各种介质有关。示例:ATM,FDDI等。
物理层
OSI的物理层规范是有关传输介质的特性标准,这些规范通常也参考了其他组织制定的标准。
连接头、帧、帧的使用、电流、编码及光调制等都属于各种物理层规范中的内容。
物理层常用多个规范完成对所有细节的定义。示例:Rj45,802.3等。
InetAddress
ip面向对象
属性
hostname
localhost
public class Demo2 {
public static void main(String[] args) throws UnknownHostException {
// InetAddress java将IP面向对象了形成的类
//获取本机的网络信息
InetAddress inetAddress = InetAddress.getLocalHost();
System.out.println(inetAddress.getHostName());//D5B5
System.out.println(inetAddress.getHostAddress());//10.0.15.215
//获取网络上的任意一台主机的信息
InetAddress inetAddress2 = InetAddress.getByName("www.baidu.com");//改成ip也可以
System.out.println(inetAddress2.getHostName());//www.baidu.com
System.out.println(inetAddress2.getHostAddress());//182.61.200.7
}
}
URL
-
URL:统一资源定位器
-
URI:统一资源定位符
-
URL的功能:可以通过它的方法直接获取网址的各个部分,还可以访问网络的资源
*/
public class Demo3 {
public static void main(String[] args) throws IOException {
URL url = new URL(“https://www.bingbing.com:333/a/b?name=bing&age=18”);
System.out.println(url.getProtocol());//协议
System.out.println(url.getPath());//资源路径
System.out.println(url.getHost());//主机名/域名/IP地址
System.out.println(url.getQuery());//查询条件
System.out.println(url.getPort());//端口
System.out.println(url.getDefaultPort());//默认端口 443
//System.out.println(url.getContent());//查询的内容URL url2 = new URL("https://www.baidu.com"); //System.out.println(url2.getContent()); //URLConnection代表客户端与服务器端的通信通道,这个类的实例可以用于读取或者写入url引入的资源 URLConnection connection = url2.openConnection(); //获取内部的字节输入流 InputStream inputStream = connection.getInputStream(); //进行读写 byte[] arr = new byte[1024]; inputStream.read(arr); System.out.println(new String(arr,"utf8"));
}
}
模拟UDP通信 DatagramSocket
/* 客户端:(app/浏览器)
- 服务器端:!=主机
- 端口号:同一台主机上的每一个服务器都拥有自己的端口号,取值范围(0,65535),常用的端口:80,8080
- 注意点:1.要保证客户端和服务器端的端口号一致 2.要保证同一台主机上的不同服务器端口号不同
**** TCP与UDP的区别:**
-
TCP UDP
- 1.是建立在连接的基础上 建立在非连接的基础上
- 2.安全性更高 安全性低
- 3.传输速度低 速度高
- 4.适合传输数据量大的数据 数据量小的数据
- */
//模拟UDP通信
//客户端
/*
-
1.创建UDP通信的对象-socket对象:对应的类是DatagramSocket.(用于UDP数据的发送与接收)
-
2.数据的准备-封装包:DatagramPacket(数据包,包括相关的属性,数据)
-
3.发送数据,通过send方法
-
4.关闭socket对象
*/
作为UDP的客户端 send
public class Demo4 {
public static void main(String[] args) throws IOException {
//模拟UDP通信
//客户端//* 1.创建UDP通信的对象-socket对象:对应的类是DatagramSocket.(用于UDP数据的发送与接收) DatagramSocket socket = new DatagramSocket();
// * 2.数据的准备-封装包:DatagramPacket(数据包,包括相关的属性,数据)
/* 打包
* 参数一:要传输的数据
* 参数二:数据的长度
* 参数三:服务器所在主机的地址
* 参数四:服务器的端口
/
byte[] buf = “bingbing”.getBytes();
DatagramPacket packet = new DatagramPacket(buf, buf.length, InetAddress.getLocalHost(), 20000);
// 3.发送数据,通过send方法
socket.send(packet); //怎么发送的
//* 4.关闭socket对象
socket.close();
}
}
作为UDP的服务器端 receive
public class Demo5 {
public static void main(String[] args) throws IOException {
//服务器端:接收数据
/*
* 1.创建socket对象,并绑定端口号—DatagramSocket
* 2.创建包对象,创建空数组,准备接收传来的数据
* 3.接收数据
* 4.关闭相关的对象
/
System.out.println(“启动服务器成功,可以随时接收数据”);
// * 1.创建socket对象,并绑定端口号—DatagramSocket
DatagramSocket socket = new DatagramSocket(20000);
// 2.创建包对象,创建空数组,准备接收传来的数据
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
//* 3.接收数据:当服务器运行起来,让他一直处于监听状态的方法
socket.receive(packet);
//显示所有数据
byte[] bytes = packet.getData();
System.out.println(new String(bytes));
//* 4.关闭相关的对象
socket.close();
}
}
随时发随时收UDP
//* 随时发随时收–使用UDP完成
//客户端
public class Demo6 {
public static void main(String[] args) throws IOException {
//* 1.创建UDP通信的对象-socket对象:对应的类是DatagramSocket.(用于UDP数据的发送与接收)
DatagramSocket socket = new DatagramSocket();
// * 2.数据的准备-封装包:DatagramPacket(数据包,包括相关的属性,数据)
/* 打包
* 参数一:要传输的数据
* 参数二:数据的长度
* 参数三:服务器所在主机的地址
* 参数四:服务器的端口
*/
//对比之下 就是换成了输入源
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String data = null;
while ((data = bufferedReader.readLine()) != null) {
DatagramPacket packet = new DatagramPacket(data.getBytes(), data.length(), InetAddress.getLocalHost(), 20000);
//* 3.发送数据,通过send方法
socket.send(packet);
//当输入over的时候结束
if (data.equals("over")) {
break;
}
}
//* 4.关闭socket对象
socket.close();
}
}
服务器端 socket
public class Demo7 {
public static void main(String[] args) throws IOException {
System.out.println(“启动服务器成功,可以随时接收数据”);
// * 1.创建socket对象,并绑定端口号—DatagramSocket
DatagramSocket socket = new DatagramSocket(20000);
//不断的接收数据
while (true) {
//* 2.创建包对象,创建空数组,准备接收传来的数据
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
//* 3.接收数据:当服务器运行起来,让他一直处于监听状态的方法
socket.receive(packet);
//显示所有数据
byte[] bytes = packet.getData();
String data = new String(bytes);
System.out.println(new String(bytes));
//当输入over的时候结束 if (data.trim().equals(“over”)) {
break;
}
}
//* 4.关闭相关的对象
//socket.close();
}
}
服务器怎么停止 停止一直是客户端 输入over
客户端
soket 发送容器
packet 打包 装信息(装入端口)
soket.send(packet) 发送功能
服务器
soket 绑定端口
packet 接收信息
socket.recieve(packet)
TCP
/*
TCP:
-
在客户端与服务器端通信的时候,对于客户端既要进行输入又要进行输出,所以在Socket对象的内部就内置了输入流和输出流,
-
当进行数据传输的时候,将数据放入socket对象的内部,将socket对象传到服务器端,相当于在客户端与服务器端建立了一个通道,
-
两端使用同一个socket对象.
*/
TCP的客户端 Socket
public class Demo8 {
public static void main(String[] args) throws IOException {//1.创建Socket对象并绑定端口,管理服务器主机 Socket socket = new Socket(InetAddress.getLocalHost(), 30000); //2.准备数据 String data = "BigData1924,你好"; //3.调用Socket内部的输出流向网络写数据 OutputStream outputStream = socket.getOutputStream(); outputStream.write(data.getBytes()); //3.使用socket的输入流将服务器回传的信息打印 InputStream inputStream = socket.getInputStream(); //将内容打印到控制台 byte[] arr = new byte[100]; int num = inputStream.read(arr); String data1 = new String(arr,0,num); System.out.println(data1); socket.close();
}
}
服务器端 ServerSocket
public class Demo9 {
public static void main(String[] args) throws IOException {
//1.创建ServerSocket对象并设置端口
ServerSocket serverSocket = new ServerSocket(30000);
//2.接收从客户端传来的socket对象
Socket socket = serverSocket.accept();
//下面的都一样
//3.使用socket的输入流卸货
InputStream inputStream = socket.getInputStream();
//将内容打印到控制台
byte[] arr = new byte[100];
int num = inputStream.read(arr);
String data = new String(arr,0,num);
System.out.println(data);
//给客户端回发一个信息,告知接收成功
//获取socket的输出流
OutputStream outputStream = socket.getOutputStream();
outputStream.write("你好,BigData1924".getBytes());
//4.关闭资源
serverSocket.close();
}
}
实现大小写转换的服务器TCP
-
这里最好都不要使用缓冲流等进行封装,就使用原始的流.否则在进行读写的时候,不能正确的在客户端与服务器端之间响应
-
如果使用了缓冲流等,要使用打印流的println,printf等方法,并且打印流要使用new PrintWriter(OutputStream o,boolean b)
-
并且b=true
*/
客户端
public class Demo10 {
public static void main(String[] args) throws UnknownHostException, IOException {
//1.创建Socket对象并绑定服务器的地址和端口
Socket socket = new Socket(InetAddress.getLocalHost(), 22200);//2.准备数据---实现让用户从控制台输入 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); //3.获取socket内部的输出流 OutputStream outputStream = socket.getOutputStream(); PrintWriter printWriter = new PrintWriter(outputStream,true);//当第二个参数为true的时候,会自动刷新, //只有调用println/printf方法是起作用. //4.将数据写入网络 String data = null; while ((data = bufferedReader.readLine()) != null) { printWriter.println(data); //当输入over的时候,代表结束 if ("over".equals(data)) { break; } //接收从服务器传回的数据 //将内容写到控制台 InputStream inputStream = socket.getInputStream(); BufferedReader bufferedReader2 = new BufferedReader(new InputStreamReader(inputStream)); String data2 = bufferedReader2.readLine(); System.out.println("data1:"+data2); } //5.关闭资源 bufferedReader.close(); bufferedReader2.close(); printWriter.close(); socket.close();
}
}
服务器端
//服务器端
public class Demo11 {
public static void main(String[] args) throws IOException {
//1.创建ServerSocket对象并绑定接口
ServerSocket serverSocket = new ServerSocket(22200);
//2.接收套接字的连接,保证客户端与服务器端使用同一个socket对象---一直处于监听的状态
Socket socket = serverSocket.accept();
//3.获取输入流
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//获取输出流
PrintWriter printWriter = new PrintWriter(socket.getOutputStream(),true);
//读写过程
String data = null;
while ((data = bufferedReader.readLine()) != null) {
//打印到控制台
System.out.println(data.toUpperCase());
//实现将服务器的数据写回客户端
//这里必须使用println,不能用print
printWriter.println(data.toUpperCase());
System.out.println("haha");
//当输入over的时候,代表结束
if ("over".equals(data)) {
break;
}
}
//5.关闭资源
bufferedReader.close();
printWriter.close();
serverSocket.close();
}
}