前段时间出差,还有做一个Java商城的实战项目,花费了很多时间,没有进行系统的学习,今天来继续网络编程的学习。
学习Java的io流应用,和TCP、UDP的socket、package编程
1.1 概述
打电话 -- 连接 -- 接了 --通话 TCP
发短信 -- 发送了就完事儿了 --接收 UDP
计算机网络,指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
网络编程的目的
无线电台...传播交流信息,数据交换,通信
想要达成这个效果需要什么?
-
如何准确的定位网络上的一台主机,IP地址:端口,定位到这个计算机上的某个资源
-
找到了这个主机,如何传输数据?
网页编程:JavaWeb B/S架构
网络编程:TCP/IP C/S架构
1.2 网络通信的要素
如何实现网络的通信?
通信双方地址:
-
IP地址 192.168.1.1
-
端口号 :8080
-
192.168.1.1:8080
规则:网络通信协议
TCP/IP参考模型
| OSI七层网络模型 | TCP/IP四层概念模型 | 对应网络协议 |
|---|---|---|
| 应用层 | 应用层 | HTTP、TFTP、FTP、NFS、WAIS、SMTP |
| 表示层 | 应用层 | Telnet、Rlogin、SNMP、Gopher |
| 会话层 | 应用层 | SMTP、DNS |
| 传输层 | 传输层 | TCP、UDP |
| 网络层 | 网络层 | IP、ICMP、ARP、RARP、AKP、UUCP |
| 数据链路层 | 数据链路层 | FDDI、Ethernet、Arpanet、PDN、SLIP、PPP |
| 物理层 | 数据链路层 | IEEE 802.1A、IEEE 802.2到IEEE 802.11 |
小结:
-
网络编程中有两个主要的问题
-
如何准确的定位到网络上的一台或者多台主机
-
找到主机之后如何进行通信
-
-
网络编程中的要素
-
IP地址和端口号
-
网络通信协议
-
-
万物皆对象
1.3 IP
IP地址:InetAddress
-
唯一定位一台网络上计算机
-
127.0.0.1:本机localhost
-
IP地址的分类
-
IPv4/IPv6
-
IPv4 127.0.0.1,4个字节组成,0~255,有42亿个左右;30亿在北美,亚洲只有4亿,2011年已经用尽
-
IPv6 可以使用cmd命令ipconfig查看,有128位,8个无符号整数
-
-
C:\Users\88534>ipconfig
Windows IP 配置
以太网适配器 VirtualBox Host-Only Network:
连接特定的 DNS 后缀 . . . . . . . :
本地链接 IPv6 地址. . . . . . . . : fe80::fc60:729c:8420:ee91%14
IPv4 地址 . . . . . . . . . . . . : 192.168.56.1
子网掩码 . . . . . . . . . . . . : 255.255.255.0
默认网关. . . . . . . . . . . . . :
无线局域网适配器 本地连接* 1:
媒体状态 . . . . . . . . . . . . : 媒体已断开连接
连接特定的 DNS 后缀 . . . . . . . :
无线局域网适配器 本地连接* 2:
媒体状态 . . . . . . . . . . . . : 媒体已断开连接
连接特定的 DNS 后缀 . . . . . . . :
无线局域网适配器 WLAN:
连接特定的 DNS 后缀 . . . . . . . :
本地链接 IPv6 地址. . . . . . . . : fe80::81a3:fbe4:4431:e509%19
IPv4 地址 . . . . . . . . . . . . : 192.168.1.4
子网掩码 . . . . . . . . . . . . : 255.255.255.0
默认网关. . . . . . . . . . . . . : 192.168.1.1
-
公网(互联网)/私网(局域网)
-
ABCD类地址8、16、24位+多=组播地址
-
192.168.xx.xx专门给组织内部使用
-
0-----------------------128--------192--------255
-
-
域名:便于记忆
1.4 端口
端口表示计算机上的一个程序的进程
-
不同的进程有不同的端口号,用来区分软件
-
被规定0~65535
1 package com.zhou.networkCode; 2 3 import java.net.InetAddress; 4 import java.net.UnknownHostException; 5 6 //测试IP 7 public class TestInetAddress { 8 public static void main(String[] args) { 9 try { 10 //查询本机地址 11 InetAddress inetAddress1 = InetAddress.getByName("127.0.0.1");//localhost、getLocalHost() 12 System.out.println(inetAddress1); 13 14 //查询网站IP地址 15 InetAddress inetAddress2 = InetAddress.getByName("www.baidu.com"); 16 System.out.println(inetAddress2); 17 18 //常用方法 19 System.out.println(inetAddress2.getAddress());//[B@1b6d3586 20 System.out.println(inetAddress2.getHostAddress());//183.232.231.174 ip 21 System.out.println(inetAddress2.getCanonicalHostName());//www.baidu.com 规范的名字 22 System.out.println(inetAddress2.getHostName());//www.baidu.com 域名,或者自己电脑的名字 23 24 } catch (UnknownHostException e) { 25 e.printStackTrace(); 26 } 27 } 28 }
-
TCP/UDP:65535*2,每个协议都有一组。可以分别使用同一端口不同协议。 tcp:80,udp:80.在单个协议下,端口号不能冲突
-
端口分类
-
公有端口:0~1023
-
HTTP:80
-
HTTPS:443
-
FTP:21
-
SSH:22
-
Telnet:23
-
-
程序注册端口:2014~49151,分配用户或者程序
-
Tomcat:8080
-
MySQL:3306
-
Oracle:1521
-
-
动态、私有:49152~65535
netstat -ano #查看所有的端口
netstat -ano|findstr "5900" #查看指定的端口
tasklist|findstr "8696" #查看指定端口的进程
ctrl+shift+ESC #打开任务管理器,查看进程 -
1.5 通信协议
协议:约定,大家共同使用的方法
网络通信协议:速度,传输码率、代码结构、传输控制...
大事化小:采用分层的概念
TCP/IP协议簇:实际上是一组协议
-
TCP簇:用户传输协议
-
IP簇:用户数据报协议
出名的协议:
-
TCP:传输控制协议
-
IP:网络互联协议
TCP/UDP对比
TCP:打电话
-
连接,稳定
-
三次握手,四次挥手
-
最少需要三次,保证稳定连接
-
A:你瞅啥?
-
B:瞅你咋地?(建立B->A)
-
A:干一场!(建立A->B)
-
-
A:我要走了
-
B:我知道了(断开A->B)
-
B:我也要走了
-
A:好的,我知道你要走了(断开B->A)
-
-
客户端、服务端
-
传输完成,释放连接,传输可靠,效率低
UDP:发短信
-
不连接,不稳定
-
客户端、服务端:没有明确的界限
-
不管有没有准备好,都发
-
DDOS:洪水攻击,饱和攻击
1.6 TCP
服务器
-
连接服务器Socket
-
发送消息
客户端
-
建立服务的端口ServerSocket
-
等待用户的链接accept
-
接收消息
简单通信
服务器端先执行
1 package com.zhou.networkCode; 2 3 import java.io.ByteArrayOutputStream; 4 import java.io.IOException; 5 import java.io.InputStream; 6 import java.net.ServerSocket; 7 import java.net.Socket; 8 9 public class TcpServerDemo01 { 10 //先运行服务器端Server开启接受,再到运行客户端Client发送信息 11 public static void main(String[] args) { 12 ServerSocket serverSocket = null; 13 Socket socket = null; 14 InputStream is = null; 15 ByteArrayOutputStream baos = null; 16 try { 17 //1.我得有一个地址 18 serverSocket = new ServerSocket(9999); 19 //2.等待客户端连接过来 20 socket = serverSocket.accept(); 21 //3.读取客户端的消息 22 is = socket.getInputStream(); 23 24 /* 25 byte[] buffer = new byte[1024]; 26 int len; 27 while ((len = is.read(buffer)) != -1) { 28 String msg = new String((buffer, 0, len); 29 System.out.println(msg); 30 } 31 */ 32 33 //管道流 34 baos = new ByteArrayOutputStream(); 35 byte[] buffer = new byte[1024]; 36 int len; 37 while ((len = is.read(buffer)) != -1) { 38 baos.write(buffer,0,len); 39 } 40 System.out.println(baos.toString()); 41 42 43 } catch (Exception e) { 44 e.printStackTrace(); 45 } finally { 46 //关闭资源 47 if (baos!=null){ 48 try { 49 baos.close(); 50 } catch (IOException e) { 51 e.printStackTrace(); 52 } 53 } 54 if (is!=null){ 55 try { 56 is.close(); 57 } catch (IOException e) { 58 e.printStackTrace(); 59 } 60 } 61 if (socket!=null){ 62 try { 63 socket.close(); 64 } catch (IOException e) { 65 e.printStackTrace(); 66 } 67 } 68 if (serverSocket!=null){ 69 try { 70 serverSocket.close(); 71 } catch (IOException e) { 72 e.printStackTrace(); 73 } 74 } 75 } 76 } 77 }
客户端后执行
1 package com.zhou.networkCode; 2 3 import java.io.IOException; 4 import java.io.OutputStream; 5 import java.net.InetAddress; 6 import java.net.Socket; 7 8 public class TcpClientDemo01 { 9 public static void main(String[] args) { 10 Socket socket = null; 11 OutputStream os = null; 12 try { 13 //1.要知道服务器的地址 14 InetAddress serverIP = InetAddress.getByName("127.0.0.1"); 15 int port = 9999; 16 //2.创建一个socket连接 17 socket = new Socket(serverIP,port); 18 //3.发送消息IO流 19 os = socket.getOutputStream(); 20 os.write("你好!".getBytes());//发送信息 21 } catch (Exception e) { 22 e.printStackTrace(); 23 } finally { 24 if (os!=null){ 25 try { 26 os.close(); 27 } catch (IOException e) { 28 e.printStackTrace(); 29 } 30 } 31 if (socket!=null){ 32 try { 33 socket.close(); 34 } catch (IOException e) { 35 e.printStackTrace(); 36 } 37 } 38 } 39 } 40 }
输出:你好
文件上传
服务器端
1 package com.zhou.networkCode; 2 3 import java.io.*; 4 import java.net.ServerSocket; 5 import java.net.Socket; 6 import java.nio.charset.StandardCharsets; 7 8 public class TcpServerDemo02 { 9 public static void main(String[] args) throws IOException { 10 //1.创建服务 11 ServerSocket serverSocket = new ServerSocket(9000); 12 //2.监听客户端的连接 13 Socket socket = serverSocket.accept();//阻塞式监听,会一直等待客户端连接 14 //3.获取输入流 15 InputStream is = socket.getInputStream(); 16 //4.文件输出 17 FileOutputStream fos = new FileOutputStream(new File("C:\\Users\\88534\\Desktop\\Java入门\\NetWorkCode\\receive.jpg")); 18 byte[] buffer = new byte[1024]; 19 int len; 20 while ((len=is.read(buffer))!=-1){ 21 fos.write(buffer,0,len); 22 } 23 //通知客户端接收完毕 24 OutputStream os = socket.getOutputStream(); 25 os.write("我接收完毕了,你可以断开了".getBytes()); 26 //5.关闭资源 27 os.close(); 28 fos.close(); 29 is.close(); 30 socket.close(); 31 serverSocket.close(); 32 } 33 }
客户端
1 package com.zhou.networkCode; 2 3 import java.io.*; 4 import java.net.InetAddress; 5 import java.net.Socket; 6 7 public class TcpClientDemo02 { 8 public static void main(String[] args) throws IOException { 9 //1.建立一个socket连接 10 Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000); 11 //2.创建一个输出流 12 OutputStream os = socket.getOutputStream(); 13 //3.文件流 14 FileInputStream fis = new FileInputStream(new File("C:\\Users\\88534\\Desktop\\Java入门\\NetWorkCode\\Java.jpg")); 15 //4.写出文件 16 byte[] buffer = new byte[1024]; 17 int len; 18 while ((len=fis.read(buffer))!=-1){ 19 os.write(buffer,0,len); 20 } 21 //通知服务器,已经传输完了 22 socket.shutdownOutput(); 23 //确定服务器接收完毕,才能够断开连接 24 InputStream is = socket.getInputStream(); 25 //String Array[] 26 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 27 byte[] buffer2 = new byte[1024]; 28 int len2; 29 while ((len2=is.read(buffer2))!=-1){ 30 baos.write(buffer2,0,len2); 31 } 32 System.out.println(baos.toString()); 33 //5.关闭资源 34 baos.close(); 35 is.close(); 36 fis.close(); 37 os.close(); 38 socket.close(); 39 } 40 }
1.7 Tomcat
服务器:Tomcat服务器
客户端:浏览器 B/S架构
打开bin目录下startup.bat(Windows下)/startup.sh(IOS下)打开服务器,开启8080端口,在webapp文件夹中放入网页信息
1.8 UDP
发短信:不需要连接,只需要知道对方的地址
发送消息
发送端
1 package com.zhou.networkCode; 2 3 import java.net.DatagramPacket; 4 import java.net.DatagramSocket; 5 import java.net.InetAddress; 6 7 //不需要连接服务器 8 public class UdpClientDemo01 { 9 public static void main(String[] args) throws Exception{ 10 //1.建立一个Socket 11 DatagramSocket socket = new DatagramSocket(); 12 13 //2.建个包 14 String msg = "Hello,Server!"; 15 16 //发送位置 17 InetAddress localhost = InetAddress.getByName("localhost"); 18 int port = 9090; 19 //建立一个Packet 20 DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, port); 21 //3.发送包 22 socket.send(packet); 23 //4.关闭流 24 socket.close(); 25 } 26 }
接收端
1 package com.zhou.networkCode; 2 3 import java.net.DatagramPacket; 4 import java.net.DatagramSocket; 5 6 public class UdpServerDemo01 { 7 public static void main(String[] args) throws Exception{ 8 //开放端口 9 DatagramSocket socket = new DatagramSocket(9090); 10 //接收数据包 11 byte[] buffer = new byte[1024]; 12 DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length); 13 socket.receive(packet);//阻塞接收 14 15 System.out.println(packet.getAddress().getHostAddress()); 16 System.out.println(new String(packet.getData(),0,packet.getLength())); 17 //关闭连接 18 socket.close(); 19 } 20 }
输出:127.0.0.1
Hello,Server!
咨询
循环发送消息
1 package com.zhou.networkCode; 2 3 import java.io.BufferedReader; 4 import java.io.InputStreamReader; 5 import java.net.DatagramPacket; 6 import java.net.DatagramSocket; 7 import java.net.InetSocketAddress; 8 9 public class UdpSenderDemo01 { 10 public static void main(String[] args) throws Exception{ 11 DatagramSocket socket = new DatagramSocket(8888); 12 13 //准备数据:控制台读取System.in 14 15 BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 16 17 while (true){ 18 String data = reader.readLine(); 19 byte[] datas = data.getBytes(); 20 DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress("localhost", 6666)); 21 22 socket.send(packet); 23 if (data.equals("bye")) { 24 break; 25 } 26 } 27 28 socket.close(); 29 } 30 }
循环接收消息
1 package com.zhou.networkCode; 2 3 import java.net.DatagramPacket; 4 import java.net.DatagramSocket; 5 6 public class UdpReceiverDemo01 { 7 public static void main(String[] args) throws Exception{ 8 DatagramSocket socket = new DatagramSocket(6666); 9 10 while (true){ 11 //准备接收包裹 12 byte[] container = new byte[1024]; 13 DatagramPacket packet = new DatagramPacket(container,0,container.length); 14 15 //断开连接:检测输入bye 16 byte[] data = packet.getData(); 17 String receiveData = new String(data, 0, data.length); 18 19 System.out.println(receiveData); 20 if (receiveData.equals("bye")){ 21 break; 22 } 23 24 socket.receive(packet); 25 } 26 27 28 socket.close(); 29 } 30 }
在线咨询
使用多线程,既可以是接收方,又可以是发送方
发送端
1 package com.zhou.networkCode; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 import java.net.DatagramPacket; 7 import java.net.DatagramSocket; 8 import java.net.InetSocketAddress; 9 10 public class OnlineTalkSenderDemo01 implements Runnable{ 11 DatagramSocket socket = null; 12 BufferedReader reader = null; 13 14 private int fromPort; 15 private String toIP; 16 private int toPort; 17 18 public OnlineTalkSenderDemo01(int fromPort, String toIP, int toPort) { 19 this.fromPort = fromPort; 20 this.toIP = toIP; 21 this.toPort = toPort; 22 23 try { 24 socket = new DatagramSocket(fromPort); 25 reader = new BufferedReader(new InputStreamReader(System.in)); 26 } catch (Exception e) { 27 e.printStackTrace(); 28 } 29 } 30 31 @Override 32 public void run() { 33 34 while (true){ 35 try { 36 String data = reader.readLine(); 37 byte[] datas = data.getBytes(); 38 DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress(this.toIP, this.toPort)); 39 40 socket.send(packet); 41 if (data.equals("bye")) { 42 break; 43 } 44 } catch (Exception e) { 45 e.printStackTrace(); 46 } 47 } 48 socket.close(); 49 } 50 }
接收端
1 package com.zhou.networkCode; 2 3 import java.io.IOException; 4 import java.net.DatagramPacket; 5 import java.net.DatagramSocket; 6 import java.net.SocketException; 7 8 public class OnlineTalkReceiverDemo01 implements Runnable{ 9 DatagramSocket socket = null; 10 private int port; 11 private String msgFrom; 12 13 public OnlineTalkReceiverDemo01(int port, String msgFrom) { 14 this.port = port; 15 this.msgFrom = msgFrom; 16 try { 17 socket = new DatagramSocket(port); 18 } catch (Exception e) { 19 e.printStackTrace(); 20 } 21 } 22 23 @Override 24 public void run() { 25 while (true){ 26 try { 27 //准备接收包裹 28 byte[] container = new byte[100]; 29 DatagramPacket packet = new DatagramPacket(container,0,container.length); 30 socket.receive(packet); 31 32 //断开连接:检测输入bye 33 byte[] data = packet.getData(); 34 String receiveData = new String(data, 0, data.length); 35 36 System.out.println(msgFrom + ":" + receiveData); 37 if (receiveData.equals("bye")){ 38 break; 39 } 40 41 } catch (Exception e) { 42 e.printStackTrace(); 43 } 44 } 45 socket.close(); 46 } 47 }
用户1:学生->老师
package com.zhou.networkCode; public class OnlineTalkStudent { public static void main(String[] args) { //开启两个线程 new Thread(new OnlineTalkSenderDemo01(7777,"127.0.0.1",9999)).start(); new Thread(new OnlineTalkReceiverDemo01(8888,"老师")).start(); } }
用户2:老师->学生
package com.zhou.networkCode; public class OnlineTalkTeacher { public static void main(String[] args) { new Thread((new OnlineTalkSenderDemo01(5555,"localhost",8888))).start(); new Thread(new OnlineTalkReceiverDemo01(9999,"学生")).start(); } }
1.8 URL
统一资源定位符:定位资源,可以定位互联网上的某一个具体资源
DNS为域名解析 域名->指代IP
协议://IP地址:端口/文件所在目录/文件名.文件类型
package com.zhou.networkCode; import java.net.MalformedURLException; import java.net.URL; public class URLDemo01 { public static void main(String[] args) throws MalformedURLException { URL url = new URL("http://localhost:8080/helloWorld/index.jsp?username=zhou&password=123"); System.out.println(url.getProtocol());//协议:http System.out.println(url.getHost());//主机ip:localhost System.out.println(url.getPort());//端口:8080 System.out.println(url.getPath());//文件:/helloWorld/index.jsp System.out.println(url.getFile());//全路径:/helloWorld/index.jsp?username=zhou&password=123 System.out.println(url.getQuery());//参数:username=zhou&password=123 } }
从Tomcat下载文件
打开startup.bat运行Tomcat打开8080端口
1 package com.zhou.networkCode; 2 3 import java.io.FileOutputStream; 4 import java.io.InputStream; 5 import java.net.HttpURLConnection; 6 import java.net.MalformedURLException; 7 import java.net.URL; 8 9 public class URLDownload { 10 public static void main(String[] args) throws Exception { 11 //1.下载地址 12 URL url = new URL("http://localhost:8080/helloWorld/helloWorld.txt"); 13 //2.连接到这个资源,用HTTP 14 HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); 15 InputStream inputStream = urlConnection.getInputStream(); 16 FileOutputStream fos = new FileOutputStream("HELLOWORLD.txt"); 17 byte[] buffer = new byte[1024]; 18 int len; 19 while ((len=inputStream.read(buffer))!=-1){ 20 fos.write(buffer,0,len);//写出这个数据 21 } 22 fos.close(); 23 inputStream.close(); 24 urlConnection.disconnect();//断开连接 25 } 26 }
浙公网安备 33010602011771号