什么是网络?
- 由点和线构成,表示诸多对象间的相互联系
计算机网络
- 为实现资源共享和信息传递,通过通信线路连接起来的若干主机。
- 互联网:点与点相连
- 万维网:WWW-World Wide Web 端与端相连
- 物联网:(IoT - Internet of things)物与物相连
网络模型
-
OIS(Oper System Interconnection)开放式系统互联
通信协议 -
TCP/IP 模型
一组用于实现网络互连的通信协议,将协议分为四层。
TCP协议:Transmission Control Protocol 传输控制协议 -
是一种面向连接的、可靠的、基于字节流的传输层通信协议。数据大小无限制。建立连接的过程中需要三次握手,断开连接的过程需要四次挥手
UDP协议:User Datagram Protocol用户数据报协议 -
是一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,每个包的大小64KB
IP与端口
-
IP协议:Inernet Protocol Address 互联网协议地址/网际协议地址
分配给互联网设备的数字标识(唯一标识) -
IP地址分为两种
IPV4:4字节32位整数,并分成4段8位的二进制数,每8位之间用圆点隔开,每8位整数可以转换为一个0~255的十进制整数
格式:D.D.D.D 例如:255.255.255.255IPV6:16字节128位整数,并分成8段十六进制,每16位之间用圆点隔开,每16位整数可以转换为一个0~65535的十进制整数.=
格式:X.X.X.X.X.X.X.X 例如:FFFF.FFFF.FFFFF.FFFF.FFFF.FFFF.FFFF.FFFF
IPV4的应用分类
- A类:政府机构,1.0.0.1~123.255.255.254
- B类:中型企业,128.0.0.1~191.255.255.254
- C类:个人用户,192.0.0.1~223.255.255.254
- D类:用于组播,224.0.0.1~239.255.255.254
- E类:用于实验,240.0.0.1~255.255.255.254
- 回环地址:127.0.0.1,指本机,一般用于测试使用
- 查看IP命令:ipconfig
- 测试IP命令:ping D.D.D.D
Port
- 端口号:在通信实体上进行网络通讯的程序的唯一标识
- 端口分类
公认端口:0~1023
注册端口:1024~49151
动态或私有端口:49152~65535 - 常用端口:
MySql:3306
Oracle:1521
Tomcat:8080
SMTP:25
Web服务器:80
FTP服务器:21
网络编程
InetAddress类
-
概念:标识互联网协议(IP)地址对象,封装了与该IP地址相关的所以信息,并提供获取信息的常用方法。
-
方法:
public static InetAddress getLocalHost()//获得本地主机地址对象 public static InetAddress getByName(String host)//根据主机名称获得地址对象 public static InetAddress[] getAllByName(String host)//获得所有相关地址对象 public String getHostAddress() //获取IP地址字符串 public String getHostName()//获得IP地址主机名
import java.net.InetAddress;
import java.net.UnknownHostException;
public class TestInetAddress {
public static void main(String[] args) throws Exception {
//InetAddress local = new InetAddress();//The constructor InetAddress() is not visible
//构造方法私有化。不能通过构造形式创建对象,通过静态方法获得本类中创建的对象,此方式的好处可以限制创建对象的次数
// MyClass mc = MyClass.getMyClassInstance();
// MyClass mc1 = MyClass.getMyClassInstance();
// MyClass mc2 = MyClass.getMyClassInstance();
// MyClass mc3 = MyClass.getMyClassInstance();
InetAddress local = InetAddress.getLocalHost();//获取本地主机
String ip = local.getHostAddress();//获取本地主机的相关ip,地址
String name = local.getHostName();//
System.out.println(ip+"\t"+name);
//获得任意主机的IP地址对象, IP,主机名、域名
//InetAddress local2 = InetAddress.getByName("192.168.1.3");
//InetAddress local2 = InetAddress.getByName("DESKTOP-EHPGQKV");
//System.out.println(local2);
InetAddress[] address = InetAddress.getAllByName("www.baidu.com");
for(InetAddress add :address) {
System.out.println(add.getHostAddress());
}
}
}
//class MyClass{
// static int count = 0;
// private MyClass() {
//
// }
// public static MyClass getMyClassInstance() {
// if(count == 3) {
// System.out.println("已经创建了"+(count+1)+"次了");
// return null;
// }
// count++;
// return new MyClass();
// }
//}
基于TCP的网络编程
-
Scocket编程:
Socket(套接字)是网络中的一个通信节点
分为客户端Socket与服务器ServerSocket
通信要求:IP地址+端口号ServerSocket 服务器套接字 其中有个accept方法,得到一个Socket(也就是客户端)。 Socket客户端 有指定Ip地址的指定端口号的有参构造方法 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200318225812415.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDI1NTgyOQ==,size_16,color_FFFFFF,t_70)
开发步骤
- 建立通信连接(会话):
创建ServerSocket,指定端口号
调用accept等待客户端接入 - 客户端请求服务器:
创建Socket,指定服务器IP+端口号
使用输出流,发送请求数据给服务器
使用输入流,接收响应数据到客户端(等待) - 服务器响应客户端:
使用输入流,接收请求的数据到服务器(等待)
使用输出流,发送响应数据给客户端
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws Exception {
//1.创建一个服务套接字
ServerSocket server = new ServerSocket(6666);
//2.调用accept等待客户端
Socket client = server.accept();
//3.通过客户端获取输入输出流
InputStream is = client.getInputStream();//字节流
InputStreamReader isr = new InputStreamReader(is,"UTF-8");//桥转换
BufferedReader br = new BufferedReader(isr);//过滤流
OutputStream os = client.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os,"UTF-8");
PrintWriter pw = new PrintWriter(osw);
//4.读取数据
String message = br.readLine();
System.out.println("客户端说:"+message);
//5.响应数据
pw.println("客服端,你好");
pw.flush();
//6.关闭
pw.close();
br.close();
client.close();
server.close();
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) throws Exception{
//1.创建客户端 IP+端口号
Socket client = new Socket("192.168.0.105",6666);
//2.获取输入输出流
InputStream is = client.getInputStream();//字节流
InputStreamReader isr = new InputStreamReader(is,"UTF-8");//桥转换
BufferedReader br = new BufferedReader(isr);//过滤流
OutputStream os = client.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os,"UTF-8");
PrintWriter pw = new PrintWriter(osw);
//3.发送数据
pw.println("服务器,你好");
pw.flush();
//4.接收响应数据
String message = br.readLine();
System.out.println("服务器说:"+message);
//5.关闭
pw.close();
br.close();
client.close();
}
}
互聊案例:
import java.net.ServerSocket;
import java.net.Socket;
/*
* 服务器接收多个客户端请求
* 主线程:接收请求
* 子线程:负责接收数据
*/
public class Server {
public static void main(String[] args) throws Exception {
ServerSocket server = new ServerSocket(8888);
while(true) {
Socket client = server.accept();
DataThread dt = new DataThread(client);
dt.start();
}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class DataThread extends Thread{
private Socket client;
public DataThread(Socket client) {
this.client=client;
}
Scanner sc = new Scanner(System.in);
public void run() {
//接收数据
try {
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream(),"UTF-8"));
PrintWriter pw = new PrintWriter( new OutputStreamWriter(client.getOutputStream(),"UTF-8"));
while(true) {
String msg = br.readLine();
System.out.println(client.getInetAddress().getHostName()+"说:"+msg);
String callmsg = sc.next();
pw.println(callmsg);
pw.flush();
if(msg.equals("88")||msg.equals("byebye")) {
System.out.println(client.getInetAddress().getHostName()+"退出了聊天");
break;
}
}
} catch (IOException e) {
System.out.println(client.getInetAddress().getHostName()+"退出了聊天");
}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Client1 {
public static void main(String[] args) throws Exception, IOException {
Socket client = new Socket("192.168.0.105",8888);
PrintWriter pw = new PrintWriter( new OutputStreamWriter(client.getOutputStream(),"UTF-8"));
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream(),"UTF-8"));
Scanner sc = new Scanner(System.in);
while(true) {
String msg = sc.next();
pw.println(msg);
pw.flush();
String callmsg = br.readLine();
System.out.println("服务器回复"+callmsg);
if(msg.equals("88")||msg.equals("byebye")) {
break;
}
}
pw.close();
client.close();
System.out.println("您退出了");
}
}
课堂案例
- 使用Scoket编程实现服务器端注册:
注册信息保存在properties文件中
封装格式
id = {id:“1001”,name:“tom”,pwd:“123”,age:20,score:98.5}
注册成功后返回字符串”注册成功“ - 使用Scoket编程实现服务器端登录:
获取properties文件中的用户信息,进行用户名 与密码的校验
校验成功后返回字符串”登录成功“
Client.java
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
/*
* 注册
* 登录
*/
public class Client {
public void reg() {
try {
Socket client = new Socket("192.168.0.107",9999);
ClientRegThread crt = new ClientRegThread(client);
crt.start();
crt.join();
} catch (Exception e) {
e.printStackTrace();
}
}
public void login() {//快速加try catch alt+shift+z
try {
Socket client = new Socket("192.168.0.107",8888);
ClientLoginThread clt = new ClientLoginThread(client);
clt.start();
clt.join();
} catch (Exception e) {
e.printStackTrace();
}
}
}
ClientLoginThread.java
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class ClientLoginThread extends Thread{
private Socket client;
public ClientLoginThread(Socket client) {
this.client = client;
}
@Override
public void run(){
try {
//1/获得输入输出流
InputStream is = client.getInputStream();
InputStreamReader isr = new InputStreamReader(is,"UTF-8");
BufferedReader br = new BufferedReader(isr);
OutputStream os = client.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os,"UTF-8");
PrintWriter pw = new PrintWriter(osw);
//2.用户输入数据,并拼接整理
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名:");
String username = sc.next();
System.out.println("请输入密码:");
String password = sc.next();
String userinfo = username+"#"+password;
//3.提交给服务器
pw.println(userinfo);
pw.flush();
//4,接收服务器的回应
String msg = br.readLine();
System.out.println(msg);
//5.关闭
pw.close();
br.close();
client.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
ClientRegThread.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class ClientRegThread extends Thread{
private Socket client;
public ClientRegThread(Socket client) {
this.client = client;
}
@Override
public void run() {
try {
//1/获得输入输出流
InputStream is = client.getInputStream();
InputStreamReader isr = new InputStreamReader(is,"UTF-8");
BufferedReader br = new BufferedReader(isr);
OutputStream os = client.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os,"UTF-8");
PrintWriter pw = new PrintWriter(osw);
//2.用户输入数据,并拼接整理
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名:");
String username = sc.next();
System.out.println("请输入密码:");
String password = sc.next();
String userinfo = username+"#"+password;
//3.提交给服务器
pw.println(userinfo);
pw.flush();
//4,接收服务器的回应
String msg = br.readLine();
System.out.println(msg);
//5.关闭
pw.close();
br.close();
client.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
LoginThread.java
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Properties;
import java.util.Scanner;
public class LoginThread extends Thread{
private Socket client;
private Properties userPros;
public LoginThread(Socket client,Properties userPros) {
this.client = client;
this.userPros = userPros;
}
@Override
public void run() {
try {
//1/获得输入输出流
InputStream is = client.getInputStream();
InputStreamReader isr = new InputStreamReader(is,"UTF-8");
BufferedReader br = new BufferedReader(isr);
OutputStream os = client.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os,"UTF-8");
PrintWriter pw = new PrintWriter(osw);
//2.用户输入数据,并拼接整理
String userinfo = br.readLine();
String[] users = userinfo.split("#");
String username = users[0];
String password = users[1];
//3.验证
if(userPros.containsKey(username)) {
if(userPros.getProperty(username).equals(password)) {
pw.println("登录成功!");
pw.flush();
}else {
pw.println("登录失败,密码错误");
pw.flush();
}
}else {
pw.println("登录失败,账号不存在:");
pw.flush();
}
pw.close();
br.close();
client.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
RegThread.java
import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Properties;
public class RegThread extends Thread{
//客户端
private Socket client;
//配置文件
private Properties userPros;
public RegThread(Socket client, Properties userPros) {
this.client = client;
this.userPros = userPros;
}
//线程任务
public void run() {
try {
//1.获得输入输出流
InputStream is = client.getInputStream();
InputStreamReader isr = new InputStreamReader(is,"UTF-8");
BufferedReader br = new BufferedReader(isr);
OutputStream os = client.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os,"UTF-8");
PrintWriter pw = new PrintWriter(osw);
//2.获得用户提交数据 zhangsan#123
String userinfo = br.readLine();
String[] users = userinfo.split("#");
String username = users[0];
String password = users[1];
//3.判断用户名是否存在
if(userPros.containsKey(username)) {
pw.println("用户已存在!请重新输入....");
pw.flush();
}else {
//存到集合对象里
userPros.setProperty(username, password);
//存到硬盘的文件里
//4.如果不存在,应该保存,并告知当前客户端,注册成功!
userPros.store(new FileWriter("Files\\userPros.properties"),null);
pw.println("注册成功。。。");
pw.flush();
}
//5.关闭资源
pw.close();
br.close();
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Server.java
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;
/*
* 服务器对象
* 注册
* 登录 userPros.properties
* 将注册任务,登录任务的两个线程去做
*/
public class Server {
private Properties userPros;
public Server() {
userPros = new Properties();//用于存储properties文件内容
File file = new File("Files\\userPros.properties");
if(file.exists()) {
try {
//是把外部文件加载到userPros对象中
userPros.load(new FileReader(file));
} catch (Exception e) {
System.out.println("加载文件失败!");
}
}
}
//注册
public void registerUser() {
try {
//1.创建服务端
ServerSocket server = new ServerSocket(9999);
System.out.println("注册线程已启动");
while(true) {
//2.接收客户端
Socket client = server.accept();
//3.将客户端对象和配置文件传给注册线程
new RegThread(client,userPros).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void login() {
try {
//1.创建服务端
ServerSocket server = new ServerSocket(8888);
System.out.println("登录线程已启动");
while(true) {
//2.接收客户端
Socket client = server.accept();
//3.将客户端对象和配置文件传给注册线程
LoginThread It = new LoginThread(client,userPros);
It.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
StartMenu.java
import java.util.Scanner;
public class StartMenu {
public static void main(String[] args) {
Client client = new Client();
System.out.println("欢迎进入夸夸系统");
Scanner sc = new Scanner(System.in);
int choice = 0;
do {
System.out.println("请输入您的选择:1.注册 2.登录 0.退出");
choice = sc.nextInt();
switch(choice) {
case 1:
client.reg();
break;
case 2:
client.login();
default:
break;
}
}while(choice!=0);
System.out.println("欢迎下次再来");
}
}
StartServer.java
public class StartServer {
public static void main(String[] args) {
Server server = new Server();//启动服务
//两个线程,并发调用方法
new Thread() {//匿名内部类
public void run() {
server.registerUser();
};
}.start();
new Thread() {//匿名内部类
public void run() {
server.login();
};
}.start();
}
}