java学习
网络编程
1.网络分层
网络分层是将网络通信划分为不同的逻辑层次,每一层负责特定的功能,从而实现网络通信的模块化和标准化。常用的网络分层模型包括OSI(开放系统互联)模型和TCP/IP模型。
特点和作用:
- 分层模型使得网络协议更易于设计、实现和维护,每一层都有明确定义的功能和接口。
- 分层模型提供了标准化的接口和协议,不同厂商和组织之间可以基于共同的标准进行通信和互操作。
- 每一层的功能清晰划分,有助于故障排除和性能优化。
总的来说,网络分层模型是一种组织网络通信的方式,将复杂的通信过程分解为多个层次,使得网络设计和管理更加简单和可靠。
2.网络编程三要素
2.1 IP地址
IP地址相当于每台计算机的标识符,也就是“名字”,如果想要实现计算机的网络通信,那么IP地址就是帮助你找到你想要通信的计算机的方式。
IP地址分类为IP4,和IP6。
IP4又四个字节组成,32位,大约可以表示42亿台计算机,但是随着电子产品的增多,IP4分配的地址明显是不够的,那么我们就需要一种能分配更多地址的方式,那就是IP6。
IP6有16字节,128位,号称可以为地球的每一粒沙子命名。
如果想要知道自己电脑的IP地址,可以Win+R打开黑窗口,输入ipconfig就可以查看自己电脑的IP4和IP6地址(一些新的设备没有IP4地址)。
2.2 端口
如果说IP地址是计算机的标识,那么端口号就是应用程序的标识,没有端口号,两台计算机之间也不能实现网络通信。
端口分类:
公认端口:0~1023。被预先定义的服务通信占用(如:HTTP占用端口80,FTP占用端口21,Telnet占用端口23)
注册端口:1024~49151。分配给用户进程或应用程序。(如:Tomcat占用端口8080,MySQL占用端口3306,Oracle占用端口1521等)。(我们后面开发的程序可以使用这个范围的端口号)
动态/私有端口:49152~65535。
端口号与IP地址的组合得出一个网络套接字:Socket。
2.3 协议
网络通信协议是一组规则和约定,用于在计算机网络中进行通信和数据交换。这些协议定义了数据如何在网络中传输、路由和处理。常见的网络通信协议包括:
-
TCP(传输控制协议):提供可靠的、面向连接的通信服务,确保数据的顺序传输和不丢失。常用于需要可靠数据传输的应用,如网页浏览、文件传输等。
-
UDP(用户数据报协议):提供无连接的通信服务,数据传输不可靠,不保证数据的顺序和完整性。常用于实时应用,如音视频传输、在线游戏等。
-
IP(互联网协议):定义了计算机在网络上的唯一标识(IP地址),以及数据包的格式和路由规则。IPv4和IPv6是目前广泛使用的两个版本。
-
HTTP(超文本传输协议):用于在客户端和服务器之间传输超文本文档,是万维网的核心协议。通过HTTP,用户可以访问网页、发送和接收电子邮件等。
-
HTTPS(超文本传输安全协议):是HTTP的安全版本,通过SSL/TLS加密协议保护数据传输的安全性和完整性。
-
FTP(文件传输协议):用于在网络上传输文件,支持文件上传、下载和管理。
-
SMTP(简单邮件传输协议):用于在网络上传输电子邮件,定义了电子邮件的格式和传输规则。
-
POP3(邮局协议第3版)和IMAP(互联网消息访问协议):用于接收和管理电子邮件的协议,POP3将邮件下载到本地客户端,而IMAP在服务器上管理邮件,客户端只是远程访问邮件。
-
DNS(域名系统):将域名映射到IP地址的分布式数据库系统,用于解析域名和进行网络寻址。
-
ARP(地址解析协议):将IP地址解析为物理地址(MAC地址)的协议,用于在局域网中进行通信。
这些网络通信协议共同构成了计算机网络的基础,实现了各种应用和服务之间的通信和交互。
这里为我们着重讲UDP通信和TCP通信。
3.UDP
从上面图片我们可以看到,使用UDP通信时,不需要与向接收的一方提前建立联系,直接发送信息,信息是否传送到了,不能得知,如果接收信息的一方没在线,发送信息的一方仍然可以发送信息,所以信息是否安全发送不能保证,但是没有了事先的建立联系,通信效率也提高了不少。
实现UDP通信,主要使用到下面方法。
下面我们用代码实现一下。
用户端:
public class Client {
public static void main(String[] args) {
//1、创建客户端,发消息的人
try {
DatagramSocket socket =new DatagramSocket();
//2、创建包含信息的包
Scanner scan=new Scanner(System.in);
while (true) {
String msg=scan.nextLine();//输入字符串
byte[] bytes=msg.getBytes();//转换成字节数组
if("exit".equals(msg))//退出判断
{
socket.close();
break;
}
//将信息包装
DatagramPacket packet=new DatagramPacket(bytes,bytes.length, InetAddress.getLocalHost(),6666);
//发送信息包
socket.send(packet);
}
} catch (Exception e) {//捕获异常
throw new RuntimeException(e);
}
}
}
服务端:
public class Server {
public static void main(String[] args) {
try {
//1。创建服务端对象
DatagramSocket socket =new DatagramSocket(6666);//指定端口号
//2,创建一个数据包对象,用于接受数据
byte[] buffer =new byte[1024*64];
DatagramPacket packet =new DatagramPacket(buffer,buffer.length);
while (true) {
//接收信息包
socket.receive(packet);
int len=packet.getLength();
String s1=new String(buffer,0,len);
System.out.println(s1);//打印信息
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
4.TCP
发送信息:
接收信息:
下面我们用多线程实现一个服务端连接多个用户端,并且可以实现多发多收。
服务端:
package com.lenrn.tcp;
import java.io.DataInputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class Server {
public static void main(String[] args) throws Exception {
//1.实例化一个serversocket对象
ServerSocket serverSocket=new ServerSocket(6886);
//2.等待客户端连接,程序暂停,等待客户端的连接请求
System.out.println("服务端启动");
while (true) {
//多次与新用户连接
Socket socket= serverSocket.accept();
System.out.println("已经与"+socket.getRemoteSocketAddress()+"建立连接");
//子线程
new ServerReadThread(socket).start();
}
}
}
class ServerReadThread extends Thread{
private Socket socket;
public ServerReadThread(Socket socket)
{
this.socket=socket;
}
@Override
public void run() {
try {
//3.从socket对象中得到一个字节输入流、
InputStream is = socket.getInputStream();
//4.将低级的字节输入流包装成数据输入流
DataInputStream dis=new DataInputStream(is);
while (true)
{
String rs= dis.readUTF();
System.out.println(rs);
}
} catch (Exception e) {
System.out.println(socket.getRemoteSocketAddress()+"下线了");
}
}
}
用户端:
用户端多开需要勾选选项。
勾选应用即可。
package com.lenrn.tcp;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws Exception {
//1.创建一个Socket对象,同时请求连接服务端
Socket socket=new Socket("127.0.0.1",6886);
//2.从socket管道中得到一个字节输出流
OutputStream os=socket.getOutputStream();
//3.将低级的字节输出流包装成数据输出流
DataOutputStream dos=new DataOutputStream(os);
//4.写数据出去
Scanner scan=new Scanner(System.in);
while (true) {
String msg = socket.getRemoteSocketAddress().toString();
msg+=": ";
String k=scan.nextLine();
msg+=k;
if("exit".equals(k))
{
System.out.println("退出成功");
dos.close();
socket.close();
break;
}
dos.writeUTF(msg);
}
}
}