网络编程(基础)

本文概述了网络编程的基础,包括计算机网络、网络协议的作用,以及IP地址、端口号、TCP/IP模型。重点讲解了如何定位主机、通信要素(如TCP和UDP的区别),以及IP分类、InetAddress操作、端口范围和通信协议的实际应用,如TCP连接示例和UDP短信发送。
摘要由CSDN通过智能技术生成

网络编程

1、概述(自行百度)

  • 计算机网络:

  • 网络协议:就比如说我们规定普通话为通用交流语言,这就是一种协议

  • 网络编程的目的:数据交换,通信

2、网络通信的要素

  • IP:定位到网络中的某台计算机

  • 端口号:定位到计算机中的某个应用

  • TCP/IP参考模型:(百度上都有)

总结:

1、网络编程中有两个主要问题

a.如何准确的定位到网络上的一台或者多台主机

b.找到主机后如何进行通信

2、网络编程中的要素:IP、端口号、网络通信协议(tcp、udp)

3、万物皆对象

3、IP地址

3.1 分类

  • ipv4 / ipv6:

    ipv4:由4个字节组成,0-255, 总共42亿个,如下:

    192.168.1.56

    ipv6:128位,由8个无符号整数组成,如下:

    2408:8207:7895:8e10:bab1:b5ed:7ec6:c2a7

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

    ABCD类地址:

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

  • 域名:

3.2 InetAddress对象

  • 获取本机IP

//获取本机地址
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(localHost);
InetAddress byName = InetAddress.getByName("localhost");
System.out.println(byName);
System.out.println(InetAddress.getByName("127.0.0.1"));
  • 获取远程IP

//获取百度IP
InetAddress baiduIP = InetAddress.getByName("www.baidu.com");

4、端口

  • 端口号的范围:0-65535,TCP和UDP都是这个范围

  • 常见端口号:HTTP 80、HTTPS 443、FTP 21、Telent 23、Tomcat 8080、Mysql 3306、Oracle 1521

  • 端口分类:

    • 公有端口:0-1023

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

    • 动态、私有:49152-65535`

      netstat -ano #查看所有的端口

      netstat -ano | grep "1234" #查看指定端口

5、通信协议

  • 协议:一种约定,比如普通话就是一种交流的协议

  • TCP与UDP:

    1、TCP:面相链接、可靠传输、三次握手、四次挥手、点到点传输、数据传输按序到达且不会重复和丢包、效率较低、面相字符传输、首部开销20-60字节

    2、UDP:无连接、不可靠、传输数据无序且可能会丢包,、支持一对一,一对多,多对一,多对多等、面向报文传输、首部开销8个字节

  • 三次握手:

    1. 客户端向服务器发送带有SYN标志的数据包(服务器确认客户端的发送和自己接收正常)

    2. 服务器向客户端发送带有ACK/SYN标志的数据包(客户端确认自己的发送和接收正常,确认服务器的发送和接收正常)

    3. 客户端向服务器发送带有ACK标志的数据包(服务器确认自己的发送正常和客户端的接收正常)

  • 四次挥手:

    1. 客户端向服务器发送带一个FIN,用来关闭客户端到服务器的数据传送

    2. 服务器接收到FIN并发回一个ack,确认序号为收到的序号加1,和SYN一样,一个FIN将占用一个序号

    3. 服务器关闭与客户端的链接,发送一个FIN给客户端

    4. 客户端发回ack报文确认,并将确认序号设置为接受序号加1

6、TCP

  • 客户端:

    1. 获取服务器的IP和端口号

    2. 创建Socket链接

    3. 通过IO流向服务器发送数据

    //获取服务器的IP和端口号
    InetAddress address = InetAddress.getByName("127.0.0.1");
    int port = 9090;
    //创建Socket链接
    socket = new Socket(address, port);
    //发送消息通过IO流
    outputStream = socket.getOutputStream();
    outputStream.write("Hello world!".getBytes());

  • 服务器

    1. 设置服务器端口号

    2. 监听客户端链接(accept)

    3. 获取客户端信息

    4. 处理信息

    //设置服务端端口号为9090
    serverSocket = new ServerSocket(9090);
    while (true){
        //监听客户端链接
        socket = serverSocket.accept();
        //获取客户端的消息
        inputStream = socket.getInputStream();
    /*
    //处理inputstream
    byte[] buffer = new byte[1024];
    int len;
    while((len = inputStream.read(buffer)) != -1){
        String msg = new String(buffer, 0, len);
        System.out.println(msg);
    }*/
        //通过管道流处理inputstream
        byteArrayOutputStream = new ByteArrayOutputStream();
        byte[] bytes = new byte[1024];
        int len;
        while((len = inputStream.read(bytes)) != -1){
            byteArrayOutputStream.write(bytes, 0, len);
        }
        System.out.println(byteArrayOutputStream.toString());
    }
  • 文件上传

    服务器端

    public class TCPDownload {
    ​
        private static ServerSocket serverSocket = null;
        private static Socket socket = null;
        private static InputStream inputStream = null;
        private static FileOutputStream fileOutputStream = null;
    ​
        private static OutputStream outputStream = null;
    ​
        public static void main(String[] args) {
            try {
                serverSocket = new ServerSocket(8888);
                socket = serverSocket.accept();
                inputStream = socket.getInputStream();
                fileOutputStream = new FileOutputStream(new File("receive.jpg"));
    ​
                byte[] buffer = new byte[1024];
                int len;
                while((len = inputStream.read(buffer)) != -1){
                    fileOutputStream.write(buffer, 0, len);
                }
    ​
                //当服务器接受完毕后,告知客户端接受完毕
                outputStream = socket.getOutputStream();
                outputStream.write("upload success!".getBytes());
    ​
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                //关闭资源(自己封装的关闭资源的工具类)
                CloseResource.closeResource(fileOutputStream);
                CloseResource.closeResource(inputStream);
                CloseResource.closeResource(socket);
                CloseResource.closeResource(serverSocket);
            }
    ​
        }
    }

    客户端

    public class TCPUpload {
    ​
        private static Socket socket = null;
    ​
        private static OutputStream outputStream = null;
    ​
        private static FileInputStream fileInputStream = null;
    ​
        private static InputStream inputStream = null;
    ​
        private static ByteArrayOutputStream byteArrayOutputStream = null;
    ​
        public static void main(String[] args) {
            try {
                //获取服务器IP和端口号,这里我们使用本机作为服务器
                InetAddress localhost = InetAddress.getByName("localhost");
                int port = 8888;
                socket = new Socket(localhost, port);
                outputStream = socket.getOutputStream();
    ​
                //读取文件
                fileInputStream = new FileInputStream("/home/lpf/图片/man_paint_sky_129261_1920x1080.jpg");
                //写文件
                byte[] buffer = new byte[1024];
                int len;
                while((len = fileInputStream.read(buffer)) != -1){
                    outputStream.write(buffer, 0, len);
                }
    ​
                //通知服务器我已经传送完毕了
                socket.shutdownOutput();     //如果不写这句代码,客户端和服务器都会处在一个无限等待的状态
    ​
                //获取服务端的通知
                inputStream = socket.getInputStream();
                byteArrayOutputStream = new ByteArrayOutputStream();
                byte[] bytes = new byte[1024];
                int length;
                while((length = inputStream.read(bytes)) != -1){
                    byteArrayOutputStream.write(bytes, 0, length);
                }
                System.out.println(byteArrayOutputStream.toString());
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                //关闭资源的工具类
                CloseResource.closeResource(byteArrayOutputStream);
                CloseResource.closeResource(inputStream);
                CloseResource.closeResource(fileInputStream);
                CloseResource.closeResource(outputStream);
                CloseResource.closeResource(socket);
            }
        }
    }
  • Tomcat用来做服务端(了解即可)

7、UDP

比如发短信的时候,我不需要与对方进行链接,只需要知道对方的地址即可

  • 发送端

public class UDPClient {
​
    private static DatagramSocket datagramSocket = null;
​
    private static DatagramPacket datagramPacket = null;
​
    public static void  main(String[] args) {
        try {
            //创建一个Socket
            datagramSocket = new DatagramSocket();
​
            //获取服务端的IP和端口号
            InetAddress address = InetAddress.getByName("127.0.0.1");
            int port = 9090;
            //设置发送的消息
            String msg = "Hello world!";
            //创建数据包
            datagramPacket = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, address, port);
            //发送包
            datagramSocket.send(datagramPacket);
​
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            CloseResource.closeResource(datagramPacket);
            CloseResource.closeResource(datagramSocket);
        }
    }
}
  • 接收端

public class UDPServer {
​
    private static DatagramSocket datagramSocket = null;
​
    private static DatagramPacket datagramPacket = null;
​
    public static void main(String[] args) {
        try {
            datagramSocket = new DatagramSocket(9090);
            byte[] buffer = new byte[1024];
            datagramPacket = new DatagramPacket(buffer, 0, buffer.length);
            datagramSocket.receive(datagramPacket);
            //输出包中的信息
            System.out.println(datagramPacket.getAddress());
            System.out.println(new String(datagramPacket.getData(), 0, datagramPacket.getLength()));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            CloseResource.closeResource(datagramPacket);
            CloseResource.closeResource(datagramSocket);
        }
    }
}
  • 使用UDP实现端到端的聊天Demo(使用多线程,参照上面代码)

发送方:

public class UDPSend implements Runnable {

    private DatagramSocket socket = null;

    private BufferedReader reader = null;

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

    public UDPSend(int fromPort, int toPort, String toIP) {
        this.fromPort = fromPort;
        this.toPort = toPort;
        this.toIP = toIP;

        try {
            socket = new DatagramSocket(this.fromPort);
            reader = new BufferedReader(new InputStreamReader(System.in));
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

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

接受方:

public class UDPRevice implements Runnable {

    private DatagramSocket socket = null;

    private int fromPort;
    private String myName;

    public UDPRevice(int fromPort, String myName) {
        this.fromPort = fromPort;
        this.myName = myName;

        try {
            socket = new DatagramSocket(fromPort);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        while (true){
            try{
                byte[] data = new byte[1024];
                DatagramPacket packet = new DatagramPacket(data, 0, data.length);
                socket.receive(packet);
                byte[] msg = packet.getData();
                String receiveData = new String(msg, 0, msg.length);
                System.out.println(myName + ":" + receiveData);

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

最后通代理模式创建这两个线程从而实现聊天功能:

public class TalkStudent {

    public static void main(String[] args) {
        new Thread(new UDPSend(7777, 9999, "127.0.0.1")).start();

        new Thread(new UDPRevice(8888, "Teacher")).start();
    }
}

8、URL

  • 统一资源定位符

  • 组成:

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

  • 下载网络资源

public class DownloadURL {

    private static HttpURLConnection connection = null;
    private static InputStream inputStream = null;
    private static FileOutputStream stream = null;

    public static void main(String[] args) {
        try {
            URL url = new URL("https://m701.music.126.net/20211019180445/4bd82af769d78f834d6c47666191b513/jdyyaac/obj/w5rDlsOJwrLDjj7CmsOj/11255785312/2660/3c23/c8a7/9d1782c01855c2d620a6afcbdfab6bd9.m4a");
            //链接资源
            connection = (HttpURLConnection)url.openConnection();
            //获取流并下载
            inputStream = connection.getInputStream();
            stream = new FileOutputStream("f.m4a");
            byte[] data = new byte[1024];
            int len;
            while((len = inputStream.read(data)) != -1){
                stream.write(data, 0, len);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            connection.disconnect();
            CloseResource.closeResource(inputStream);
            CloseResource.closeResource(stream);
        }

    }
}

笔记是按照B站狂神的视频写的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值