Java基础-网络编程(十)
文章目录
- 一、网络编程概述
-
- 1.概念
- 2.目的
- 二、网络编程三要素
-
- 1.TCP/IP
-
- 1.1.IP地址
- 1.2.端口号
- 2.通信协议
- 3.TCP编程
- 4.UDP编程
- 5.URL
一、网络编程概述
1.概念
1、网络:计算机网络,由在不同地理位置、不同的计算机主机,互联形成的一个计算机系统。有通讯和数据共享的作用。
2、网络编程:在已经拥有完备成熟的网络系统之后,在整个基础上,使用网络进行编程,对应用层进行设计的活动。
2.目的
二、网络编程三要素
1、在网络编程中,必须要使用的三个基本的通信数据
2、IP地址、端口号、通信协议
(1)IP地址:网络中每一台计算机的唯一标识,通过IP地址找到指定的计算机。
(2)端口:用于标识进程的逻辑地址,通过端口找到指定进程。
(3)协议:定义通信规则,符合协议则可以通信,不符合不能通信。
1.TCP/IP
1.1.IP地址
1、在一个计算机网络中,某台计算机在网络中的唯一标志
2、分类:
(1)IPv4:192.168.2.84
使用4个0-255的数字,来表示一个ip地址,32位,2^32个地址,40亿四个字节中,可能有2个字节或者3个字节表示所在的子网剩余的部分是在子网中的IP号码
在一个子网中,使用一个字节表示,0-255 0表示子网的网号:192.168.2.0就表示当前的子网网号 255表示广播地址(在整个子网中的所有地址,都会接收到发送到广播地址的数据)特殊的IP地址:127.0.0.1,表示本地回环地址,表示当前正在运行这个程序的Ip相关的命令:ipconfig(查询当前网卡信息) ping(查看某个IP是否联通)
(2)IPv6:
由8组数字组成,每组数字都是4个16进制数(每个数字16种状态,32数字)
(3)127.0.0.1: 本机 localhost
TCP/IP 参考模型
总结:
- 网络编程中有两个主要的问题
如何准确的定位到网络上的一台或者多台主机
找到主机之后如何进行通信- 网络编程中的要素
IP和端口号 IP
网络通信协议 udp,tcp- 万物皆对象
/** * @author Daniel * 测试IP */public class TestIndress { public static void main(String[] args) { /** * 1、用于描述ip地址的对象所属的类型(主机名称、ip地址) * 2、获取方式: * getByName(String host): 根据主机名称获取当前类型对象 * getByAddress(byte[] arr):根据ip地址的字节数组获取当前类型对象 * getAllByName(String host):根据主机名称获取的所有当前类型对象的数组 * getLocalHost():获取当前主机的当前类型对象 * 3、对象的常用方法: * getHostName():获取主机名称 * getAddress():获取ip地址的字节数组 * toString():同时获取主机名称和ip地址的字符串表示 */ try { //查询本机地址 InetAddress inetAddress1 = InetAddress.getByName ( "127.0.0.1" ); System.out.println (inetAddress1); InetAddress inetAddress2 = InetAddress.getByName ( "localhost" ); System.out.println (inetAddress2); //查询网站ip地址 InetAddress inetAddress3 = InetAddress.getByName ( "www.baidu.com" ); System.out.println (inetAddress3); InetAddress localHost = InetAddress.getLocalHost ();//域名或自己电脑的名字 System.out.println (localHost); System.out.println ( inetAddress2.getAddress () );//IP System.out.println ( inetAddress2.getCanonicalHostName () );//规范的名字 System.out.println ( inetAddress2.getHostAddress () );//域名或自己电脑的名字 } catch (UnknownHostException e) { e.printStackTrace (); } }}
运行结果为:
1.2.端口号
1、也是一个数字,就是用于标记在电脑中的某个进程
2、使用两个字节来表示端口号:0-65535
也就是说,在计算机中,同时运行着的进程,最多只能有65536个
当程序运行时,需要有一个端口号,在程序运行结束之后,端口号被收回
3、在网络程序中,先在网络中通过ip地址,找到计算机,然后通过端口号找到对应的进程。
4、分配:在程序启动的时候,可以使用程序中指定的端口号,也可以随机分配
5、常用的端口号:
操作系统:0-1024之间
公有端口:0-1023
HTTP:80
HTTPS:443
FTP:21
MySQL:3306
Oracle:1521
Tomcat:8080
netstat -ano #查看所有的端口 netstat -ano | findstr "5900" #查看指定的端口 tasklist | findstr "8696" #查看指定端口的进程 如qq
快捷打开任务管理器 :Ctrl+Shift+Esc
/** * @author Daniel * InetSocketAddress */public class InetSockTest { public static void main(String[] args) { InetSocketAddress inetSocketAddress1 = new InetSocketAddress ( "127.0.0.1", 8080 ); System.out.println (inetSocketAddress1); InetSocketAddress inetSocketAddress2 = new InetSocketAddress ( "localhost",8080 ); System.out.println (inetSocketAddress2); System.out.println ( inetSocketAddress1.getPort () ); System.out.println ( inetSocketAddress1.getHostName () ); }}
运行结果为:
2.通信协议
TCP & UDP 对比
TCP:打电话
连接,稳定
三次握手 & 四次挥手
- 最少需要三次,保证稳定连接!
- A:你瞅啥?
- B:瞅你咋地?
- A:立新湖干一场!
- A:我要走了!
- B:我真的要走了吗?
- B:你真的真的要走了吗?
- A:我真的要走了!
UDP:发短信
不连接,不稳定
客户端、服务端:没有明确的界限
不管有没有准备号,都可以发给你……
如:导弹攻击
DDOS:洪水攻击!(饱和攻击)
3.TCP编程
1、使用的通信点就是Socket类型
2、客户端和服务端获取Socket对象的区别:
(1)客户端使用Socket的构造方法,创建一个Socket对象
(2)服务端不能使用自己创建的方式,而是使用服务端一个特殊的对象ServerSocket,接收客户端发来的请求,生成一个为这个客户端服务的Socket对象
3、构造方法:
Socket(InetAddress ip, int port):建立一个通信点,专门用于和ip主机的port程序进行通信。
只要这个对象创建成功了,就说明这个连接已经建立起来了,就说明当前的客户端已经联系上服务端了,已经获取了服务端返回的响应。
在创建对象的过程,就是在请求和服务端连接的过程。
4、服务端获取Socket对象的方式:
(1)启动一个服务程序,类型是ServerSocket,可以接收客户端发来的连接请求,一旦接收到请求,就可以创建一个和当前客户端交互的Socket对象
(2)ServerSocket的构造方法
ServerSocket(int port):创建一个服务端Socket对象,等待访问port端口的客户端
(3)accept():接收一个客户端发来的请求,返回一个服务此客户端的Socket对象
5、获取客户端和服务端的连接
(1)两个方法:
InputStream getInputStream():获取Socket对象的网络输入流
OutputStream getOutputStream():获取Socket对象的网络输出流
(2)一旦获取了输入输出流,就可以通过I\O的方式,来操作网络数据的传输。
(3)对应关系:
客户端的网络输入流,对应服务端的网络输出流
客户端的网络输出流,对应服务端的网络输入流
6、TCP编程步骤
客户端:
(1)创建Socket对象,建立和服务端的连接
(2)获取网络输入流和网络输出流
(3)通过I\O的操作来进行数据传输
服务端:
(1)创建ServerSocket对象,开启服务器,监听指定端口
(2)调用accept方法,接收客户端发来的请求,返回一个Socket对象
(3)获取服务端的网络输入流和网络输出流
(4)通过I\O的操作来进行输出传输
7、TCP编程加强:
(1)让客户端也接收数据,服务端也发送数据
(2)让字节流进行加强,转成字符流,加强成缓冲字符流
(3)让服务端多线程,同时可以处理多个用户的请求
TCP实现聊天
/** * @author Daniel * 服务端 */public class ServerTcpDemo { public static void main(String[] args) { ServerSocket socket = null; Socket accept = null; InputStream is = null; ByteArrayOutputStream bos = null; try { //1.我得有一个地址 socket = new ServerSocket ( 9999 ); while(true){ //2.等待客户端连接过来 accept = socket.accept (); //3.读取客户端信息 is = accept.getInputStream (); //管道流 bos = new ByteArrayOutputStream (); byte[] buffer = new byte[1024]; int len; while ((len = is.read (buffer))!= -1) {bos.write ( buffer, 0, len ); } System.out.println (bos.toString ()); } } catch (IOException e1) { e1.printStackTrace (); }finally { if(bos != null){ try {bos.close (); } catch (IOException e) {e.printStackTrace (); } } if(is != null){ try {is.close (); } catch (IOException e) {e.printStackTrace (); } } if(accept != null){ try {accept.close (); } catch (IOException e) {e.printStackTrace (); } } if(socket != null){ try {socket.close (); } catch (IOException e) {e.printStackTrace (); } } } }}
/** * @author Daniel * 客户端 */public class ClientTcpDemo { public static void main(String[] args) { InetAddress serverIp = null; Socket socket = null; OutputStream out = null; try { //1.要知道服务器的地址 端口 serverIp = InetAddress.getByName ( "127.0.0.1" ); int port = 9999; //创建一个socket连接 socket = new Socket (serverIp,port); out = socket.getOutputStream (); //发送socketIo流 out.write ( "欢迎来Daniel的博客学习".getBytes () ); } catch (Exception e) { e.printStackTrace (); }finally { if(out != null){ try { out.close (); } catch (IOException e) { e.printStackTrace (); } } if(socket != null){ try { socket.close (); } catch (IOException e) { e.printStackTrace (); } } } }}
运行结果显示(先开启服务端再开启客户端)
TCP实现传输文件
(1)先准备要传输的图片,如下(放根目录下):
(2)写客户端,服务端
/** * @author Daniel * 客户端 */public class FileTcpClientDaniel { public static void main(String[] args) throws Exception { //1.创建一个Socket连接 Socket socket = new Socket ( InetAddress.getByName ( "127.0.0.1" ), 2024 ); //2.创建一个输出流 OutputStream os = socket.getOutputStream (); //3.读取文件 FileInputStream fis = new FileInputStream ( new File ( "1.jpg" ) ); //4.写出文件 int len; byte[] bytes = new byte[1024]; while ((len = fis.read ( bytes ))!= -1){ os.write ( bytes,0,len ); } //通知服务器我已经结束了 socket.shutdownOutput ();//我已经传输完了! //确定服务器接收完毕,才能够断开连接 InputStream inputStream = socket.getInputStream (); ByteArrayOutputStream bos = new ByteArrayOutputStream (); byte[] bytes1 = new byte[1024]; int len1; while ((len1 = inputStream.read ( bytes1 ))!= -1){ bos.write (bytes1,0,len1 ); } System.out.println (bos.toString ()); //关闭资源 inputStream.close (); bos.close (); fis.close (); os.close (); socket.close (); }}
/** * @author Daniel * 服务端 */public class FileTcpServerDaniel { public static void main(String[] args) throws Exception{ //1.创建服务 ServerSocket socket = new ServerSocket ( 2024 ); //2.监听客户端的连接 Socket accept = socket.accept (); //3.获取输入流 InputStream is = accept.getInputStream (); //文件输出 FileOutputStream fos = new FileOutputStream ( new File ( "66.jpg" ) ); int len; byte[] bytes = new byte[1024]; while ((len =is.read ( bytes ))!= -1){ fos.write ( bytes,0,len ); } //通知客户端我接收完毕了 OutputStream outputStream =accept.getOutputStream (); outputStream.write ( "我已经接收到了,你可以断开连接了".getBytes () ); //关闭资源 fos.close (); is.close (); accept.close (); socket.close (); outputStream.close (); }}
(3)先运行服务端,再运行客户端,运行结果显示目录下多出一个文件
4.UDP编程
1、使用的Socket是:DatagramSocket
2、构造方法:
DatagramSocket():不指定端口号,创建通信点,端口号随机分配,一般用于发送端
DatagramSocket(int port):指定端口号,创建通信点,一般用于接收端
3、成员方法:
send(DatagramPacket dp):将一个dp数据报包发送
receive(DatagramPacket dp):将数据接收到dp参数中
4、DatagramPacket介绍:
1、表示一个数据报数据的封装对象的类型
2、构造方法:
DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)
buf:要发送的数据的字节数组
offset:从数组的哪个位置开始发送
length:发送多少数据
address:发送到哪个ip
port:发送到哪个程序
3、常用成员方法:
getData():返回该数据包中的字节数组
getLength():返回该数据包中接收到的字节个数
5、UDP编程的步骤:
发送端:
1、使用的Socket是:DatagramSocket
2、构造方法:
DatagramSocket():不指定端口号,创建通信点,端口号随机分配,一般用于发送端
DatagramSocket(int port):指定端口号,创建通信点,一般用于接收端
3、成员方法:
send(DatagramPacket dp):将一个dp数据报包发送
receive(DatagramPacket dp):将数据接收到dp参数中
4、DatagramPacket介绍:
1、表示一个数据报数据的封装对象的类型
2、构造方法:
DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)
buf:要发送的数据的字节数组
offset:从数组的哪个位置开始发送
length:发送多少数据
address:发送到哪个ip
port:发送到哪个程序
3、常用成员方法:
getData():返回该数据包中的字节数组
getLength():返回该数据包中接收到的字节个数
5、UDP编程的步骤:
发送端:
(1)准备通信点对象
(2)准备发送的包裹对象
(3)调用通信点的发送方法
接收端:
(1)准备通信点对象
(2)准备接收端接收的容器
(3)调用通信点的接收方法
(4)解析接收到的数据准备通信点对象
(5)准备发送的包裹对象
(6)调用通信点的发送方法
接收端:
(1)准备通信点对象
(2)准备接收端接收的容器
(3)调用通信点的接收方法
(4)解析接收到的数据
//UDP编程 发送端public static void main(String[] args) throws IOException {// 创建通信点DatagramSocket ds = new DatagramSocket();byte[] b = "你好,我是周杰伦".getBytes();int len = b.length;InetAddress lh = InetAddress.getLocalHost();byte[] as ={(byte)192,(byte)168,2,84};byte[] a ={127,0,0,1};InetAddress ll = InetAddress.getByAddress(a);//System.out.println(lh.toString());//创建数据包DatagramPacket dp = new DatagramPacket(b, 0, len, ll, 9999);//调用send方法ds.send(dp);ds.close();}}
public class ClientUdp { //udp接收端 public static void main(String[] args) throws IOException { //创建通信点 DatagramSocket ds = new DatagramSocket(9999); //创建一个数组 byte[] bs = new byte[1024]; int len = bs.length; //创建一个接受包 DatagramPacket dp = new DatagramPacket(bs, len-1); //接受数据 ds.receive(dp); byte[] data = dp.getData(); int length = dp.getLength(); System.out.println(new String(data,0,length)); }}
运行结果为:
5.URL
https://www.baidu.com/
统一资源定位符:定位资源的,定位互联网上的某一个资源
DNS域名解析 www.baidu.com xxx.x…x…x
协议://ip地址:端口/项目名/资源
/** * @author Daniel * url */public class UrlDaniel { public static void main(String[] args) throws Exception { URL url = new URL ( "https://localhost:8080/index/jsp?username=Daniel&password=123" ); System.out.println ( url.getProtocol () );//协议 System.out.println ( url.getPort () );//端口 System.out.println ( url.getPath () );//文件 System.out.println ( url.getHost () );//主机ip System.out.println ( url.getQuery () );//参数 System.out.println ( url.getFile () );//全路径 }}
运行结果为: