欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java学习(18)-- 网络编程

程序员文章站 2022-07-12 08:11:28
...

java学习(18)

这篇来写关于网络编程的内容。

1.网络编程&& Udp

1.1 网络通信介绍

(1)tcp/ip协议

(2)udp/ip协议


1.2 Socket通信

网络编程三要素:

(1)ip:一个计算的标示(找到这个计算机)

(2)端口:应用程序都会对应一个端口,用来进行通信,有效端口:0~65535,其中0~1024系统使用或保留端口(360查看端口)。

(3)协议:总共有2种协议:TCP、UDP


1.3 三要素详解:

(1)特殊的IP地址:

127.0.0.1本地回环地址用来做一些本地测试

pingIP地址用来检测本机是否可以和指定的IP地址的计算机可以进行正常通讯

java学习(18)-- 网络编程

ipconfig用来查看IP地址

xxx.xxx.xxx.255 :广播地址


(2)端口号

物理端口:物理设备对应的端口网卡口

逻辑端口用来标示我们的计算机上的进程 , 端口号的有效范围应该是 0-65535其中0-1024被系统占用或者保留


(3)协议:

UDP协议:

A.把数据打成一个数据包 , 不需要建立连接

B.数据包的大小有限制不能超过64k

C.因为无连接,所以属于不可靠协议(可能丢失数据)

D.因为无连接 ,所以效率高

TCP协议:

A.需要建立连接,形成连接通道

B.数据可以使用连接通道直接进行传输,无大小限制

C.因为有链接,所以属于可靠协议

D.因为有链接,所以效率低


1.4 InetAddress:IP地址的描述类

A:InetAddress类的概述

为了方便我们对IP地址的获取和操作,java提供了一个类InetAddress 供我们使用此类表示互联网协议 (IP) 地址。 

B:InetAddress类的常见功能

public static InetAddress getByName(String host)( host: 可以是主机名,也可以是IP地址的字符串表现形式)

public String getHostAddress()返回 IP 地址字符串(以文本表现形式)。

public String getHostName()获取此 IP 地址的主机名。 

示例:

public static void main(String[] args) throws Exception {
		InetAddress address = InetAddress.getByName("10.100.9.174");
		System.out.println(address.getHostAddress());
		System.out.println(address.getHostName());
	}
java学习(18)-- 网络编程

1.5 socket编程(套接字编程,网络编程

Socket套接字:网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。


Socket原理机制:

(1)通信的两端都有Socket。

(2)网络通信其实就是Socket间的通信。

(3)数据在两个Socket间通过IO传输。


1.6 UDP协议

特点:

(1)把数据打包

(2)不需要建立连接,也称为面向无连接协议

(3)数据需打包,数据大小有限制64k

(4)无需建立连接,所以不可靠

(5)速度快


UDP通信步骤:

发送端步骤:

UDP发送数据的步骤:

A:创建UDP发送数据端Socket对象

B:创建数据包,并给出数据,把数据打包

C:通过Socket对象发送数据包 

D:释放资源

示例:

public static void main(String[] args) throws Exception {
		
		//1.创建发送端Socket对象
		DatagramSocket ds = new DatagramSocket();
		
		String str = "hello,world";
		byte[] buf = str.getBytes();
		int length = buf.length;
		InetAddress address = InetAddress.getByName("127.0.0.1");
		int port = 6666;
		
		//2.创建数据包
		DatagramPacket dp = new DatagramPacket(buf,length,address,port);
		
		//3.发送数据
		ds.send(dp);
		
		//4.释放资源
		ds.close();
	}

接收端步骤:

UDP协议接收数据步骤:

A:创建UDP接收数据端Socket对象

B:创建一个接收数据的数据包

C:接收数据,数据在数据包中

D:解析数据包,并把数据显示在控制台

E:释放资源

示例:

public static void main(String[] args) throws Exception {
		//1.创建接收端socket对象
		DatagramSocket ds = new DatagramSocket(6666);
		
		//2.创建数据包
		byte[] buf = new byte[1024];
		int length = buf.length;
		DatagramPacket dp = new DatagramPacket(buf, length);
		
		//3.接受数据
		ds.receive(dp);
		byte[] data = dp.getData();
		int len = dp.getLength();
		System.out.println(new String(data, 0, len));
		
		//4.释放资源
		ds.close();
	}
运行:

java学习(18)-- 网络编程

1.7案例:键盘录入数据实现数据的动态发送

发送端:

public class UdpClient {

	public static void main(String[] args) throws Exception {
		
		//创建发送端socket对象
		DatagramSocket ds = new DatagramSocket();
		
		InetAddress address = InetAddress.getByName("127.0.0.1");
		int port = 7777;
		
		Scanner sc = new Scanner(System.in);
		String line;
		System.out.println("请输入聊天内容:");
		while((line = sc.nextLine())!=null){
			System.out.println("请输入聊天内容:");
			byte[] buf = line.getBytes();
			int length = buf.length;
			DatagramPacket dp = new DatagramPacket(buf, length, address, port);
			
			//发送信息
			ds.send(dp);
		}
		
		//释放资源
		ds.close();
	}
}
接收端:

public class UdpServer {

	public static void main(String[] args) throws Exception {
		//创建接收端socket对象
		DatagramSocket ds = new DatagramSocket(7777);
	
		while(true){
			byte[] buf = new byte[1024];
			int length = buf.length;
			DatagramPacket dp = new DatagramPacket(buf, length);
			ds.receive(dp);
			byte[] data = dp.getData();
			int len = dp.getLength();
			System.out.println("客户端:"+new String(data,0,len));
		}
		
	}
}
运行:

java学习(18)-- 网络编程java学习(18)-- 网络编程

2.TCP协

2.1 TCP协议

特点:

1.需要建立通道

2.传送大量数据无限制

3.面向连接

4.可靠

5.速度慢


TCp协议书写步骤:

发送端:

TCP协议发送数据步骤:

A:创建TCP协议发送端Socket对象

指定服务器IP及端口

B:获取输出流,并写数据

C:释放资源

示例:

public static void main(String[] args) throws Exception {
		//创建socket对象
		Socket socket = new Socket("127.0.0.1",20000);
		
		//获取输出流
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
		
		//获取键盘输入
		System.out.println("请输入聊天内容:");
		Scanner sc = new Scanner(System.in);
		String line = sc.nextLine();
		
		//写到流中
		bw.write(line);
		bw.flush();
		
		//释放资源
		socket.close();
		
	}

注意:TCP协议是不能直接运行客户端的,必须先运行服务器。因为他是一种可靠的协议。直接运行客户端会报错:

java学习(18)-- 网络编程

接收端:

TCP协议接收数据步骤:

A:创建TCP协议接收端Socket对象

B:监听客户端连接

C:获取输入流,并读取数据,显示在控制台

D:释放资源

示例:

public static void main(String[] args) throws Exception {
		//创建socket对象
		ServerSocket serverSocket = new ServerSocket(20000);
		
		//监听
		Socket socket = serverSocket.accept();
		
		//获取通道输入流
		BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		
		//读数据
		String line = br.readLine();
		
		System.out.println("客户端:"+line);
		
		//释放资源
		socket.close();
		
	}


2.2 案例:客户端键盘录入数据,服务器端接收数据在控制台输出

上述Tcp代码运行即可:

java学习(18)-- 网络编程java学习(18)-- 网络编程


2.3 案例:上传文本文件

客户端:

a: 读取文本文件中的数据

b: 发送到服务器端

服务器:

a: 读取流通道中的数据

b: 把数据写入到文本文件中

分析:基于Tcp协议的文本文件上传

发送端:

public class TcpClient {

	public static void main(String[] args) throws Exception {
		//创建socket对象
		Socket socket = new Socket("127.0.0.1",20000);
		
		//封装流
		BufferedReader br = new BufferedReader(new FileReader("a.txt"));
		String readLine;
		
		//获取输出流
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
		
		while(( readLine = br.readLine())!=null){	
			//写到流中
			bw.write(readLine);
			bw.newLine();
			bw.flush();		
		}
		
		//释放资源
		socket.close();
		
	}
}
接收端:

public class TcpServer {

	public static void main(String[] args) throws Exception {
		//创建socket对象
		ServerSocket serverSocket = new ServerSocket(20000);
		
		//监听
		Socket socket = serverSocket.accept();
		String line;
		
		//获取通道输入流
		BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		//写到文件 b.txt 中
		BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
		while((line = br.readLine())!=null){
			bw.write(line);
			bw.newLine();
			bw.flush();
		}
		
		//释放资源
		socket.close();
	}
}


2.4 基于多线程实现文本文件的上传

分析:对于上述代码,由于接收端把写入文件写死了,只能有一个发送端上传文件,并且每次都会把文件内容覆盖掉,因此,利用多线程改进,可以支持多个发送端上传文件,并且可以使用UUID类每次生成一个随机文件名,避免内容覆盖

改进:

发送端代码不用调整,改进接收端代码,以及添加一个线程类和利用UUID类来产生文件名字的类:

接收端:

public class TcpServer {

	public static void main(String[] args) throws Exception {
		//创建socket对象
		ServerSocket serverSocket = new ServerSocket(20000);
		
		while(true){
			//监听
			Socket socket = serverSocket.accept();
			new Thread(new ServerThread(socket)).start();
		}
	}
}
线程类:

public class ServerThread implements  Runnable{

	Socket socket;
	public ServerThread(Socket socket){
		this.socket = socket;
	}
	
	@Override
	public void run() {
		try {
			String line;
			//获取通道输入流
			BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			
			BufferedWriter bw = new BufferedWriter(new FileWriter(UUIDUtils.getFiledName()));
			while((line = br.readLine())!=null){
				bw.write(line);
				bw.newLine();
				bw.flush();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
	}

	
}
产生文件名类:

public class UUIDUtils {

	public static String getFiledName(){
		String fileName = UUID.randomUUID().toString();
		fileName = fileName.replace("-", "")+".txt";
		return fileName;
	}
}
这样,每次复制得到的文件名不同:

java学习(18)-- 网络编程


2.5 软件当中基本都是udp和tcp混用