zoukankan      html  css  js  c++  java
  • Java学习笔记 第十章 网络编程

    JAVA学习笔记第十章

    10.网络编程

    10.1引入

    image-20210601115242973

    image-20210601115608318

    image-20210601120234610

    image-20210601120349735

    image-20210601120808343

    TCP建立连接:

    image-20210601120613329

    释放连接:

    image-20210601120654942

    image-20210601120755773

    image-20210601120741148

    10.2InetAddress & InetSocketAddress

    image-20210601155342380

    image-20210601155212394

    InetAddress有两个方法:

    image-20210601155313663

    InetSocketAddress封装了ip和端口号

    image-20210601155731764

    10.3套接字

    image-20210601161300976

    10.4TCP通信

    10.4.1客户端和服务端通信

    客户端发送一句话到服务器

    public class TestClient { // 客户端
        public static void main(String[] args) throws IOException {
            // 创建套接字:指定服务器ip和端口号
            Socket s = new Socket("127.0.0.1", 8888);
            //对程序员来说,向外发送数据 感受 --》 利用输出流;
            OutputStream os = s.getOutputStream();
            DataOutputStream dos = new DataOutputStream(os);
            //利用OutputStream就可以向外发送数据流,但是没有直接发送String的方法
            //所以我们又在OutputStream外面套了一个处理流:DataOutputStream
            dos.writeUTF("你好");
    
            // 关闭流 + 关闭网络资源
            dos.close();
            os.close();
            s.close();
    
        }
    }
    
    public class TestServer { // 服务器
        public static void main(String[] args) throws IOException {
            // 1.创建套接字:指定服务器的端口
            ServerSocket ss = new ServerSocket(8888);
            // 2.等待客户端发送来的信息
            Socket s = ss.accept(); // 阻塞方法:等待客户端的数据,什么时候收到数据,什么时候程序继续向下执行
            // 3.accept返回值为Socket,这个Socket其实就是客户端的Socket
            //接到这个Socket之后,客户端和服务端才真正产生了连接,才真正可以通信了
            //感受到的操作流
            InputStream is = s.getInputStream();
            DataInputStream dis = new DataInputStream(is);
    
            // 4.读取客户端发来的数据
            String str = dis.readUTF();
            System.out.println("客户端发来的数据为:" + str);
    
            // 5.关闭流 + 关闭网络资源
            dis.close();
            is.close();
            s.close();
        }
    }
    

    先开服务器,然后开启客户端,在服务器端可以看到控制台打印出客户端发来的数据为:你好

    如果先开客户端,会报出连接被拒绝的错误

    服务端也可以向客户端发送信息

    public class TestServer { // 服务器
        public static void main(String[] args) throws IOException {
            // 1.创建套接字:指定服务器的端口
            ServerSocket ss = new ServerSocket(8888);
            // 2.等待客户端发送来的信息
            Socket s = ss.accept(); // 阻塞方法:等待客户端的数据,什么时候收到数据,什么时候程序继续向下执行
            // 3.accept返回值为Socket,这个Socket其实就是客户端的Socket
            //接到这个Socket之后,客户端和服务端才真正产生了连接,才真正可以通信了
            //感受到的操作流
            InputStream is = s.getInputStream();
            DataInputStream dis = new DataInputStream(is);
    
            // 4.读取客户端发来的数据
            String str = dis.readUTF();
            System.out.println("客户端发来的数据为:" + str);
    
            // 6.向客户端发送数据
            OutputStream os = s.getOutputStream();
            DataOutputStream dos = new DataOutputStream(os);
            dos.writeUTF("服务器端接收到你的消息");
    
            // 5.关闭流 + 关闭网络资源
            dos.close();
            os.close();
            dis.close();
            is.close();
            s.close();
        }
    }
    
    
    public class TestClient { // 客户端
        public static void main(String[] args) throws IOException {
            // 创建套接字:指定服务器ip和端口号
            Socket s = new Socket("127.0.0.1", 8888);
            //对程序员来说,向外发送数据 感受 --》 利用输出流;
            OutputStream os = s.getOutputStream();
            DataOutputStream dos = new DataOutputStream(os);
            //利用OutputStream就可以向外发送数据流,但是没有直接发送String的方法
            //所以我们又在OutputStream外面套了一个处理流:DataOutputStream
            dos.writeUTF("你好");
    
            //客户端接收服务器的数据
            InputStream is = s.getInputStream();
            DataInputStream dis = new DataInputStream(is);
            String str = dis.readUTF();
            System.out.println("服务器对我说:" + str);
    
            // 关闭流 + 关闭网络资源
            dis.close();
            is.close();
            dos.close();
            os.close();
            s.close();
    
        }
    }
    
    

    10.4.2登录验证

    模拟登录时输入账号密码,并进行验证的过程

    public class User implements Serializable {
        private static final long serialVersionUID = 6158646660109509935L;
        private String name;
        private String pwd;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPwd() {
            return pwd;
        }
    
        public void setPwd(String pwd) {
            this.pwd = pwd;
        }
    
        public User(String name, String pwd) {
            this.name = name;
            this.pwd = pwd;
        }
    }
    
    

    需要实现Serializable接口,并且通过idea创建UID

    public class Client {  //客户端
        public static void main(String[] args) throws IOException {
            // 1.创建套接字
            Socket s = new Socket("127.0.0.1", 8888);
    
            // 2.录入账号和密码
            Scanner sc = new Scanner(System.in);
            System.out.println("username:");
            String name = sc.next();
            System.out.println("password:");
            String pwd = sc.next();
    
            // 3.将账号和密码封装为一个User对象
            User user = new User(name, pwd);
    
            // 4.向外发送对象,利用输出流
            OutputStream os = s.getOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(os);
            oos.writeObject(user);
    
            // 5.接收服务端发送的结果
            InputStream is = s.getInputStream();
            DataInputStream dis = new DataInputStream(is);
            Boolean flag = dis.readBoolean();
            System.out.println(flag);
    
            // 6.关闭流 + 网络资源
            dis.close();
            is.close();
            oos.close();
            os.close();
            s.close();
        }
    }
    
    
    public class Server {  //服务端
        public static void main(String[] args) throws IOException, ClassNotFoundException {
            // 1.创建套接字
            ServerSocket ss = new ServerSocket(8888);
    
            // 2.等待客户端发来的信息
            Socket s = ss.accept();
    
            // 3.获取传入的数据
            InputStream is = s.getInputStream();
            ObjectInputStream ois = new ObjectInputStream(is);
    
            // 4.读取客户端发送的数据
            User user = (User) ois.readObject();
    
            // 5.对对象进行验证:
            boolean flag = false;
            if (user.getName().equals("wrr") && user.getPwd().equals("1234")){
                flag = true;
            }
    
            // 6.向客户端输出结果
            OutputStream os = s.getOutputStream();
            DataOutputStream dos = new DataOutputStream(os);
            dos.writeBoolean(flag);
    
            // 7.关闭流 + 网络资源
            dos.close();
            os.close();
            ois.close();
            is.close();
            ss.close();
        }
    }
    

    10.4.3完整的异常处理方式

    Socket提出去,其他的流在外面初始化为null

    关闭流和资源放到finally,再对里面的流进行异常处理

    public class Client {  //客户端
        public static void main(String[] args){
            // 1.创建套接字
            Socket s = null;
            OutputStream os = null;
            ObjectOutputStream oos = null;
            InputStream is = null;
            DataInputStream dis = null;
            try {
                s = new Socket("127.0.0.1", 8888);
                // 2.录入账号和密码
                Scanner sc = new Scanner(System.in);
                System.out.println("username:");
                String name = sc.next();
                System.out.println("password:");
                String pwd = sc.next();
    
                // 3.将账号和密码封装为一个User对象
                User user = new User(name, pwd);
    
                // 4.向外发送对象,利用输出流
                os = s.getOutputStream();
                oos = new ObjectOutputStream(os);
                oos.writeObject(user);
    
                // 5.接收服务端发送的结果
                is = s.getInputStream();
                dis = new DataInputStream(is);
                Boolean flag = dis.readBoolean();
                System.out.println(flag);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                // 6.关闭流 + 网络资源
                try {
                    if(dis != null) {
                        dis.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if(is != null) {
                        is.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if(oos != null) {
                        oos.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if(os != null) {
                        os.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if(s != null) {
                        s.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            
        }
    }
    
    
    public class Server {
        public static void main(String[] args){
            // 1.创建套接字
            ServerSocket ss = null;
            InputStream is = null;
            ObjectInputStream ois = null;
            OutputStream os = null;
            DataOutputStream dos = null;
            
            try {
                ss = new ServerSocket(8888);
                // 2.等待客户端发来的信息
                Socket s = ss.accept();
    
                // 3.获取传入的数据
                is = s.getInputStream();
                ois = new ObjectInputStream(is);
    
                // 4.读取客户端发送的数据
                User user = null;
                try {
                    user = (User) ois.readObject();
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
    
                // 5.对对象进行验证:
                boolean flag = false;
                if (user.getName().equals("wrr") && user.getPwd().equals("1234")){
                    flag = true;
                }
    
                // 6.向客户端输出结果
                os = s.getOutputStream();
                dos = new DataOutputStream(os);
                dos.writeBoolean(flag);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                // 7.关闭流 + 网络资源
                try {
                    if(dos != null) {
                        dos.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if(os != null) {
                        os.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if(ois != null) {
                        ois.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if(is != null) {
                        is.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if(ss != null) {
                        ss.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    
            
    
            
        }
    }
    
    

    10.4.4多个客户端和一个服务器

    客户端的代码不变

    public class Client {  //客户端
        public static void main(String[] args){
            // 1.创建套接字
            Socket s = null;
            OutputStream os = null;
            ObjectOutputStream oos = null;
            InputStream is = null;
            DataInputStream dis = null;
            try {
                s = new Socket("127.0.0.1", 8888);
                // 2.录入账号和密码
                Scanner sc = new Scanner(System.in);
                System.out.println("username:");
                String name = sc.next();
                System.out.println("password:");
                String pwd = sc.next();
    
                // 3.将账号和密码封装为一个User对象
                User user = new User(name, pwd);
    
                // 4.向外发送对象,利用输出流
                os = s.getOutputStream();
                oos = new ObjectOutputStream(os);
                oos.writeObject(user);
    
                // 5.接收服务端发送的结果
                is = s.getInputStream();
                dis = new DataInputStream(is);
                Boolean flag = dis.readBoolean();
                System.out.println(flag);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                // 6.关闭流 + 网络资源
                try {
                    if(dis != null) {
                        dis.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if(is != null) {
                        is.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if(oos != null) {
                        oos.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if(os != null) {
                        os.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if(s != null) {
                        s.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    
        }
    }
    
    

    服务端 Server.java

    public class Server {
        public static void main(String[] args){
            // 1.创建套接字
            ServerSocket ss = null;
            Socket s = null;
            int count = 0; // 定义一个计数器,用来计数 客户端的请求
            try {
                ss = new ServerSocket(8888);
                // 2.等待客户端发来的信息
                while (true) { // 加入死循环,服务器一直监听客户端是否发送数据
                    s = ss.accept();
                    //每次过来的客户端的请求靠线程处理
                    new ServerThread(s).start();
                    count++;
                    System.out.println("当前是第"+count+"个用户访问我们的服务器,对应的用户是"+s.getInetAddress());
                }
    
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    }
    

    新建ServerThread.java

    public class ServerThread extends Thread{  // 线程:专门处理客户端的请求
        InputStream is = null;
        ObjectInputStream ois = null;
        OutputStream os = null;
        DataOutputStream dos = null;
        Socket s = null;
        public ServerThread(Socket s){
            this.s = s;
        }
        @Override
        public void run() {
            // 3.获取传入的数据
            try{
                is = s.getInputStream();
                ois = new ObjectInputStream(is);
    
                // 4.读取客户端发送的数据
                User user = null;
                try {
                    user = (User) ois.readObject();
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
    
                // 5.对对象进行验证:
                boolean flag = false;
                if (user.getName().equals("wrr") && user.getPwd().equals("1234")){
                    flag = true;
                }
    
                // 6.向客户端输出结果
                os = s.getOutputStream();
                dos = new DataOutputStream(os);
                dos.writeBoolean(flag);
            } catch (IOException e){
                e.printStackTrace();
            } finally {
                try {
                    if(dos != null) {
                        dos.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if(os != null) {
                        os.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if(ois != null) {
                        ois.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if(is != null) {
                        is.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    

    10.5UDP通信

    image-20210602000804582

    10.5.1单向通信

    public class TestSend {
        public static void main(String[] args) throws IOException { //发送方
            System.out.println("学生上线");
            // 1.准备套接字,指定发送方的端口号
            DatagramSocket ds = new DatagramSocket(8888);
            // 2.准备数据包
            String str = "你好";
            byte[] bytes = str.getBytes();
            DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("localhost"), 9999);
            /*
            需要四个参数: 1.传送数据转为字节的数组 2.字节数组的长度 3.接收方的IP地址 4.接收方的端口号
             */
    
            // 3.发送
            ds.send(dp);
    
            // 4.关闭资源
            ds.close();
    
        }
    }
    
    
    public class TestReceive {
        public static void main(String[] args) throws IOException { //接收方
            System.out.println("接收消息");
            // 1.准备套接字
            DatagramSocket ds = new DatagramSocket(9999);
    
            // 2.有一个空的数据包,准备接收对方传过来的数据
            byte[] b = new byte[1024];
            DatagramPacket dp = new DatagramPacket(b, b.length);
    
            // 3.接收对方的数据包,然后放入到我们的dp数据包中填充
            ds.receive(dp); //接收完以后,dp里面就填充好内容了
    
            // 4.取出数据:
            byte[] data = dp.getData();
            String s = new String(data, 0, dp.getLength());  // dp.getLength()数组包中的有效长度
            System.out.println(s);
    
            // 5.关闭资源
            ds.close();
    
        }
    }
    
    

    10.5.2双向通信

    public class TestReceive {
        public static void main(String[] args) throws IOException { //接收方
            System.out.println("接收消息");
            // 1.准备套接字
            DatagramSocket ds = new DatagramSocket(9999);
    
            // 2.有一个空的数据包,准备接收对方传过来的数据
            byte[] b = new byte[1024];
            DatagramPacket dp = new DatagramPacket(b, b.length);
    
            // 3.接收对方的数据包,然后放入到我们的dp数据包中填充
            ds.receive(dp); //接收完以后,dp里面就填充好内容了
    
            // 4.取出数据:
            byte[] data = dp.getData();
            String s = new String(data, 0, dp.getLength());  // dp.getLength()数组包中的有效长度
            System.out.println(s);
    
            // 5.回复
            String str = "Hello";
            byte[] bytes = str.getBytes();
            DatagramPacket dp1 = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("localhost"), 8888);
    
            ds.send(dp1);
    
            // 5.关闭资源
            ds.close();
    
        }
    }
    
    
    public class TestSend {
        public static void main(String[] args) throws IOException { //发送方
            System.out.println("学生上线");
            // 1.准备套接字,指定发送方的端口号
            DatagramSocket ds = new DatagramSocket(8888);
            // 2.准备数据包
            String str = "你好";
            byte[] bytes = str.getBytes();
            DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("localhost"), 9999);
            /*
            需要四个参数: 1.传送数据转为字节的数组 2.字节数组的长度 3.接收方的IP地址 4.接收方的端口号
             */
    
            // 3.发送
            ds.send(dp);
    
            // 4.接收
            byte[] b = new byte[1024];
            DatagramPacket dp1 = new DatagramPacket(b, b.length);
            ds.receive(dp1);
    
            byte[] data = dp1.getData();
            String s = new String(data, 0, dp1.getLength());
            System.out.println(s);
    
            // 4.关闭资源
            ds.close();
    
        }
    }
    
    

    10.5.3完整的异常处理方式

    与TCP协议的通信一致,如10.4.3

  • 相关阅读:
    FreeRTOS 动态内存管理
    NODE.JS之我见
    Maven使用详解
    WPF依赖属性详解
    对比MFC资源文件谈谈WPF布局方式
    MAPPING SEGMENTS TO PAGES
    只用一行代码让你的ASP.NET MVC 跑起来
    WPF The Hard Way
    Java判断回文数算法简单实现
    2014让我受益最大的那些书--别找了,都在这里
  • 原文地址:https://www.cnblogs.com/wrrr/p/14871906.html
Copyright © 2011-2022 走看看