网络编程


1.1 概述


打电话:TCP链接


发短信:UDP链接


 


计算机网络:


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


 


网络编程的目的:


无线电台...传播交流信息,数据交换。通信。


 


想要达到这个效果需要什么:


  1. 如何准确的定位网络上的一台主机 127.0.0.1:端口,定位到这个计算机上的某个资源

  2. 找到了这个主机,如何传输数据?


 


javaWeb:网页编程  B/S架构


网络编程:TCP/IP  C/S架构


 


1.2 网络通信的要素


如何实现网络的通信?


通信双方地址:


  • ip

  • 端口号

  • 127.0.0.1:8080


规则:网络通信的协议


TCP/IP参考模型:



 


1.3 IP


ip地址:InetAddress


  • 唯一定位一台计算机

  • 127.0.0.1:本机(localhost)

  • ip地址分类

    • ABCD类地址

    • 192.168.xx.xx:专门给组织内部使用的

    • IPV4:127.0.0.1,4个字节组成。0~255,42亿;有30亿都在北美;亚洲只有4亿。2011年就用完了。

    • IPV6:128位。8个无符号整数。

      2021:0ba22:aaaa:0339:2222:9090:b9b0:1234
    • ipv4 / ipv6

    • 公网(互联网)- 私网(局域网)

  • 域名:记忆IP问题!

    • IP:www.baidu.com


 


1.4 端口


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


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

  • 被规定 0-65535

  • TCP、UDP:单个协议下,端口号不能冲突。

  • 端口分类

    • Tomcat:8080

    • MySQL:3306

    • Oracle:1521

    • HTTP:80

    • HTTPS:443

    • FTP:21

    • Telent:23

    • 公有端口 0-1023

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

    • 动态、私有:49152~65535

      netstat -ano # 查看所有端口;
      netstat -ano|findstr "端口号" # 查看指定的端口

 


1.5 通信协议


协议:就是一种约定。


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


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


重要:


  • TCP:用户传输协议

  • UDP:用户数据报协议


出名的协议:


  • TCP:

  • IP:网络互连协议


 


TCP udp 对比


TCP:打电话


  • 链接,稳定

  • 三次握手 四次挥手




  • 客户端、服务端

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


UDP:发短信


  • 不连接,不稳定

  • 客户端、服务端:没有明确的界限

  • 不管有没有准备好,都可以发给你...

  • DDOS:洪水攻击!(饱和攻击)


 


1.6 TCP


客户端


  1. 连接服务器 Socket

  2. 发送消息


package com.zhang;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

public class InternetTeat {
    public static void main(String[] args) {
        InetAddress addressIP = null;
        Socket socket = null;
        OutputStream os = null;
        try {
            //要知道服务器的地址、端口号
            addressIP = InetAddress.getByName("127.0.0.1");
            int port = 9999;
            //创建一个socket链接
            socket = new Socket(addressIP, port);
            //发送消息 IO 流
            os = socket.getOutputStream();
            os.write("这是网络编程".getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(os != null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 


服务器


  1. 建立服务的端口 ServerSocket

  2. 等待用户的链接 accept

  3. 接收用户的消息


package com.zhang;

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

public class ServiceSocketTest {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream stream = null;
        ByteArrayOutputStream baos = null;
        try {

            //需要有一个地址
            serverSocket = new ServerSocket(9999);
            //等待客户端链接
            socket = serverSocket.accept();
            //接收客户端消息
            stream = socket.getInputStream();

            //管道流
            baos = new ByteArrayOutputStream();
            byte[] buff = new byte[1024];
            int len;
            while ((len = stream.read(buff)) != -1) {
                //到字节数组中去写,长度从0~len
                baos.write(buff, 0, len);
            }

            System.out.println(baos.toString());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (baos != null) {
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (serverSocket != null) {
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 


文件上传


客户端:


package com.zhang.lesson02;

import java.io.*;
import java.net.Socket;

public class SocketTest {
    public static void main(String[] args) throws Exception {
        //1.创建链接
        Socket socket = new Socket("127.0.0.1", 2000);
        //2.创建输出流
        OutputStream os = socket.getOutputStream();
        //3.读取文件_文件流
        FileInputStream fis = new FileInputStream(new File("tupian.jpg"));
        //4.写出文件
        byte[] bytes = new byte[1024];
        int len;
        while ((len=fis.read(bytes))!=-1){
            os.write(bytes,0,len);
        }

        //通知服务器,我已经传输完了
        socket.shutdownOutput();

        //确定服务器接收完毕,才能关闭
        InputStream is = socket.getInputStream();
        //创建管道流
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buff = new byte[1024];
        int len2;
        while ((len2=is.read(buff))!=-1){
            baos.write(buff, 0, len2);
        }

        System.out.println(baos.toString());
        //5.关流
        baos.close();
        is.close();
        fis.close();
        os.close();
        socket.close();
    }
}

服务端:


package com.zhang.lesson02;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerSocketTest {
    public static void main(String[] args) throws Exception {
        //1.创建服务
        ServerSocket serverSocket = new ServerSocket(2000);
        //2.监听客户连接
        Socket accept = serverSocket.accept();//客户端没连接,则会一直等待,一旦连接,则立即失效
        //3.接收客户端消息
        InputStream is = accept.getInputStream();

        //4.输出文件,使用文件输出流
        FileOutputStream fos = new FileOutputStream(new File("wenjian.jpg"));
        byte[] bytes = new byte[1024];
        int len;
        while ((len=is.read(bytes))!=-1){
            fos.write(bytes, 0, len);
        }

        //通知客户端,我接收完毕了
        OutputStream os = accept.getOutputStream();
        os.write("我接收完毕,你可以关闭了".getBytes());
        //5.关流
        os.close();
        fos.close();
        is.close();
        accept.close();
    }
}

 


UDP


UDP不存在服务器


发送消息


发送端


package com.zhang.lesson03;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class DataGramSocketTest {
    public static void main(String[] args) throws Exception {
        //创建连接
        DatagramSocket socket = new DatagramSocket();
        String msg = "Hello Word";
        //创建包
        //参数一:要输出的包,参数二:开始长度:参数三:结束长度 参数四:发送的地址 参数五:端口号
        DatagramPacket packet = new DatagramPacket(msg.getBytes(),0 ,msg.getBytes().length,InetAddress.getByName("127.0.0.1"),8080);
        //输出包
        socket.send(packet);
        //关流
        socket.close();
    }
}

接收端


package com.zhang.lesson03;

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class DataGramSocketDemo {
    public static void main(String[] args) throws Exception {
        //开放端口
        DatagramSocket socket = new DatagramSocket(8080);
        //接收数据包
        byte[] buff = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buff, 0, buff.length);
        //接收数据
        socket.receive(packet);
        System.out.println(packet.getAddress());

        String s = new String(packet.getData(),0,packet.getLength());
        System.out.println(s);
        //关流
        socket.close();
    }
}

单方面发送消息


package com.zhang.lesson04;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UdpSenderSocket {
    public static void main(String[] args) throws Exception {
        //创建连接
        DatagramSocket socket = new DatagramSocket(8888);

        //从控制台读数据
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
       while (true){
           //读取当前行
           String data = reader.readLine();
           byte[] buff = data.getBytes();

           DatagramPacket packet = new DatagramPacket(buff,0,buff.length, InetAddress.getByName("localhost"),6666);

           socket.send(packet);

           if (data.equals("bye")){
               break;
           }
       }
        socket.close();
    }
}

package com.zhang.lesson04;

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UdpReaderSocket {
    public static void main(String[] args) throws Exception {
        DatagramSocket socket = new DatagramSocket(5555);
        while (true){
            byte[] container = new byte[1024];
            DatagramPacket packet = new DatagramPacket(container, 0, container.length);
            socket.receive(packet);

            System.out.println(new String(packet.getData(),0,packet.getLength()));

            if(packet.equals("bye")){
                break;
            }
        }
        socket.close();
    }
}

 


双线程实现双方发送消息


发送线程:


package com.zhang.lesson05;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;

public class TalkSend implements Runnable {
    DatagramSocket socket = null;
    BufferedReader reader = null;

    private int fromPort;
    private String toIP;
    private int toPort;

    public TalkSend(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 (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        while (true) {
            try {
                String readLine = reader.readLine();
                byte[] buff = readLine.getBytes();
                DatagramPacket packet = new DatagramPacket(buff, 0, buff.length, new InetSocketAddress(this.toIP, this.toPort));
                socket.send(packet);
                if (packet.equals("bye")) {
                    break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        socket.close();
    }
}

接收线程:


package com.zhang.lesson05;

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

public class TalkReceive implements Runnable {

    DatagramSocket socket = null;
    private int port;
    private String msgFrom;

    public TalkReceive(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[] container = new byte[1024];
                DatagramPacket packet = new DatagramPacket(container, 0, container.length);
                socket.receive(packet);

                byte[] data = packet.getData();
                String datas = new String(data, 0, packet.getLength());
                System.out.println(msgFrom + ":" + datas);

                if (packet.equals("bye")) {
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        socket.close();
    }
}

开启双线程


package com.zhang.lesson05;

public class TalkStudent {
    public static void main(String[] args) {
        //开启两个线程
        new Thread(new TalkSend(4444,"localhost",9999)).start();
        new Thread(new TalkReceive(2222,"老师")).start();
    }
}

package com.zhang.lesson05;

public class TalkTeacher {
    public static void main(String[] args) {
        //开启两个线程
        new Thread(new TalkSend(6666,"localhost",2222)).start();
        new Thread(new TalkReceive(9999,"学生")).start();
    }
}

 


URL


连接下载:


package com.zhang.lesson06;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class TestUrl {
    public static void main(String[] args) throws Exception{
        //创建 URL 连接
        URL url = new URL("https://m701.music.126.net/20210327012415/e8ea2cf75d56d87dea92dd0bed342bca/jdyyaac/560b/5208/0253/aa0c399dc3eb148e2335591da4c6e6ab.m4a");
        //打开链接
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
        //接收文件
        InputStream inputStream = urlConnection.getInputStream();
        //输出文件
        FileOutputStream fos = new FileOutputStream(new File("music.m4a"));
        //缓冲区
        byte[] buff = new byte[1024];
        int len;
        while ((len=inputStream.read(buff)) != -1){
            fos.write(buff, 0, len);
        }
        //关流
        fos.close();
        inputStream.close();
        urlConnection.disconnect();
    }
}