• Java网络编程实践


    网络编程的目的

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

    想要达到这个效果需要什么:
    1. 如何准确的定位网络上的第一台主机 192.168.16.124:端口,定位到这个计算机上的某个资源。 2. 找到这个主机,如何传输数据?

    javaweb:网页编程 B/S
    网络编程:TCP/IP C/S

    网络通信的要素

    如何实现网络的通信?

    通信双方地址:

    • IP
    • 端口号
    • 192.168.16.124:5900

    规则:网络通信规则

    TCP/IP 参考模型:

    小结:
    1.网络编程中有两个主要问题

    如何准确的定位到网络上的一台或多台主机
    找到主机之后如何进行通信

    2.网络编程中的要素

    IP和端口号
    网络通信协议  udp、tcp

    3.万物皆对象

    IP

    ip地址:InetAddress

    • 唯一定位一台网络上的计算机
    • 127.0.0.1: 本机localhost
    • IP地址的分类

    ipv4/ipv6

    ==IPV4== 127.0.0.1, 4个字节组成。0-255 ==IPV6== 128位。8个无符号整数(包含abcde),例如:

    2001:0bb2:a3e1:0015:0000:0000:1aaa:1312  
    

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

    ABCD类IP地址(百度查看) 192.168.xx.xx专门给组织内部使用的

    • 域名

    IP:www.vip.com

    public static void main(String[] args) {
        try {
            //查询本机地址
            InetAddress inetAddress1 = InetAddress.getByName("127.0.0.1");
            System.out.println(inetAddress1);
            InetAddress inetAddress3 = InetAddress.getByName("localhost");
            System.out.println(inetAddress3);
            InetAddress inetAddress4 = InetAddress.getLocalHost();
            System.out.println(inetAddress4);
    
        //查询网站ip地址
        InetAddress inetAddress2 = InetAddress.getByName("www.baidu.com");
        System.out.println(inetAddress2);
    
    
        //常用方法
        //System.out.println(inetAddress2.getAddress());//一串字符
        System.out.println(inetAddress2.getCanonicalHostName());//规范的名字
        System.out.println(inetAddress2.getHostAddress());//ip
        System.out.println(inetAddress2.getHostName());//域名,或者自己电脑的名称
    
    } catch (UnknownHostException e) {
        e.printStackTrace();
    }
    

    }

    端口

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

    • 不同的进程有不同的端口号!用来区分软件!
    • 被规定0-65535
    • TCP,UDP : 65535*2 单个协议下,端口号不能冲突
    • 端口分类

    公用端口:0-1023

    HTTP:80
    HTTPS:443
    FTP:21
    Telent:23

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

    Tomcat: 8080
    MySQL:3306
    Oracle:1521

    动态、私有:49512-65535

    netstat -ano # 查看所有的端口
    netstat -ano|findstr "5900" # 查看指定的端口
    tasklist|findstr "8696" # 查看指定端口的进程
    Ctrl + shift + ESC 快捷打开任务管理器

    public static void main(String[] args) {
        InetSocketAddress socketAddress1 = new InetSocketAddress("127.0.0.1", 8080);
        InetSocketAddress socketAddress2 = new InetSocketAddress("localhost", 8080);
        System.out.println(socketAddress1);
        System.out.println(socketAddress2);
    
    System.out.println(socketAddress1.getAddress());
    System.out.println(socketAddress1.getHostName());//地址
    System.out.println(socketAddress1.getPort());//端口
    

    }

    通信协议

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

    问题:非常复杂

    大事化小:分成!

    TCP/IP协议簇

    重要:

    • TCP:用户传输协议
    • UDP:用户数据报协议

    TCP-UDP 对比:

    TCP:好比打电话

    连接、稳定
    三次握手、四次挥手

    三次握手可以理解为:

    A:你瞅啥
    B:瞅你咋地
    A:干一场
    

    A触发B,B回应,A再响应
    四次挥手可以理解为:

    A: 我要走了
    B:你真的要走了吗?
    B:你真的真的要走了吗?
    A:我真的要走了!
    

    A触发B,B回应,B再次确认,A再响应

    客户端、服务端
    传输完成、释放连接、效率低

    UDP:好比发短信

    不连接,不稳定
    客户端、服务端:没有明确的界限
    不管有没有准备好,都可以发给你

    TCP

    客户端:

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

    /*
    客户端
    */
    public class TCPClientDemo01 {

    public static void main(String[] args) {
    
        Socket socket = null;
        OutputStream os = null;
        try {
            //1.要知道服务器地址
            InetAddress serverIP = InetAddress.getByName("127.0.0.1");
            int port = 9999;
            //2.创建一个socket连接
            socket = new Socket(serverIP, port);
            //3.发送消息IO流
            os = socket.getOutputStream();
            os.write("你好!".getBytes());
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException 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();
                }
            }
        }
    }
    

    }

    服务端:

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

    /*
    服务端
    */
    public class TCPServerDemo01 {
    public static void main(String[] args) {

        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream is = null;
        ByteArrayOutputStream baos = null;
    
        try {
            //1.服务端得有一个地址
            serverSocket = new ServerSocket(9999);
            //2.等待客户端连接过来
            socket = serverSocket.accept();
            //3.读取客户端的消息
            is = socket.getInputStream();
            //方式一:
    

    // byte[] buffer = new byte[1024];
    // int len;
    // while((len=is.read(buffer)) != -1){
    // String msg = new String(buffer, 0, len);
    // System.out.println(msg);
    // }
    //方式二:管道流
    baos = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int len;
    while((len = is.read(buffer)) != -1){
    baos.write(buffer, 0, len);
    }

            System.out.println(baos.toString());
    
    
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            //关闭资源
            //按以下顺序关闭
    

    // baos.close();
    // is.close();
    // socket.close();
    // serverSocket.close;
    if (baos != null){
    try {
    baos.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    if(is != null){
    try {
    is.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();
    }
    }
    }
    }
    }

    分析:先运行服务端,再运行客户端,然后服务端会收到"你好"字符串。

    将服务端代码改为持续监听——放入到while循环中。

                while (true){
                    //2.等待客户端连接过来
                    socket = serverSocket.accept();
                    //3.读取客户端的消息
                    is = socket.getInputStream();
                    //方式一:
    //            byte[] buffer = new byte[1024];
    //            int len;
    //            while((len=is.read(buffer)) != -1){
    //                String msg = new String(buffer, 0, len);
    //                System.out.println(msg);
    //            }
                    //方式二:管道流
                    baos = new ByteArrayOutputStream();
                    byte[] buffer = new byte[1024];
                    int len;
                    while((len = is.read(buffer)) != -1){
                        baos.write(buffer, 0, len);
                    }
    
                System.out.println(baos.toString());
            }
    

    TCP流程:

    客户端:

    1. 连接服务器 Socket
    2. 发送消息

    服务器:

    1. 建立服务的端口 ServerSocket
    2. 等待用户的连接 accept()
    3. 接收用户消息

    TCP文件上传

    客户端:

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

    /*
    客户端
    */

    public class TCPClientDemo02 {
    public static void main(String[] args) throws Exception {
    //1.创建一个socket连接
    Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);
    //2.创建一个输出流
    OutputStream os = socket.getOutputStream();

        //3.文件流
        FileInputStream fis = new FileInputStream(new File("testpic.png"));
        //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());
    
        //5.关闭资源
        baos.close();
        inputStream.close();
        fis.close();
        os.close();
        socket.close();
    
    }
    

    }

    服务端:

    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 TCPServerDemo02 {
    public static void main(String[] args) throws Exception {
    //1.创建服务
    ServerSocket serverSocket = new ServerSocket(9000);
    //2.监听客户端的连接
    Socket socket = serverSocket.accept();//阻塞监听,会一直等待客户端连接
    //3.获取输入流
    InputStream is = socket.getInputStream();

        //4.文件输出
        FileOutputStream fos = new FileOutputStream(new File("receive.png"));
        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();
    
    }
    

    }

    UDP

    发送消息

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

    public class UDPClientDemo01 {

    public static void main(String[] args) throws Exception {
        //1.建立一个socket
        DatagramSocket socket = new DatagramSocket();
    
        //2.建个包
        String msg = "你好啊,服务器!";
    
        //发送给谁
        InetAddress localhost = InetAddress.getByName("localhost");
        int port = 9090;
        //数据、数据的长度起始、要发送给谁
        DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, port);
    
        //3.发送包
        socket.send(packet);
    
        //4.关闭流
        socket.close();
    }
    

    }

    接收端:

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

    //还是要等待客户端的连接 public class UDPServerDemo01 { public static void main(String[] args) throws Exception { //开放端口 DatagramSocket socket = new DatagramSocket(9090); //接收数据包 byte[] buffer = new byte[1024]; DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);

        socket.receive(packet);//阻塞接收
    
    //读取数据
    System.out.println(packet.getAddress().getHostAddress());
    System.out.println(new String(packet.getData(), 0, packet.getLength()));
    //关闭连接
    socket.close();
    

    }

    }

    循环发送消息

    循环发送消息

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

    public class UDPSenderDemo01 {
    public static void main(String[] args) throws Exception {
    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("bye")){
                break;
            }
        }
    
        socket.close();
    }
    

    }

    循环接收消息

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

    public class UDPReceiveDemo01 {
    public static void main(String[] args) throws Exception {
    DatagramSocket socket = new DatagramSocket(6666);

        while(true){
            byte[] container = new byte[1024];
            DatagramPacket packet = new DatagramPacket(container, 0, container.length);
            socket.receive(packet);//阻塞式接收包裹
    
            //断开连接
            byte[] data = packet.getData();
            String receiveData = new String(data, 0, data.length);
    
            System.out.println(receiveData);
    
            if (receiveData.equals("bye")){
                break;
            }
    
        }
    
        socket.close();
    
    }
    

    }

    实现简易聊天

    发送功能

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

    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 (SocketException e) {
            e.printStackTrace();
        }
    
    }
    
    @Override
    public void run() {
    
        while(true) {
            try {
                String 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("bye")) {
                    break;
                }
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        socket.close();
    }
    

    }

    接收功能

    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 receiveData = new String(data, 0, data.length);
    
                System.out.println(msgFrom + ":" + receiveData);
    
                if (receiveData.equals("bye")){
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    
        socket.close();
    }
    

    }

    学生窗口:

    public class TalkStudent {
        public static void main(String[] args) {
            new Thread(new TalkSend(7777, "localhost", 9999)).start();
            new Thread(new TalkReceive(8888, "老师")).start();
        }
    }
    

    教师窗口:

    public class TalkTeacher {
        public static void main(String[] args) {
            new Thread(new TalkSend(5555, "localhost", 8888)).start();
            new Thread(new TalkReceive(9999, "学生")).start();
        }
    }
    

    URL

    统一资源定位符:定位资源的,定位互联网上的某一个资源 、

    • getPath: 文件地址
    • getProtocol: 协议
    • getHost: 主机ip
    • getPort: 端口
    • getFile: 全路径
    • getQuery: 参数
  • 相关阅读:
    python 并发编程 多线程 event
    python 并发编程 多线程 定时器
    python 并发编程 多线程 信号量
    linux top 查看CPU命令
    python 并发编程 多线程 GIL与多线程
    python 并发编程 多线程 死锁现象与递归锁
    python 并发编程 多线程 GIL与Lock
    python GIL全局解释器锁与互斥锁 目录
    python 并发编程 多线程 GIL全局解释器锁基本概念
    执行python程序 出现三部曲
  • 原文地址:https://www.cnblogs.com/kylinxxx/p/13299737.html
Copyright © 2020-2023  润新知