网络编程

什么是网络?

  • 由点和线构成,表示诸多对象间的相互联系

计算机网络

  • 为实现资源共享和信息传递,通过通信线路连接起来的若干主机。
  • 互联网:点与点相连
  • 万维网: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.255

    IPV6: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();
		
	}
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值