java入门基础十四(网络编程)

19 网络编程

19.1 计算机网络

计算机网络:指将地理不同的具有独立功能的多台计算机及外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。

19.2 网络编程

实现多台计算机之间实现数据的共享和传递。

网络应用程序主要组成为: 网络编程+IO流+多线程

19.3 网络模型

在这里插入图片描述

19.4 网络编程三要素

网络通讯的模型:请求-响应,客户端-服务端

三要素:IP地址,端口,协议(数据传输的规则)

19.4.1 IP地址

含义:

网络中计算机的唯一标识(IP地址是一个32位的二进制数据,为了方便,将一个字节的二进制转换为一个十进制的数据)

组成:

网络号段+主机段

分类:

A类IP地址:第一段号码为网络号码,剩下的三段号码为本地计算机的号码

----可以配置256* 256* 256台主机

B类IP地址:前二段号码为网络号码,剩下的二段号码为本地计算机的号码

C类地址前三段号码为网络号码,剩下的一段号码为本地计算机的号码

拓展:

A类地址的表示范围为:0.0.0.0~126.255.255.255,默认网络屏蔽为:255.0.0.0;A类地址分配给规模特别大的网络使用。A类网络用第一组数字表示网络本身的地址,后面三组数字作为连接于网络上的主机的地址。分配给具有大量主机(直接个人用户)而局域网络个数较少的大型网络。例如IBM公司的网络。

B类地址的表示范围为:128.0.0.0~191.255.255.255,默认网络屏蔽为:255.255.0.0;

C类地址的表示范围为:,默认网络屏蔽为:;类地址分配给小型网络,如一般的局域网和校园网,它可连接的主机数量是最少的,采用把所属的用户分为若干的网段进行管理。

特殊地址:

127.0.0.1 回环地址,可用于测试本机的网络是否有问题( ping 127.0.0.1 )

查看本机IP( DOS命令 ipconfig )

xxx.xxx.xxx.255 广播地址

示例:获取本机的ip

//获取本机ip地址
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(localHost);

示例:获取百度首页的ip

//获取百度首页服务器的ip地址
InetAddress byName = InetAddress.getByName("www.baidu.com");
System.out.println(byName);
//www.baidu.com/14.215.177.39

//获取百度首页服务器的所有ip
InetAddress[] allByName = InetAddress.getAllByName("www.baidu.com");
for (InetAddress inetAddress : allByName) {
    System.out.println(inetAddress);
}
/*
www.baidu.com/14.215.177.39
www.baidu.com/14.215.177.38
*/

注:一个域名可以对应多个地址,但一个ip只能对应一个域名。

19.4.2 端口号

  1. A:每个网络程序都会至少有一个逻辑端口

  2. B:用于标识进程的逻辑地址,不同进程的标识不同

  3. C:有效端口:065535,其中01024系统使用或保留端口。

a) 80

b) ftp:23

c) www.baidu.com:80

通过第三方工具可以查看

注:端口与协议有关:TCP和UDP的端口互不相干,同一个协议的端口不能重复,不同协议的可以重复

19.4.3 协议

通信规则,就是数据的传输规则

TCP、UDP都是传输层的协议

TCP

​ 建立连接,形成传输数据的通道;在连接中进行大数据量传输;通过三次握手完成连接,是可靠协议;必须建立连接,效率会稍低,例如:打电话

UDP

​ 将数据源和目的封装到数据包中,不需要建立连接;每个数据报的大小在限制在64k;因无连接,是不可靠协议;不需要建立连接,速度快:例如发短信

在这里插入图片描述

19.5 InetAddress类

含义:用来表示主机的信息

getLocalHost(); —获取本地主机ip

getByName(); — 在给定主机名的情况下确定主机的 IP 地址。

getAllByName(); —在给定主机名的情况下确定主机所有的 IP 地址。

示例见:19.4.1

19.6 Socket

含义:套接字,表示的是ip地址和端口号的组合。

网络编程主要就是指Socket编程,网络之间的通信其实就是Socket间的通信,数据就通过IO流在两个Socket间进行传递。

19.7 TCP编程

Socket(客户端的套接字),ServerSocket(服务端的套接字)

客户端(发送一个请求) 服务端(接收到这个请求,给予响应)

19.7.1 示例

示例1:一对一聊天-----客户端和服务端(多线程)

客户端和服务端接收信息的线程类:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

public class ReceiveThread extends Thread{

	private Socket socket;
	
	public ReceiveThread(Socket socket) {
		this.socket = socket;
	}

	@Override
	public void run() {
		BufferedReader br = null;
		try {
			br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		} catch (IOException e) {
			e.printStackTrace();
		}
		while(true){
			try {
				System.out.println(br.readLine());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

客户端:

import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class Client {
	@SuppressWarnings("all")
	public static void main(String[] args) throws UnknownHostException, IOException {
		
		Socket socket = new Socket("127.0.0.1",8080);
		Scanner scan = new Scanner(System.in);
		new ReceiveThread(socket).start();
		//发送给服务端信息
		while(true ){
			PrintStream ps = new PrintStream(socket.getOutputStream());
			ps.println("客户端:"+scan.next());		
		}
	}
}

服务端:

import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class Server {

	@SuppressWarnings("all")
	public static void main(String[] args) throws IOException, InterruptedException {

		//创建服务端的ServerSocket
		ServerSocket server = new ServerSocket(8080);
		Scanner scan = new Scanner(System.in);
		Socket socket = server.accept();
		new ReceiveThread(socket).start();
		while(true){
			//发送给客户端信息
			PrintStream ps = new PrintStream(socket.getOutputStream());
			ps.println("服务端:"+scan.next());
		}
	}
}
示例2:客户端连接服务端,从服务端下载文件

注:示例下载视频文件(.mp4)采用带缓冲区的字节流传输。

服务端:

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;


public class Server {

	@SuppressWarnings("all")
	public static void main(String[] args) throws IOException, InterruptedException {

		//创建服务端的ServerSocket
		ServerSocket server = new ServerSocket(8080);
		
		Socket socket = server.accept();

		OutputStream os = socket.getOutputStream();
		
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream("111.mp4"));
		
		byte [] bs =new byte[1024];
		int len;
		while((len=bis.read(bs))!=-1){
			os.write(bs, 0, len);
		}
		os.close();
		bis.close();
	}
}

客户端:

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.io.InputStream;

public class Client {
	@SuppressWarnings("all")
	public static void main(String[] args) throws UnknownHostException, IOException {

		Socket socket = new Socket("127.0.0.1",8080);

		InputStream is = socket.getInputStream();
		
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("download.mp4"));
		
		byte [] bs =new byte[1024];
		int len;
		while((len=is.read(bs))!=-1){
			bos.write(bs, 0, len);
		}
		is.close();
		bos.close();		
	}
}

19.7.2 拓展示例

服务器平台上的多客户聊天

19.7.3 TCP的交互(三次握手和四次挥手)

三次握手成功,建立联系,开始传输数据
在这里插入图片描述

四次挥手成功,数据传输结束,双方断开
在这里插入图片描述

19.8 UDP编程

19.8.1 简介

​ UDP(User Datagram Protocol)用户数据报包协议,UDP和TCP位于同一层-传输层,但它对于数据包的顺序错误或重发没有TCP可靠;UDP是一种面向无连接的通信协议。UDP向应用程序提供一种发送封装的原始IP数据包的方法,并且发送时无需建立连接,不保证可靠数据的传输 。

19.8.2 使用示例

示例1:简单通信

客户端1

public class Client_1 {

	public static void main(String[] args) throws IOException {
		/**
		 * udp协议
		 */
		DatagramSocket socket = new DatagramSocket();
		byte [] bs="Hello~~哈喽".getBytes();
		
        //创建发送数据的数据包。
        //包中有:发送的数据、数据的长度、接受数据的主机ip地址、端口号
		DatagramPacket packet = new DatagramPacket(bs, bs.length, InetAddress.getByName("127.0.0.1"), 8080);
		
        //使用socket发送数据包
		socket.send(packet);
		
        //创建存放接收数据的容器
		byte [] buf=new byte[1024];
        //设置接收数据的数据包
		packet = new DatagramPacket(buf, buf.length);
        //使用socket接收数据
		socket.receive(packet);
		System.out.println(new String(buf).trim());
		//关闭资源
		socket.close();
		
	}
}

客户端2

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class Client_2 {

	public static void main(String[] args) throws IOException {
		DatagramSocket socket = new DatagramSocket(8080);
		//接收数据的容器
		byte [] bs =new byte[1024];
        //设置数据包
		DatagramPacket packet = new DatagramPacket(bs, bs.length);
        //使用套接字接收数据包
		socket.receive(packet);
		System.out.println(new String(bs).trim());
		
        //发送数据
		byte [] buf ="你好!".getBytes();
		packet = new DatagramPacket(buf, buf.length,packet.getSocketAddress());
		socket.send(packet);
		
        //关闭资源
		socket.close();
	}
}

注:

  1. UDP协议中收发数据使用 receive/send方法。
  2. 数据包收发数据都是使用字符数组。
  3. UDP允许数据收发时遗失。
示例2:使用UDP协议进行一对一聊天(多线程)

用来接收数据的线程:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class ReceiveThread extends Thread{
	private DatagramSocket socket;
	
	public ReceiveThread(DatagramSocket socket) {
		this.socket = socket;
	}
	@Override
	public void run() {
		byte [] buf=new byte[1024];
		
		System.out.println(new String(buf).trim());
		while (true){
			try {
				DatagramPacket packet = new DatagramPacket(buf, buf.length);
				socket.receive(packet);
				System.out.println(new String(buf).trim());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

用来发送数据的线程:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;

public class SendThread extends Thread{

	private DatagramSocket socket;
	private String ip;
	private String name;
	private int port;
	
	public SendThread(DatagramSocket socket, String ip, String name, int port) {
		this.socket = socket;
		this.ip = ip;
		this.name = name;
		this.port = port;
	}
	
	@SuppressWarnings("all")
	@Override
	public void run() {
		Scanner scan =new Scanner(System.in);
		byte[] bs =null;
		
		while (true){
			bs=(name+":"+scan.next()).getBytes();
			try {
				DatagramPacket packet = new DatagramPacket(bs, bs.length,InetAddress.getByName(ip), port);
				socket.send(packet);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

客户端1:

public class Client_1 {

	public static void main(String[] args) throws IOException {
		/**
		 * udp协议
		 */
		DatagramSocket socket = new DatagramSocket(7070);
        //开启发送数据的线程
		new SendThread(socket, "127.0.0.1", "小明", 8080).start();
        //开启接收数据的线程
		new ReceiveThread(socket).start();		
	}
}

客户端2:

public class Client_2 {

	public static void main(String[] args) throws IOException {
		DatagramSocket socket = new DatagramSocket(8080);
        //开启发送数据的线程
		new SendThread(socket, "127.0.0.1", "小红", 7070).start();
        //开启接收数据的线程
        new ReceiveThread(socket).start();
	}
}

19.9 TCP和UDP的比较

比较表:

TCPUDP
是否连接面向连接无面向连接
传输可靠性可靠不可靠
应用场合传输大量数据少量数据
速度

19.20 HttpURLConnection(了解Resquest及Response)

简单示例介绍:(下载网络图片)

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;

public class Test_2 {
	public static void main(String[] args) throws IOException {
		
		
		//网络接口
		String urlStr = "https://p0.ssl.qhimgs1.com/sdr/400__/t018b0c452a789b9b2a.jpg" ;
		//创建网络连接对象
		URL url = new URL(urlStr);
		
		//获取HttpURLConnection对象
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		
		//设置
		conn.setRequestMethod("GET");//请求方式
		conn.setConnectTimeout(5000);//连接超时时间
		conn.setReadTimeout(5000);//读取超时时间
		
		//获取响应状态码
		int responseCode = conn.getResponseCode();
		
		if(responseCode==200){
			BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
			BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("cop.jpg"));
			byte [] cs =new byte[1024];
			int len;
			while((len=bis.read(cs))!=-1){
				bos.write(cs, 0, len);
			}
			bos.close();
		}else if(responseCode==404){
			System.out.println("访问对象不存在");
		}
	}
}
;//请求方式
		conn.setConnectTimeout(5000);//连接超时时间
		conn.setReadTimeout(5000);//读取超时时间
		
		//获取响应状态码
		int responseCode = conn.getResponseCode();
		
		if(responseCode==200){
			BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
			BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("cop.jpg"));
			byte [] cs =new byte[1024];
			int len;
			while((len=bis.read(cs))!=-1){
				bos.write(cs, 0, len);
			}
			bos.close();
		}else if(responseCode==404){
			System.out.println("访问对象不存在");
		}
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值