javase day22

在这里插入图片描述
网络编程(套接字)
通过Java程序实现网络之间的数据传输 底层基于网络来传输的流
网络模型

ip地址
确定在网络中的位置 IPv4 由四位0-255之间的数组成的 10.34.8.10 IPv6
端口
计算机和外部进行数据交互的媒介—端口号(0-65535)
0-1024这些端口号大部分已经被系统占用,自己使用端口号的时候就从1025往后找

www.baidu.com 域名
在这里插入图片描述
通过DNS可以映射到对应的IP

SocketAddress 代表IP地址的类

package cn.tedu.inernet;

import java.net.InetSocketAddress;

/**
*@author 作者:
*@version 创建时间:2020年11月22日下午8:33:39
*@description 描述:
*/
public class InetSocketAddressDemo {
	public static void main(String[] args) {
		//表示IP和端口的对象
		//127.0.0.1这个IP一直指向本地
		//localhost和127.0.0.1互相映射
		//InetSocketAddress isa=new InetSocketAddress("www.baidu.com", 8090);
		//InetSocketAddress isa=new InetSocketAddress("192.168.199.140", 8090);
		//InetSocketAddress isa=new InetSocketAddress("127.0.0.1", 8090);
		InetSocketAddress isa=new InetSocketAddress("localhost", 8090);
		//获取IP地址
		System.out.println(isa.getAddress());
		//获取主机名
		System.out.println(isa.getHostName());
		//获取端口号
		System.out.println(isa.getPort());
	}
}

UDP 底层基于流,不会建立连接,不可靠,但是传输速度快
底层是经过数据包来进行数据的传输,数据包大小一般不能超过64kb
适用场景:视频聊天等–DatagramSocket、DatagramPacket

package cn.tedu.inernet.udp;

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

/**
*@author 作者:
*@version 创建时间:2020年11月22日下午10:21:51
*@description 描述:发送端
*/
public class UDPSenderDemo {
	public static void main(String[] args) throws IOException {
		//创建套接字对象
		DatagramSocket ds=new DatagramSocket();
		//创建待传输数据包
		//第一个参数要传输数据的字节数组
		//第二个参数真正要发送数据的长度(最大和数组长度一致)
		//第三个参数指明要传输的IP地址和端口号
		DatagramPacket dp=new DatagramPacket("你好".getBytes(), "你好".getBytes().length, new InetSocketAddress("127.0.0.1", 8009));
		//发送数据包
		ds.send(dp);
		//关流---底层是字节流
		ds.close();
	}
}

package cn.tedu.inernet.udp;

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

/**
*@author 作者:
*@version 创建时间:2020年11月22日下午10:30:33
*@description 描述:接收端
*/
public class UDPReceiverDemo {
	public static void main(String[] args) throws IOException {
		//创建套接字对象--绑定端口号
		DatagramSocket ds=new DatagramSocket(8009);
		//创建数据包用来接受数据---第二个参数代表实际接受数据的长度
		DatagramPacket dp=new DatagramPacket(new byte[1024], 1024);
		//接受数据把数据存放到数据包
		//阻塞
		ds.receive(dp);
		//关流
		ds.close();
		//解析数据包
		//dp.getData()---获取数据
		//dp.getLength()---获取长度
		System.out.println(new String(dp.getData(),0,dp.getLength()));
		//获取IP地址和端口号
		System.out.println(dp.getAddress());
		System.out.println(dp.getPort());
	}
}

发送端
1、创建套接字对象
2、创建需要发送的数据包(指定要发送的数据的长度以及IP地址和端口号)
3、发送数据包
4、关流
接收端
1、创建套接字对象(绑定具体的端口号)
2、创建需要接受的数据包(指定真实接受数据的长度)
3、接收数据包
4、关流
5、解析数据包

案例:
1、通过UDP来实现简易的聊天室(线程)

package cn.tedu.inernet.udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.util.Scanner;

/**
*@author 作者:
*@version 创建时间:2020年11月22日下午11:08:14
*@description 描述:简易的聊天(线程)
*/
public class UDPChatDemo {
	public static void main(String[] args) {
		//开启线程
		new Thread(new Sender()).start();
		new Thread(new Receiver()).start();
	}
}
//发送端--线程
class Sender implements Runnable{
	//声明对象
	DatagramSocket ds;
	Scanner sc;
	@Override
	public void run() {
		// TODO Auto-generated method stub
	//对象的初始化
		try {
			ds=new DatagramSocket();
			sc=new Scanner(System.in);
			while(true) {//保证一直写数据发送数据
				//录入信息
				byte[] bs=sc.nextLine().getBytes();
				//创建发送的数据包
				DatagramPacket dp=new DatagramPacket(bs, bs.length,new InetSocketAddress("127.0.0.1", 8090));
				//发送数据包
				ds.send(dp);
			}
			
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
//接收端
class Receiver implements Runnable{
	//声明对象
	DatagramSocket ds;
	DatagramPacket dp;
	@Override
	public void run() {
		// TODO Auto-generated method stub
		//对象初始化
		try {
			ds=new DatagramSocket(8090);
			dp=new DatagramPacket(new byte[1024], 1024);
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		while(true) {
			//接受数据包
			try {
				ds.receive(dp);
				//解析数据包
				System.out.println(new String(dp.getData(),0,dp.getLength()));
				System.out.println(dp.getAddress());
				System.out.println();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

TCP三次握手
在这里插入图片描述
TCP
底层基于流,建立链接,可靠,传输速度慢
TCP通过字节流直接传输数据不需要数据包,就没有传输数据的限制
适用场景:传输文件,下载电影等

客户端
1、建立TCP客户端对象
2、发起链接(指明要发送的ip和端口)
3、获取自带的字节输出流
4、根据自带的字节输出流往服务端写出数据
5、通知服务器已经写完、关流

服务器端
1、创建TCP服务器端对象
2、接受链接
3、获取自带的字节流
4、通过自带的字节进行数据读取
5、通知客户端已经读取完、关流

package cn.tedu.inernet.tcp;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;

/**
*@author 作者:
*@version 创建时间:2020年11月27日下午2:22:21
*@description 描述:客户端
*/
public class TCPClientDemo {
	public static void main(String[] args) throws IOException {
		//创建TCP的套接字
		Socket s=new Socket();
		//发起链接----指定链接的IP和端口
		//阻塞---服务器不接受链接阻塞报错
		s.connect(new InetSocketAddress("127.0.0.1", 8010));
		/*//证明写有无阻塞
		OutputStream os=s.getOutputStream();
		for (int i = 0; i < 1000000000; i++) {
			os.write("abc".getBytes());
			System.out.println(i);//没有全输完说明写也有阻塞
		}*/
		//while(true);
		//获取自带的字节输出流
		//写出的数据默认往服务器里边写
		OutputStream os=s.getOutputStream();
		//通过自带的字节输出流写数据
		os.write("服务器你好...".getBytes());
		//通知服务器数据已写完
		s.shutdownOutput();
		
		//获取自带的字节输入流
		InputStream in=s.getInputStream();
		//读取数据
		byte[] bs=new byte[1024];
		int len=-1;
		while((len=in.read(bs))!=-1) {
			System.out.println(new String(bs,0,len));
		}
		//通知服务器端数据已读完
		s.shutdownInput();
		//关流
		os.close();
		in.close();
		
	}
}

package cn.tedu.inernet.tcp;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
*@author 作者:
*@version 创建时间:2020年11月27日下午2:32:00
*@description 描述:服务器
*/
public class TCPServerDemo {
	public static void main(String[] args) throws IOException {
		//创建tcp服务器端对象----绑定端口
		ServerSocket ss=new ServerSocket(8010);
		//接受链接
		//阻塞
		Socket s=ss.accept();
		//while(true);
		//System.out.println(1);//光运行服务器没有输出1说明接受阻塞;运行完服务运行客户机输出1说明服务器读取阻塞
		//读取传过来的数据
		//获取自带的输入流
		InputStream in=s.getInputStream();
		//自建缓冲区
		byte[] bs=new byte[1024];
		int len=-1;
		while((len=in.read(bs))!=-1) {//读取有阻塞
			System.out.println(new String(bs,0,len));
		}
		//通知客户端数据已读完
		s.shutdownInput();
		
		//获取自带的字节输出流
		OutputStream os=s.getOutputStream();
		//往客户端写数据
		os.write("你也好".getBytes());
		//通知客户端数据已经写完
		s.shutdownOutput();
		//关流
		os.close();
		//关流
		in.close();
	}
}

receive、connect、accept、write、read都有阻塞存在

TCP实现文件的复制
在这里插入图片描述
在这里插入图片描述

package cn.tedu.inernet.tcp;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;

/**
*@author 作者:
*@version 创建时间:2020年11月27日下午4:54:00
*@description 描述:
*/
public class TCPFileCopyClient {
	public static void main(String[] args) throws IOException {
		//创建TCP客户端对象
		Socket s=new Socket();
		//发起链接
		s.connect(new InetSocketAddress("127.0.0.1", 9009));
		//创建文件类对象
		File file=new File("D:\\a\\1.mp4");
		//把外部文件读取进来
		FileInputStream fis=new FileInputStream(file);
		//获取自带的输出流
		OutputStream os=s.getOutputStream();
		//获取文件的名称,长度
		//先传文件的长度
		//os.write(file.getName().length());
		os.write(file.getName().length()-128);
		//传文件的内容
		os.write(file.getName().getBytes());
		byte[] bs=new byte[1024*1024*10];
		int len=-1;
		while((len=fis.read(bs))!=-1){
			//往服务端写数据
			os.write(bs,0,len);
		}
		//通知服务端已写完
		s.shutdownOutput();
		//关流
		fis.close();
		os.close();
	}
}

package cn.tedu.inernet.tcp;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
*@author 作者:
*@version 创建时间:2020年11月27日下午4:54:24
*@description 描述:
*/
public class TCPFileCopyServer {
	public static void main(String[] args) throws IOException {
		//获取TCP服务端的对象
		ServerSocket ss=new ServerSocket(9009);
		Socket s=ss.accept();
		//获取自带的字节输入流读取客户端发来的数据
		InputStream is=s.getInputStream();
		//接受文件名长度值
		//int length=is.read();
		byte length=(byte)is.read();
		//新建字节数组
		//byte[] bts=new byte[length];
		byte[] bts=new byte[length+128];
		//按照这个字节数组读取文件名内容
		is.read(bts);//字节数组里存满了文件名内容
		//创建文件字节输出流
		//FileOutputStream fos=new FileOutputStream("D:\\a\\b\\"+new String(bts,0,length));//length为int
		FileOutputStream fos=new FileOutputStream("D:\\a\\b\\"+new String(bts));
		byte[] bs=new byte[1024*1024*10];
		int len=-1;
		while((len=is.read(bs))!=-1) {
			//往外部文件写数据
			fos.write(bs,0,len);
		}
		//通知客户端已经读取完毕
		s.shutdownInput();
		//关流
		fos.close();
		is.close();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值