MIKU MOE

Java_网络编程

网络编程


 

1. 概述:

计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。

JavaWeb : 网页编程 B/S 客户端/服务器

网络编程 : TCP/IP | UDP/IP C/S 浏览器/服务器

2. 网络通信要素:

实现网络通信:

  • 通信双方地址: IP 端口

  • 规则:协议

TCPIP

OSI7

3. IP

  • IP地址 : InetAddress

  • 本机localhost:127.0.0.1

  • IP地址分类:

    • IPv4 / IPv6

    • 公网

      • ABCD类地址

      • 192.168.xxx.xxx组织内部使用

  • 域名:记忆IP

InetAddress

 /*************查询本机*************/
 InetAddress inetAddress1 = InetAddress.getByName("127.0.0.1");
 InetAddress inetAddress2 = InetAddress.getByName("localhost");
 InetAddress inetAddress3 = InetAddress.get();
 /*************查询百度*************/
 InetAddress inetAddress = InetAddress.getByName("www.baidu.com");
 System.out.println(inetAddress);
 //www.baidu.com//14.215.177.39
 /*************常用方法*************/
 //System.out.println(inetAddress.getAddress());//返回一组数据
 System.out.println(inetAddress.getCanonicalHostName());//规范名
 System.out.println(inetAddress.getHostAddress())//IP
 System.out.println(inetAddress.getHostName());//域名,或自己电脑名

 

4. 端口

表示计算机上一个程序的进程

  • 不同进程有不同端口号 用来区分软件

  • 规定 0~65535

  • TCP,UDP : 65535 * 2 单个协议不能冲突

  • 端口分类

    • 公有端口 0~1023

      • HTTP : 80

      • HTTPS : 443

      • FTP : 21

      • Telent : 23

    • 程序注册端口 : 1024~49151,分配用户或程序

      • Tomcat : 8080

      • MySQL : 3306

      • Oracle : 1521

    • 动态,私有 : 49152~65535 (动态分配,尽量不要占用)

 netstat -ano #查询所有端口
 netstat -ano|findstr "5900" #查询指定端口   "|"管道,过滤  
 tasklist|findstr "8696" #查看指定端口进程
 Ctrl+shift+ESC #任务管理器快捷键

 

InetSocketAddress

 InetSocketAddress s1 = new InetSocketAddress("127.0.0.1",8080);
 InetSocketAddress s2 = new InetSocketAddress("localhost",8080);
 System.out.printfln(s1);//  127.0.0.1:8080
 System.out.printfln(s2);//  localhost/127.0.0.1:8080
 ​
 System.out.printfln(socketAddress.getAddress());//   /127.0.0.1
 System.out.printfln(socketAddress.getHostName());//  localhost /*hosts文件配置*/
 System.out.printfln(socketAddress.getPort());//      8080

5. 通信协议

网络通信协议:速率,传输码率,代码结构,传输控制....

TCP/IP协议簇:实际上是一组协议

  • TCP : 用户传输协议

  • UDP : 用户数据报协议

  • TCP/IP : 网络互连协议

TCP UDP对比

  • TCP :

    • 面相连接 稳定

    • 三次握手 四次挥手

      • 三次握手:A->B B->A A->B

      • 四次挥手:A->B B->A B->A A->B

    • 客户端 服务器

    • 传输完成 连接释放 效率低

  • UDP :

    • 不连接 不稳定

    • 客户端 服务器:无明确界限

    • 不需要准备好

    • DDOS : 分布式拒绝服务攻击(饱和攻击)

6. TCP

客户端

  1. 连接服务器 Socket

  2. 发送消息

服务器

  1. 建立服务端口 ServerSocket

  2. 等待用户连接 accept

  3. 接收用的消息

 /**********服务端**********/
 ServerSocket serverSocket = null;
 Socket socket = null;
 Inputstream is = null;
 ByteArrayOutputStream baos = null;
 try {
     //1.有一个地址
     serverSocket = new ServerSocket(9999);
     //2.等待客户端连接过来
     socket = serverSocket.accept( );//与客户端socket是一个对象
     //3.读取客户端的消息
     InputStream is = socket.getInputStream( );
     //管道流
     baos = new ByteArrayOutputStream();
     byte[] buffer = new byte[1024];
     int len;
     while ((len=is.read(buffer))!=-1){
         baos.write(buffer,0,len);
     }
     System.out.print1n(baos.toString());
 } catch(IOException e) {
     e.printStackTrace();
 } finally {
     //关闭资源
     if (baos!=nu11){
         try {baos.close();}
         catch (IOException e) {e.printstackTrace();}}
     if (is!=nu11){
         try {is.close();}
         catch (IOException e) {e.printstackTrace();}}
     if (socket!=nu11){
         try {socket.close();}
         catch (IOException e) {e.printstackTrace();}}
     if (serverSocket!=nu11){
         try {serverSocket.close();}
         catch (IOException e) {e.printstackTrace();}}
 }

先启动服务端,每启动一次客户端服务端就受到一次消息

/**********客户端**********/ 
 Socket socket = null;
 Onputstream os = null;
 try {
     //1.知道服务器地址
     InetAddress serverIP = InetAddress.getByName("127.0.0.1");
     int port = 9999;//端口号
     //2.创建一个Socket连接
     Socket socket = new Socket(serverIP,port);
     //3.发送消息 IO流
     OutputStream os = socket.getOutputstream();
     os.write("hello,world. 你好,世界.".getBytes());
 } catch {e.printStackTrace();}
 finally {
     //关闭资源
     if (Onputstream!=nu11){
         try {Onputstream.close();}
         catch (IOException e) {e.printstackTrace();}}
     if (Socket!=nu11){
         try {Socket.close();}
         catch (IOException e) {e.printstackTrace();}}
 }

文件上传

 /**********客户端  抛出异常**********/ 
 //1.创建一个Socket连接
 Socket socket = new Socket("127.0.0.1",9000);
 //2.创建一个输出流
 OutputStream os = socket.getOutputstream();
 //3.读取文件
 FileInputStream fis = new FileInputStream(new File("Pic.jpg"));
 //4.写出文件
 byte[] buffer = new byte[1024];
 int len;
 while ((len=fis.read( buffer))!=-1) {
 os.write(buffer,0,len) ;
 }
 /**********通知服务器,我已经结束 -停止服务端监听**********/ 
 socket.shutdownOutput();
 /**********确定服务器接收完毕,才能断开**********/ 
 InputStream inputStream = socket.getInputStream();
 ByteArrayOutputStream baos = new ByteArrayOutputStream( );//字符管道流
 byte[] buffer2 = new byte[1024];
 int len2;
 while ((len2=inputStream.read(buffer2))!=-1) {
     baos.write(buffer2,0,len2);
 }
 System.out.println(baos.toString());
 //关闭资源
 baos.close();fis.close();os.close( );socket.close( );

 /**********服务端  抛出异常**********/
 //1.创建服务
 ServerSocket serverSocket = new ServerSocket(9000);
 //2.监听客户端连接
 Socket socket = serverSocket.accept( );//与客户端socket是一个对象
 //3.获取输入流
 InputStream is = socket.getInputStream( );
 //4.文件输出  --文件管道流
 FileOutputStream fos = new FileOutputStream(new File("receive.jpg"));
 byte[] buffer = new byte[1024];
 int len;
 while ((len=is.read(buffer))!=-1){
     fos.write(buffer,0,len);
 }
 /**********通知服务端接收完毕**********/ 
 OutputStream os = socket.getOutputStream();
 os.write("接收完毕".getBytes());
 //关闭资源
 fos.close();
 is.close();
 socket.close();
 serverSocket.close();

  Tomcat

服务器

  • 自定义 S

  • Toncat服务器 S : Java后台开发

客户端

  • 自定义 C

  • 浏览器 B

7. UDP

无服务器客户端概念

DatagramPacket 发

DatagramSocket 接

 /*UDP不需要连接服务器*/
 //发送端
 //1.建立一个Socket
 DatagramSocket socket = new DatagramSocket();
 //2.建个包
 String msg = "xxxxxxxxxx";
 //  发送给谁
 InetAddress localhost = InetAddress.getByName("localhost");
 int port = 9090;
 //  数据,数据起始长度,发送给谁
 DatagramPacket packet = new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,localhost,port);
 //3.发送包
 socket.sned(packet);
 //4.关闭流
 socket.close();
 /*UDP不需要连接服务器*/
 //发送端
 //1.建立一个Socket
 DatagramSocket socket = new DatagramSocket();
 //2.建个包
 String msg = "xxxxxxxxxx";
 //  发送给谁
 InetAddress localhost = InetAddress.getByName("localhost");
 int port = 9090;
 //  数据,数据起始长度,发送给谁
 DatagramPacket packet = new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,localhost,port);
 //3.发送包
 socket.sned(packet);
 //4.关闭流
 socket.close();

模拟通信

发送数据方:

DatagramSocket socket = new DatagramSocket(8888);
 //准备数据,控制台读取System.in
 BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
 while (true) {
       String data = reader.readLine();
       byte[] datas = data.getBytes();
       DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress("localhost", 6666));
       socket.send(packet);
       if (data.equals("byef")) { break; }
 }
 socket.close();
数据发送方

接收数据方:

 DatagramSocket socket = new DatagramSocket(6666);
 while (true) {
     //准备接收
     byte[] c = new byte[1024];
     DatagramPacket packet = new DatagramPacket(c, 0, c.length);
     socket.receive(packet);//阻塞式接收
     //判断断开连接 bye
     byte[] data = packet.getData();
     //packet.getLength() - 不能使用data.length
     String s = new String(data, 0, packet.getLength());
     System.out.println(s);
     if (s.equals("bye")) { break; }
 }
 socket.close();
数据接收方

双方通信

 /*接收线程*/
 public class NewReceive implements Runnable {
     DatagramSocket socket = null;
     private int port;
     private String msgFrom;
     //构造器
     public NewReceive(int port,String msgFrom) {
         this.port = port;
         this.msgFrom = msgFrom;
         try {
             socket = new DatagramSocket(port);
         } catch (SocketException e) {
             e.printStackTrace();
         }
     }
     @Override
     public void run() {
         while (true) {
             try {
                 //准备接收
                 byte[] c = new byte[1024];
                 DatagramPacket packet = new DatagramPacket(c, 0, c.length);
                 socket.receive(packet);//阻塞式接收
                 //判断断开连接 bye
                 byte[] data = packet.getData();
                 //packet.getLength() - 不能使用data.length
                 String s = new String(data, 0, packet.getLength());
                 System.out.println(msgFrom+":"+s);
                 if (s.equals("bye")) { break; }
             } catch (IOException e) { e.printStackTrace(); }
         }
         socket.close();
     }
 }
接收线程代码
 /*发送线程*/
 public class NewSender implements  Runnable {
     DatagramSocket socket = null;
     BufferedReader reader = null;
     private int fromPort;
     private String toIP;//对方IP
     private  int toPort;//对方端口号
     //从那个端口发送,发送到的IP,发送到的端口
     public NewSender(int fromPort,String toIP,int toPort) {
         this.fromPort = fromPort;
         this.toIP = toIP;
         this.toPort = toPort;
         try {
             socket = new DatagramSocket(fromPort);
             reader = new BufferedReader(new InputStreamReader(System.in));
         } catch (SocketException e) {
             e.printStackTrace();
         }
     }
     @Override
     public void run() {
         while (true) {
             try {
                 String data = null;
                 data = reader.readLine();
                 byte[] datas = data.getBytes();
                 DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress(this.toIP, this.toPort));
                 socket.send(packet);
                 if (data.equals("byef")) { break; }
             } catch (Exception e) { e.printStackTrace(); }
 ​
         }
         socket.close();
     }
 }
发送线程代码

具体双端实现:

/*学生端 - 开启两线程*/
 public class NewStu {
     public static void main(String[] args) {
         //开启两线程
         new Thread(new NewSender(7778, "localhost", 8888)).start();
         new Thread(new NewReceive(9999, "学生")).start();
     }
}

/*老师端 - 开启两线程*/
 public class NewTea {
     public static void main(String[] args) {
         //开启两线程
         new Thread(new NewSender(7777, "localhost", 9999)).start();
         new Thread(new NewReceive(8888, "老师")).start();
     }
 }

8. URL

统一资源定位符 : 定位资源,定义物联网上的某一资源

DNS 域名解释 : www.baidu.com --> 14.215.177.39

协议://IP地址:端口/项目名/资源

常用方法:

 URL url = new URL("http://localhost:8080/helloword/index.jsp?username=123");
 System.out.println(url.getProtocol());//协议
 System.out.println(url.getHost());//主机 IP
 System.out.println(url.getPort());//端口
 System.out.println(url.getPath());//文件地址
 System.out.println(url.getFile());//全路径
 System.out.println(url.getQuery());//参数

网络资源下载:

 /*URL下载网络资源*/
 public class Down {
     public static void main(String[] args) throws Exception {
         //1.下载地址
         URL url = new URL("https://p2.music.126.net/Sa3hFOiQWjsHg2W_8nSI0g==/109951166154251386.jpg?param=50y50");
         //2.连接资源 HTTP
         HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
         InputStream inputStream = urlConnection.getInputStream();
         FileOutputStream fos = new FileOutputStream("Url_Down.jpg");
         byte[] buffer = new byte[1024];
         int len;
         while ((len=inputStream.read(buffer))!=-1) {
             fos.write(buffer,0,len);
         }
         fos.close();
         inputStream.close();
         urlConnection.disconnect();//断开连接
     }
 }



posted @ 2021-08-17 14:04  miku_moe  阅读(34)  评论(0)    收藏  举报