计算机网络:
计算机网络是指将地理位置不同的具有独立功能的多台过算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
网络编程的目的:传播交流信息,数据交换,通信
要达到这样的效果需要什么?
-
如何准确的连接一台主机 192.160.11.11:端口,定位到这个计算机的每个资源
-
找到这个主机,如何传输数据?
网络编程:TCP/IP C/S架构
1.2、网络通信的要素
如何实现网络通信?
通行双方的地址:
-
ip
-
端口号
规则:网络通信的协议
TCP/IP参考模型:
小结:
1.3、IP
ip地址:InetAddress对象
(该对象没有构造方法,只能通过该类的静态方法获取)
-
唯一定位一台网络上的计算机
-
127.0.0.1 : 本机 location
- ip地址的分类:
- IPV4/IPV6:
- IPV4 :127.0.0.1 , 4个字节组成。,0~255,有42亿~ ; 30亿都在北美, 亚洲4亿,2011年就用尽;
- IPV6 :128位。 8个无符号整数!
- IPV4/IPV6:
-
- 公网(互联网) - 私网(局域网):
- ABCD类地址
- 192.168.xx.xx.专门给组织内部使用
- 域名:记忆ip问题!
- 公网(互联网) - 私网(局域网):
1 try { 2 //查询本机的地址 3 InetAddress ine1 = InetAddress.getByName("127.0.0.1"); 4 System.out.println(ine1); 5 ine1 = InetAddress.getByName("localhost"); 6 System.out.println(ine1); 7 ine1 = InetAddress.getLocalHost(); //获取到计算机名和ip地址 8 System.out.println(ine1); 9 10 //查询网站ip地址 11 InetAddress ine2 = InetAddress.getByName("www.baidu.com"); 12 System.out.println(ine2); 13 14 //常用方法 15 System.out.println(ine2.getAddress()); //返回一组地址 16 System.out.println(ine2.getCanonicalHostName()); //获取规范ip地址 17 System.out.println(ine2.getHostAddress()); //ip 18 System.out.println(ine2.getHostName()); //域名或组件电脑的名字 19 } catch(UnknownHostException e) { 20 e.printStackTrace(); 21 }
1.4、端口
端口号表示计算机上一个程序的进程:
-
不同的进程有不同的端口号!用来区分软件
-
程序数量被规定为 0~65535
又分为TCP/UTP:俩协议端口号共65535*2。tcp:80,utp:80。ok 单个协议下,端口号不能冲突
-
端口分类:
-
公有端口 0~1023(尽量不要去占用,它一般会被内置的进程或服务器使用)
-
HTTP:80
-
HTTPS:443
-
FTP:21
-
Telent:23
-
-
程序注册端口:1024~49151,分配给用户或者程序
-
Tomcat:8080
-
Mysql:3306
-
Oracle:1521
-
-
动态 私有:49152~65535(也尽量不要去占用)
-
1 netstat -ano # 查看所有的端口 2 netstat -ano|findstr "端口号" # 查看指定端口号 3 tasklist|findstr "端口号" # 查看指定端口号的进程
1 InetSocketAddress socket1 = new InetSocketAddress("127.0.0.1", 8080); 2 InetSocketAddress socket2 = new InetSocketAddress("localhost", 8080); 3 System.out.println(socket1); 4 System.out.println(socket2); 5 6 System.out.println(socket1.getAddress()); 7 System.out.println(socket1.getHostName()); //本机的host 8 System.out.println(socket1.getPort()); //端口号
1.5、通信协议
协议:约定,就好比我们现在说的是普通话。
网络通信协议:速率,传输码率,代码结构,传输控制...
问题:非常的复杂
大事化小:分层!
TCP/IP协议簇:
重要的协议:
-
TCP:用户传输协议
-
UDP:用户数据报协议
出名的协议:
-
TCP
-
IP: 网络互连协议
TCP/IP协议实际上是一组协议
TCP与UDP对比:
TCP:打电话
-
连接,稳定
-
三次握手、四次挥手\
1 三次握手: 2 最少需要三次,保证稳定连接! 3 A:你瞅啥? 4 B:瞅你咋地? 5 A:干一场! 6 7 四次发送(分手): 8 A:我要走了! 9 B:你真的要走了吗? 10 B:你真的真的要走了吗? 11 A:我的真的要走了!
-
客户端、服务端
-
传输完毕,释放连接,效率低
UDP:发短信
-
不连接,不稳定
-
客户端、服务端:没有明确界限,如客户端发客户端
-
不管有没有准备好,都可以发给你
-
DDOS:洪水攻击!(给你发一堆垃圾包,造成端口线路堵塞。饱和攻击)
1.6、TCP
实现聊天:
客户端.
1.连接服务器Socket
2.发送消息
1 //客户端 2 public class TcpClient { 3 public static void main(String[] args) { 4 Socket socket=null; 5 try { 6 //获取IP地址 7 InetAddress ip = InetAddress.getByName("127.0.0.1"); 8 //创建一个Socket连接 9 socket = new Socket(ip,8888); 10 //获取连接的IO输出流,发送信息 11 OutputStream out = socket.getOutputStream(); 12 out.write("我是一个客户端".getBytes()); 13 } catch (IOException e) { 14 e.printStackTrace(); 15 } finally{ 16 try { 17 socket.close(); 18 } catch (IOException e) { 19 e.printStackTrace(); 20 } 21 } 22 } 23 }
服务器
1.建立服务的端口ServerSocket
2.等待用户的链接accept
3.接收用的消息
1 //服务端 2 public class TcpServlet { 3 public static void main(String[] args){ 4 ServerSocket server = null; 5 try { 6 //创建服务器套接字对象,指定该套接字的端口 7 server = new ServerSocket(8888); 8 //等待客户端连接,获取连接的套接字对象 9 Socket socket = server.accept(); 10 //获取该套接字对象的输入流,接收信息 11 InputStream in = socket.getInputStream(); 12 byte[] b=new byte[1024]; 13 int len; 14 // 这个接收方式有问题:假如接收中文大于b字节大小,那么那个字符会乱码 15 // while((len=in.read(b))!=-1){ 16 // System.out.println(new String(b,0,len)); 17 // } 18 //管道流 相当于在客户端与服务端之间加一个管道 可以避免乱码 19 ByteArrayOutputStream baout = new ByteArrayOutputStream(); 20 while((len=in.read(b))!=-1){ 21 //将接收到的信息写入到字节数组输出流 22 baout.write(b,0,len); 23 } 24 //因为是字节数组输出流,字节toString就可以获取到里面的值 25 System.out.println("客户端:"+baout.toString()); 26 } catch (IOException e) { 27 e.printStackTrace(); 28 }finally{ 29 try { 30 server.close(); 31 } catch (IOException e) { 32 e.printStackTrace(); 33 } 34 } 35 } 36 }
TCP实现上传文件(可以将全部流都关闭):
服务端
1 //服务端 2 public class TcpServlet02 { 3 public static void main(String[] args){ 4 try{ 5 //创建服务 6 ServerSocket serverSocket = new ServerSocket(9000); 7 //监听客户端的连接 8 Socket socket = serverSocket.accept();//阻塞式监听,会一直阻塞,等待客户端连接 9 //获取输入流 10 InputStream is=socket.getInputStream(); 11 //文件输出 将客户端发的文件写入到指定的文件流 12 FileOutputStream fos=new FileOutputStream("mmp.png");//会自动创建文件 13 byte[] buffer = new byte[1024]; 14 int len; 15 while((len=is.read(buffer))!=-1){ 16 fos.write(buffer,0,len); 17 fos.flush(); 18 } 19 20 //接收完毕,后告诉客户端 21 OutputStream os=socket.getOutputStream(); 22 os.write("我已经接收完毕".getBytes()); 23 os.flush(); 24 25 //关闭资源 26 serverSocket.close(); 27 os.close();//告诉客户端的输出流必须关闭不然客户端会报错 28 fos.close(); 29 }catch(Exception e){ 30 e.printStackTrace(); 31 } 32 33 } 34 }
客户端
1 //客户端 2 public class TcpClient02 { 3 public static void main(String[] args) { 4 try{ 5 //创建套接字 6 Socket socket=new Socket("127.0.0.1",9000); 7 //将文件输出到服务端 8 OutputStream os = socket.getOutputStream(); 9 FileInputStream fis = new FileInputStream("clipboard.png"); 10 byte[] buffer=new byte[1024]; 11 int len; 12 while((len=fis.read(buffer))!=-1){ 13 os.write(buffer,0,len); 14 os.flush(); 15 } 16 17 //上传完毕后要告诉服务器我已经结束了,服务端在走 18 socket.shutdownOutput(); 19 20 //接收服务端发送的提示信息 21 InputStream inputStream = socket.getInputStream(); 22 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 23 byte[] buffer2 = new byte[1024]; 24 int len2; 25 while ((len2=inputStream.read(buffer2))!=-1){ 26 baos.write(buffer2,0,len2); 27 baos.flush(); 28 } 29 System.out.println(baos.toString()); 30 31 //关闭资源 32 socket.close(); 33 fis.close(); 34 baos.close(); 35 }catch(Exception e){ 36 e.printStackTrace(); 37 } 38 39 } 40 }
1.7、UDP
DatagramSocket:数据报套接字
-
构造方法:
DatagramSocket(int port):指定端口,接收包。不指定端口则可以发送包
-
常用方法:
send(DatagramPacket p):将指定包发送到包指定的ip地址、端口号的接收端去
receive(DatagramPacket p):将发过来的包中的数据接收,在转给指定的包中。通过指定包来获取信息
close():关闭该套接字:
DatagramPacket:数据报包
-
构造方法:
DatagramPacket(byte[] 数据,int 开头,int 结尾,ip,端口 ):指定要发送的数据,数据长度的起始,ip和端口。发送包的地址是该构造方法指定的 ip地址 与 端口号 的接收端
DatagramPacket(byte[] 数据,int 开头,int 结尾):可用于接收包是,指定接收包的指定长度字节容器(容器大小决定信息乱不乱码),该容器的起始长度
-
常用方法:
byte[] getDate():获取包中的数据
发短信:不用连接,需要知道对方的地址
消息发送:
客户端
1 //不需要连接服务端,就可以发送包 2 public class UdpCilent { 3 public static void main(String[] args) throws Exception { 4 //创建一个socket连接 5 DatagramSocket data = new DatagramSocket(); 6 //建一个包 7 byte[] msg="你好接收端".getBytes(); 8 InetAddress localhost =InetAddress.getByName("localhost"); 9 //将要发送的数据、数据长度起始、ip地址、端口号放在包中 10 DatagramPacket packet = new DatagramPacket(msg,0,msg.length,localhost,9000); 11 //发送包 12 data.send(packet); 13 data.close(); 14 } 15 }
接收端
1 //接收端(因为没有服务端对象),还是要等待客户端的连接 2 public class UdpReceive { 3 public static void main(String[] args) throws Exception { 4 //开放端口 客户端也可以开放端口,因为没有服务端 5 DatagramSocket data = new DatagramSocket(9000); 6 //接收数据 7 byte[] msg=new byte[100]; 8 DatagramPacket packet = new DatagramPacket(msg,0,msg.length); 9 data.receive(packet);//阻塞接收 将信息给到自定义包 10 11 System.out.println(packet.getAddress().getHostName());//获取该包是那个发的 12 System.out.println(new String(packet.getData()));//获取包中的数据 13 14 data.close(); 15 } 16 }
实现连续发送信息并接收:
客户端
1 public class UdpCilent01 { 2 public static void main(String[] args) throws Exception { 3 //创建一个socket连接 4 DatagramSocket data = new DatagramSocket(); 5 //该buffer字符流,相当于Scanner对象. 获取输入到控制台的字符的流 6 BufferedReader buffer = new BufferedReader(new InputStreamReader(System.in)); 7 while(true) { 8 System.out.println("请输入信息:"); 9 //这个相当于scanner.nextLine(); 10 String str= buffer.readLine(); 11 byte[] msg =str.getBytes(); 12 //获取ip和端口号 13 InetSocketAddress localhost = new InetSocketAddress("localhost", 6666); 14 //将要发送的数据、数据长度起始、ip地址、端口号放在包中 15 DatagramPacket packet = new DatagramPacket(msg,0, msg.length,localhost); 16 data.send(packet); 17 if(str.equals("bye")){ 18 break; 19 } 20 } 21 data.close(); 22 } 23 }
接收端
1 //接收端(因为没有服务端对象),还是要等待客户端的连接 2 public class UdpReceive01 { 3 public static void main(String[] args) throws Exception { 4 //开放端口 客户端也可以开放端口,因为没有服务端 5 DatagramSocket data = new DatagramSocket(6666); 6 while(true) { 7 //接收数据 8 byte[] msg = new byte[1024]; 9 DatagramPacket packet = new DatagramPacket(msg, 0, msg.length); 10 data.receive(packet);//阻塞接收 将信息给到自定义包 11 //转化数据 12 byte[] by=packet.getData(); 13 String s=new String(by,0,by.length); 14 System.out.println(s); 15 if(s.equals("bye")){ 16 break; 17 } 18 } 19 data.close(); 20 } 21 }
实现聊天:
客户端线程:
1 public class Cilent implements Runnable { 2 DatagramSocket socket=null; 3 BufferedReader br=null; 4 5 private String ip;//连接的ip 6 private int post_b;//发送的端口 7 public Cilent(){} 8 public Cilent(String ip,int post_b){ 9 this.ip=ip; 10 this.post_b=post_b; 11 //初始化socket 12 try{ 13 socket=new DatagramSocket();//创建socket 14 br=new BufferedReader(new InputStreamReader(System.in));//创建获取控制台输入字符信息的流 15 }catch (Exception e){ 16 e.printStackTrace(); 17 } 18 } 19 @Override 20 public void run() { 21 System.out.println("请输入信息:"); 22 while(true) { 23 try{ 24 //这个相当于scanner.nextLine(); 25 String str= br.readLine(); 26 byte[] msg =str.getBytes(); 27 //获取ip和端口号 28 InetSocketAddress localhost = new InetSocketAddress(this.ip,this.post_b); 29 //将要发送的数据、数据长度起始、ip地址、端口号放在包中 30 DatagramPacket packet = new DatagramPacket(msg,0, msg.length,localhost); 31 socket.send(packet);//发送给指定端口的接收端 32 if(str.equals("bye")){ 33 break; 34 } 35 }catch (Exception e){ 36 e.printStackTrace(); 37 } 38 } 39 socket.close(); 40 } 41 }
接收端线程:
1 //接收端(因为没有服务端对象),还是要等待客户端的连接 2 public class Receive implements Runnable { 3 DatagramSocket socket=null; 4 5 private int post_z;//接收端的端口 6 private String name;//发送的人 7 public Receive(){} 8 public Receive(int post_z,String name){ 9 this.name=name; 10 this.post_z=post_z; 11 //初始化有端口socket 12 try{ 13 socket=new DatagramSocket(post_z);//开放端口 14 }catch (Exception e){ 15 e.printStackTrace(); 16 } 17 } 18 @Override 19 public void run() { 20 while(true) { 21 try{ 22 //接收数据 23 byte[] msg = new byte[1024]; 24 DatagramPacket packet = new DatagramPacket(msg, 0, msg.length); 25 socket.receive(packet);//阻塞接收 将信息给到自定义包 26 //转化数据 27 byte[] by=packet.getData(); 28 String s=new String(by,0,by.length); 29 System.out.println(this.name+":"+s); 30 if(s.equals("bye")){ 31 break; 32 } 33 }catch (Exception e){ 34 e.printStackTrace(); 35 } 36 } 37 socket.close(); 38 39 } 40 }
测试:
1 public class Test01 {//学生 2 public static void main(String[] args) { 3 new Thread(new Cilent("localhost",9999)).start();//连接的ip和发送目标的端口 4 new Thread(new Receive(8888,"老师")).start();//目标端口和发送人 5 } 6 }
1 public class Test02 {//老师 2 public static void main(String[] args) { 3 new Thread(new Cilent("localhost",8888)).start();//连接的ip和发送目标的端口 4 new Thread(new Receive(9999,"学生")).start();//目标端口和发送人 5 } 6 }
1.8、URL
统一资源定位符:定位资源的,定位互联网上的某一个资源
DNS域名解析:www.baidu.com 解析 ip=XXX...X
url有5部分组成(可少不多):
url对象的一些方法:
1 url.getProtocol() //获取协议 2 url.getHost() //获取主机ip 3 url.getPort() //获取URL的端口 4 url.getPath() //获取URL文件的软件 5 url.getFile() //获取URL文件的全路径 6 url.getQuery() //获取URL的参数
url下载网络资源:
1 public class URLTest { 2 public static void main(String[] args) throws Exception { 3 //创建字符串URL,指定网络资源地址 4 URL url=new URL("https://m10.music.126.net/20200314182045/4d9b6789fc88d129dea4e4e062607049/yyaac/060b/0e09/530e/1adeb3b7769c4c40b208dd902c8c1a12.m4a"); 5 //将字符串url转为HTTP网络url,才能下载 6 HttpURLConnection u = (HttpURLConnection)url.openConnection(); 7 InputStream in = u.getInputStream();//获取url的流(网上的东西全都是字节流) 8 //将流的资源下载到本地中 9 FileOutputStream fis = new FileOutputStream("2b.m4a"); 10 byte[] b = new byte[1024]; 11 int len; 12 while((len=in.read(b))!=-1){ 13 fis.write(b,0,len); 14 fis.flush(); 15 } 16 System.out.println("下载完毕"); 17 in.close(); 18 fis.close(); 19 } 20 }
URL编码/解码:
-
编码:URLEncoder.encode(String value,String charset)
-
解码:URLDecoder.decod(String value,String charset)
-
-
IPV4 :127.0.0.1 , 4个字节组成。,0~255,有42亿~ ; 30亿都在北美, 亚洲4亿,2011年就用尽;
-
IPV6 :128位。 8个无符号整数!
-
-
公网(互联网) - 私网(局域网):
-
ABCD类地址
-
192.168.xx.xx.专门给组织内部使用
-
-
域名:记忆ip问题!