学习Java第三十三天--网络编程

本文全面介绍了计算机网络的基础概念,包括网络模型、通信协议、IP和端口的作用,以及如何使用InetAddress类和Socket编程进行网络通信。通过实际案例,如基于TCP的聊天室和注册系统,深入浅出地讲解了网络编程的原理和实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

16. 网络编程

16.1 什么是网络

16.1.1 网络

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

16.1.2 计算机网络

  • 为实现资源共享和信息传递,通过通信线路连接起来的若干主机(Host);
  • 互联网:(Internet)点与点相连;
  • 万维网:(WWW - World Wide Web)端与段相连;
  • 网络编程:让计算机与计算机之间建立连接、进行通信;

16.2 网络模型

16.2.1 OSI

  • OSI(Oper System Interconnection)开放式系统互联;

在这里插入图片描述

  • 第一层:物理层为设备之间的数据通信提供传输信号和物理介质;(双绞线、光导纤维);
  • 第二层:链路层在物理层上,通过规程或协议(差错控制)来控制传输数据的正确性;(MAC)
  • 第三层:网络层负责定义了能够标识所有网络节点的逻辑地址;(IP地址)
  • 第四层:传输层负责是否选择差错恢复协议、数据流重用、错误顺序重排;(TCP、UDP)
  • 第五层:会话层负责使应用建立和维持会话,使通信在失效时继续恢复通信;(断点续传)
  • 第六层:表示层负责定义转换数据格式及加密,允许选择以二进制或ASCII格式传输;
  • 第七层:应用层负责文件访问和管理、可靠运输服务、远程操作服务。(HTTP、FTP、SMTP)

16.2.2 TCP/IP模型

  • 一组用于实现网络互连的通信协议,将协议分成四个层次;

在这里插入图片描述

  • 第一层:接接口层负责建立电路连接,是整个网络的物理基础,典型的协议包括以太网、ADSL等等;
  • 第二层:网络层负责分配地址和传送二进制数据,主要协议是IP协议;
  • 第三层:传输层负责传送文本数据,主要协议是TCP、UDP协议;
  • 第四层:应用层负责传送各种最终形态的数据,是直接与用户打交道的层,典型协议是HTTP、FTP等;

16.3 通信协议

TCP/UDP

  • TCP协议:Transmission Control Protocol 传输控制协议
  • 是一种面向连接的、可靠的、基于字节流的传输层通信协议。数据大小无限制。建立连接的过程需要三次握手,断开连接的过程需要四次挥手;
  • UDP协议:User Datagram Protocol 用户数据报协议
  • 是一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,每个包的大小64KB;

16.4 IP与端口

16.4.1 IP

IP协议:Internet 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.FFFF.FFFF.FFFF.FFFF.FFFF.FFFF

16.4.2 IPV4的应用分类

  • A类:政府机构,1.0.0.1 ~ 126.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~ 255.255.255.254
  • 回环地址: 127.0.0.1 , 指本机,一般用于测试使用;
  • 查看IP命令:ipconfig
  • 测试IP命令:ping D.D.D.D

16.4.3 Port

  • 端口号:在通信实体上进行网络通讯的程序的唯一标识;

端口分类:

  • 公认端口:0~1023
  • 注册端口:1024~49151
  • 动态或私有端口:49152~65535

常用端口:

  • MySql:3306
  • Oracle:1521
  • Tomcat:8080
  • SMTP:25
  • Web服务器:80
  • FTP服务器:21

16.5 网络编程

16.5.1 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;

public class TestInetAddress {

	public static void main(String[] args) throws Exception {
		InetAddress local = InetAddress.getLocalHost();//获取本地主机
		
		//获取本地主机的IP、名字
		String ip = local.getHostAddress();
		String name = local.getHostName();
//		System.out.println(ip+"\t"+name);
		
		//获取任意主机的IP地址对象  (IP、主机名)
//		InetAddress local2 = InetAddress.getByName("www.baidu.com");
//		System.out.println(local2.getHostAddress());
//		System.out.println(local2.getHostName());
		
		InetAddress[] addres = InetAddress.getAllByName("www.baidu.com");
		
		for(InetAddress add: addres) {
			System.out.println(add.getHostAddress());
		}
		
	}

}

输出结果:

39.156.66.14
39.156.66.18

16.5.2 基于TCP的网络编程

Socket编程:

  • Socket(套接字)是网络中的一个通信节点;
  • 分为客户端Socket与服务器ServerSocket;
  • 通信要求:IP地址+端口号;
import java.io.*;
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);
		System.out.println("服务器已启动");
		
		//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.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;


public class Client {

	public static void main(String[] args) throws Exception {
		//1.创建客户端,连接指定的IP+端口号
		Socket client = new Socket("192.168.31.59",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.关闭
		br.close();
		pw.close();
	}

}

输出结果:

服务器已启动
客户端:我是客户端
服务端说:我是服务端,你好

16.5.3 开发步骤

  1. 建立通信连接(会话):
    创建ServerSocket,指定端口号;
    调用accept等待客户端接入;
  2. 客户端请求服务器:
    创建Socket,指定服务器IP+端口号;
    使用输出流,发送请求数据给服务器;
    使用输入流,接收响应数据到客户端(等待);
  3. 服务器响应客户端:
    使用输入流,接收请求数据到服务器(等待)
    使用输出流,发送响应数据给客户端;
import java.net.ServerSocket;
import java.net.Socket;

/*
 * 服务器,接收多个客户端请求
 * 主线程,接收请求
 * 子线程,复制接收数据
 * */
public class Server {

	public static void main(String[] args) throws Exception {
		ServerSocket server =new ServerSocket(8888);
		System.out.println("服务器已启动");

		while(true) {
			Socket client = server.accept();
			DataThread dt = new DataThread(client);
			dt.start();
		}
	}

}
import java.io.*;
import java.net.Socket;
import java.util.Scanner;

public class DataThread extends Thread {

	private Socket client;
	public DataThread(Socket client) {
		this.client = client;
	}
	Scanner input = new Scanner(System.in);
	public void run() {
		//接收数据
		try {
			InputStream is = client.getInputStream();
			BufferedReader br = new BufferedReader( new InputStreamReader(is , "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);
				
				System.out.println("请输入回复:");
				String callmsg = input.next();
				pw.println(callmsg);
				pw.flush();
				
				if(msg.equals("byebye") || msg.equals("886")) {
					System.out.println(client.getInetAddress().getHostName()+"退出了聊天");
					break;
				}
			}
			br.close();
			pw.close();
		} catch (IOException e) {
			System.err.println(client.getInetAddress().getHostName()+"死机了");
			e.printStackTrace();
		}
	}

}
import java.io.*;
import java.net.Socket;
import java.util.Scanner;


public class Client {

	public static void main(String[] args) throws Exception {
		Socket client = new Socket("192.168.31.59",8888);
		
		OutputStream os = client.getOutputStream();
		PrintWriter pw = new PrintWriter(new OutputStreamWriter(os , "UTF-8"));
	
		BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream(),"UTF-8"));
		
		Scanner input = new Scanner(System.in);
		while(true) {
			System.out.println("请输入:");
			String msg = input.next();
			pw.println(msg);
			pw.flush();
			
			String callmsg  = br.readLine();
			System.out.println("服务端回复:"+callmsg);
			
			if(msg.equals("byebye") || msg.equals("886")){
				break;
			}
		}
		pw.close();
		client.close();
		System.out.println("您退出了");
	}

}

输出结果:

服务器已启动
DESKTOP-JFO9FHB说:你好
请输入回复:
hi
DESKTOP-JFO9FHB说:byebye
请输入回复:
886
DESKTOP-JFO9FHB退出了聊天
请输入:
你好
服务端回复:hi
请输入:
byebye
服务端回复:886
您退出了

16.5.4 课堂案例

  • 使用Socket编程实现服务器端注册:
    注册信息保存在properties文件中;
    注册成功后返回字符串“注册成功”;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;

/*
 * 服务端
 * 提供注册
 * 接收客户端发送的数据zhangsan#123
 * 保存在properties文件中
 * */
public class Server {
	private Properties userPros;//Map体系下的,Key和value都是String
	
	public Server() {
		userPros = new Properties();
		File file = new File("Files/userPros.properties");
		if(file.exists()) {//文件存在
			
			try{
				//把properties文件里的内容加载到properties集合里
				userPros.load(new FileReader(file));
			}catch(Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	public void registerUser() {
	
		try {
			//1.创建服务端
			ServerSocket server = new ServerSocket(7777);
			System.out.println("服务端已启动");
			
			//2.接收客户端
			Socket client = server.accept();
			
			
			//3.输入流输出流
			BufferedReader br  = new BufferedReader(new InputStreamReader( client.getInputStream() , "UTF-8"));
			PrintWriter pw = new PrintWriter(new OutputStreamWriter(client.getOutputStream(), "UTF-8"));
			
			
			//4.接收数据  zhangsan#123
			String user = br.readLine();
			String[] users = user.split("#");
			String username = users[0];
			String password = users[1];
			
			//对用户名进行判断
			if(userPros.containsKey(username)) {
				pw.println("用户已存在,请重新注册!");
				pw.flush();
			}else {
				//不存在,先存在userPros集合里,再存入文件
				userPros.setProperty(username, password);
				//将集合加载到文件中
				userPros.store(new FileWriter("Files/userPros.properties"), "用户信息");
				pw.println("注册成功");
				pw.flush();
			}
			pw.close();
			br.close();
			client.close();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
}
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class Client {

	public static void main(String[] args) throws Exception {
		//1.创建客户端
		Socket client = new Socket("192.168.31.59",7777);
		System.out.println("开始注册。。。");
		Scanner input = new Scanner(System.in);
		System.out.println("请输入用户名:");
		String username = input.next();
		System.out.println("请输入密码:");
		String password = input.next();
		
		String userinfo = username +"#"+password;
		
		//2.获得流
		BufferedReader br  = new BufferedReader(new InputStreamReader( client.getInputStream() , "UTF-8"));
		PrintWriter pw = new PrintWriter(new OutputStreamWriter(client.getOutputStream(), "UTF-8"));
		
		//3.提交用户信息
		pw.println(userinfo);
		pw.flush();
		
		//4.接收服务端的结果
		String msg = br.readLine();
		System.out.println(msg);
		
		br.close();
		pw.close();
	}

}
public class Start {

	public static void main(String[] args) {
		
		Server server = new Server();
		server.registerUser();
	}

}

userPros.properties文件内容:

#\u7528\u6237\u4FE1\u606F
#Wed Mar 18 17:07:42 CST 2020
zhangsan=123

输出结果:

开始注册。。。
请输入用户名:
zhangsan
请输入密码:
123
用户已存在,请重新注册!

第二次注册:

开始注册。。。
请输入用户名:
lisi
请输入密码:
123
注册成功

注册成功后文件内容:

#\u7528\u6237\u4FE1\u606F
#Wed Mar 18 22:22:19 CST 2020
zhangsan=123
lisi=123

16.6 总结
计算机网络:
为实现资源共享和信息传递,通过通信线路连接起来的若干主机;
TCP协议:
是一种面向连接的、可靠的、基于字节流的传输层通信协议。数据大小无限制;
IP:
分配给互联网设备的数字标签(唯一标识);
Port:
在通信实体上进行网络通讯的程序的唯一标识;
Socket编程:
建立连接、接收请求、发送响应;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值