zoukankan      html  css  js  c++  java
  • java:网络编程(InetAddress,InetSocketAddress,URL,TCP(Socket与SeverSocket),TCP与UDP的区别)

    InerAddress:

    /**IP地址:在网络上唯一标示一台计算机
    * 端口号:标示计算机上不同的应用程序
    * java.net.InetAddress类:此类表示互联网协议 (IP) 地址。
    * 常用方法:
    * getByName(String host) 在给定主机名的情况下确定主机的 IP 地址。
    * getHostName() 获取此 IP地址的主机名。
    * getHostAddress()返回 IP 地址字符串(以文本表现形式)。
    * getLocalHost() 返回本地主机。
    * getAllByName(String host) 在给定主机名的情况下,根据系统上配置的名称服务返回其 IP 地址所组成的数组。
    *
    */

    public class TestInetAddress {
        public static void main(String[] args) {
            try {
                //在给定主机名的情况下确定主机的 IP 地址。
    //            InetAddress inetAddress = InetAddress.getByName("P-PC");
                InetAddress inetAddress = InetAddress.getLocalHost();//获取本地主机
                System.out.println(inetAddress);
                String hostName = inetAddress.getHostName();
                System.out.println("主机名:"+hostName);
                String ip = inetAddress.getHostAddress();
                System.out.println("IP地址:"+ip);
                //根据主机名或域名获取其IP地址
                InetAddress[] ids = InetAddress.getAllByName("www.baidu.com");
                for (InetAddress inetAddress2 : ids) {
                    System.out.println(inetAddress2);
                }
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
            
        }
    }

    InetSocketAddress:

    *java.net.InetSocketAddress类:此类实现 IP 套接字地址(IP 地址 + 端口号)。
    *构造方法
    *InetSocketAddress(InetAddress addr, int port)根据 IP 地址和端口号创建套接字地址。
    *InetSocketAddress(String hostname, int port) 根据主机名和端口号创建套接字地址。
    *常用的方法:
    * getAddress():获取 InetAddress。
    * getPort() 获取端口号。
    * toString() 构造此 InetSocketAddress 的字符串表示形式。(主机名/Ip:端口号)
    * getHostName()获取 主机名。

    public class TestInetSocketAddress {
        public static void main(String[] args) {
    //        InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1",3306);
            try {
                InetSocketAddress socketAddress = new InetSocketAddress(InetAddress.getLocalHost(), 3306);
                System.out.println(socketAddress);
                InetAddress inetAddress = socketAddress.getAddress();
                System.out.println("主机信息:"+inetAddress);
                int port = socketAddress.getPort();
                System.out.println("端口号:"+port);
                String hostName = socketAddress.getHostName();
                System.out.println("主机名:"+hostName);
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
            
        }
    }

    URL:

    *URL:统一资源定位符
    *组成部分:协议,主机名或IP,端口号,资源路径
    *java.net.URL类:代表一个统一资源定位符,它是指向互联网“资源”的指针
    * 常用的构造方法
    * URL(String spec) 根据 String 表示形式创建 URL 对象。
    * URL(String protocol, String host, int port, String file) 根据指定 protocol、host、port 号和 file 创建 URL 对象。
    * 常用的方法:
    * getProtocol()获取此 URL 的协议名称。
    * getHost()获取此 URL 的主机名(如果适用)。
    * getPort() 获取此 URL 的端口号。
    * getFile()获取此 URL 的文件名。
    * getDefaultPort()获取与此 URL 关联协议的默认端口号。
    * getPath()获取此 URL 的路径部分。
    * ...

    public class TestURL {
        public static void main(String[] args) {
            try {
                URL url = new URL("http://www.baidu.com/index.html#aa?cansu=bjsxt");
                String protocol = url.getProtocol();
                System.out.println("协议:"+protocol);
                String host = url.getHost();
                System.out.println("主机名:"+host);
                int port = url.getPort();
                System.out.println("端口号:"+port);
                int defualtPort = url.getDefaultPort();
                System.out.println("默认端口:"+defualtPort);
                String file = url.getFile();
                System.out.println("资源路径:"+file);
                String path = url.getPath();
                System.out.println("资源路径:"+path);
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }
            
        }
    }

    URL类
    * InputStream openStream() 打开到此 URL 的连接并返回一个用于从该连接读入的 InputStream。

    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.MalformedURLException;
    import java.net.URL;
    
    public class WebSpider {
        public static void main(String[] args) {
            try {
                URL url = new URL("https://channel.jd.com/men.html");
                InputStream ips = url.openStream();
                InputStreamReader isr = new InputStreamReader(ips);//将字节流转换为字符流
                BufferedReader br = new BufferedReader(isr);
                String str;
                while((str=br.readLine())!=null){
                    System.out.println(str);
                }
                br.close();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

     Socket与SeverSocket信息的传递:

    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    /** 
     * java.net.ServerSocket类:此类实现服务器套接字。服务器套接字等待请求通过网络传入
     * 构造方法:
     * ServerSocket(int port)创建绑定到特定端口的服务器套接字。
     * 
     * 常用方法:
     * accept() 侦听并接受到此套接字的连接。
     * close() 关闭此套接字。
     * 
     * 服务器端
     */
    public class SimpleServer {
        public static void main(String[] args) {
            try {
                System.out.println("------服务器端启动------");
                //1.创建服务器端的套接字并指定端口
                ServerSocket serverSocket = new ServerSocket(8888);
                //2.侦听并接受到此套接字的连接。
                Socket socket = serverSocket.accept();
                //3.从套接字中获取一个输入流
                InputStream ips = socket.getInputStream();
                InputStreamReader isr = new InputStreamReader(ips);
                char[] cs = new char[1024];
                int len = isr.read(cs);
                String message = new String(cs, 0, len);
                System.out.println("客户端消息:"+message);
                isr.close();
                socket.close();
                serverSocket.close();
                System.out.println("服务器数据接收完毕!");
            } catch (IOException e) {
                e.printStackTrace();
            }
            
        }
    }
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.net.Socket;
    import java.net.UnknownHostException;
    
    /**
     *java.net.Socket类:此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点。 
     *构造方法:
     *Socket(InetAddress address, int port)创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
     *Socket(String host, int port) 创建一个流套接字并将其连接到指定主机上的指定端口号。
     *常用方法:
     *getOutputStream()返回此套接字的输出流。
     *getInputStream()  返回此套接字的输入流。
     *close()关闭此套接字。
     *客户端
     */
    public class SimpleClient {
        public static void main(String[] args) {
            try {
                System.out.println("-------客户端启动-------");
                //1.创建一个套接字并将其连接到指定的IP地址的指定端口
                Socket socket = new Socket("127.0.0.1",8888);
                //2.获取套接字的输出流,用于输出数据
                OutputStream ops = socket.getOutputStream();
                OutputStreamWriter osw = new OutputStreamWriter(ops);
                osw.write("你好!");
                osw.flush();
                osw.close();
                socket.close();
                System.out.println("客户端数据发送完毕!");
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            
         }
    }

     根据用户输入的账号密码,从服务器上判断是否正确并传递信息回来:

    import java.io.Serializable;
    /**
     * 如果要对该对象进行序列化,就必须实现Serializable接口
     * 封装用户名和密码信息
     */
    public class User implements Serializable{
        private String userName;
        private String password;
        public User(){
            
        }
        public User(String userName,String password){
            this.userName=userName;
            this.password=password;
        }
        public String getUserName() {
            return userName;
        }
        public void setUserName(String userName) {
            this.userName = userName;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
        
    }
    import java.io.DataInputStream;
    import java.io.DataInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.ObjectOutputStream;
    import java.io.OutputStream;
    import java.net.Socket;
    import java.net.UnknownHostException;
    import java.util.Scanner;
    /**
     * 客户端:
     * 1.获取用户名和密码
     * 2.将用户名和密码封装成User对象
     * 3.使用对象流将user对象发生到服务器端
     * 4.读取服务器的响应消息
     * 5.释放资源
     */
    public class LoginClient {
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
            //获取输入的用户名和密码
            System.out.println("请输入用户名:");
            String userName = input.next();
            System.out.println("请输入密码:");
            String password = input.next();
            //将用户名和密码封装成User对象
            User user = new User(userName,password);
            try {
                //创建Socket对象
                Socket socket = new Socket("127.0.0.1",6666);
                //获取输出流
                OutputStream ops = socket.getOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(ops);
                //使用对象流将user对象发送到服务器端
                oos.writeObject(user);
                oos.flush();
                //获取服务器端响应消息
                InputStream ips = socket.getInputStream();
                DataInputStream dis = new DataInputStream(ips);
                String str = dis.readUTF();
                System.out.println(str);
                //释放资源
                dis.close();
                oos.close();
                socket.close();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            
        }
        
    }
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.ObjectInputStream;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    /**
     * 服务器端:
     * 1.获取客户端发送的user对象(封装了用户名和密码)
     * 2.判断用户名和密码是否合法
     * 3.如果合法,向客户端发送"恭喜你,登陆成功!";否则向客户端发送"用户名或密码有误!"
     * 4.释放资源
     */
    public class LoginServer {
        public static void main(String[] args) {
            try {
                //1.获取客户端发送的用户名和密码信息
                ServerSocket serverSocket = new ServerSocket(6666);
                Socket socket = serverSocket.accept();
                InputStream ips = socket.getInputStream();
                ObjectInputStream ois = new ObjectInputStream(ips);
                User user = (User)ois.readObject();
                //2.判断用户名和密码是否正确
                String message;
                if("zzsxt".equals(user.getUserName())&&"zzsxt".equals(user.getPassword())){
                    message="恭喜你,登陆成功!";
                }else{
                    message="用户名或密码有误!";
                }
                //3.创建输出流向客户端发送消息
                OutputStream ops = socket.getOutputStream();
                DataOutputStream dos = new DataOutputStream(ops);
                dos.writeUTF(message);
                dos.flush();
                //4.释放资源
                ois.close();
                dos.close();
                socket.close();
                serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            
        }
    }

     方法2:

    /**
     * 服务器端:
     * 1.获取客户端发送的user对象(封装了用户名和密码)
     * 2.判断用户名和密码是否合法
     * 3.如果合法,向客户端发送"恭喜你,登陆成功!";否则向客户端发送"用户名或密码有误!"
     * 4.释放资源
     */
    public class LoginServer {
        //用于保存用户名和密码的信息,利用用户名做键,利用密码做值
        static Map<String,String> map = new HashMap<String,String>();
        //初始化map
        static{
            map.put("zzsxt", "zzsxt");
            map.put("bjsxt", "bjsxt");
            map.put("whsxt", "whsxt");
        }
        static int count=0;//第几位访客
        
        public static void main(String[] args) {
            //1.获取客户端发送的用户名和密码信息
            ServerSocket serverSocket=null;
            Socket socket=null;
            ObjectInputStream ois =null;
            DataOutputStream dos=null;
            try {
                serverSocket = new ServerSocket(6666);
                while(true){
                    socket = serverSocket.accept();
                    InputStream ips = socket.getInputStream();
                    ois = new ObjectInputStream(ips);
                    User user = (User)ois.readObject();
                    //2.判断用户名和密码是否正确
                    String userName = user.getUserName();//获取用户输入的用户名 aa
                    String password = user.getPassword();//获取用户输入的密码
                    String upass=map.get(userName);
                    String message;
                    if(upass!=null&&upass.equals(password)){
                        count++;//计数
                        message="恭喜你,登陆成功!您是第"+count+"位访客";
                    }else{
                        message="用户名或密码有误!";
                    }
                    //3.创建输出流向客户端发送消息
                    OutputStream ops = socket.getOutputStream();
                    dos = new DataOutputStream(ops);
                    dos.writeUTF(message);
                    dos.flush();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }finally{
                try {
                    //4.释放资源
                    ois.close();
                    dos.close();
                    socket.close();
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            
        }
    }

     方法3:转换为多线程交互

    import java.io.Serializable;
    /**
     * 如果要对该对象进行序列化,就必须实现Serializable接口
     * 封装用户名和密码信息
     */
    public class User implements Serializable{
        private String userName;
        private String password;
        public User(){
            
        }
        public User(String userName,String password){
            this.userName=userName;
            this.password=password;
        }
        public String getUserName() {
            return userName;
        }
        public void setUserName(String userName) {
            this.userName = userName;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
        
        @Override
        public String toString() {
            return "User [userName=" + userName + ", password=" + password + "]";
        }
        
    }
    public class LoginClient {
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
            //获取输入的用户名和密码
            System.out.println("请输入用户名:");
            String userName = input.next();
            System.out.println("请输入密码:");
            String password = input.next();
            //将用户名和密码封装成User对象
            User user = new User(userName,password);
            try {
                //创建Socket对象
                Socket socket = new Socket("127.0.0.1",6666);
                //获取输出流
                OutputStream ops = socket.getOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(ops);
                //使用对象流将user对象发送到服务器端
                oos.writeObject(user);
                oos.flush();
                //获取服务器端响应消息
                InputStream ips = socket.getInputStream();
                DataInputStream dis = new DataInputStream(ips);
                String str = dis.readUTF();
                System.out.println(str);
                //释放资源
                dis.close();
                oos.close();
                socket.close();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
    }
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.ObjectInputStream;
    import java.io.OutputStream;
    import java.net.Socket;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 用于处理客户端请求的线程
     * @author Administrator
     *
     */
    public class ServerThread extends Thread{
        private Socket socket;
        //用于保存用户名和密码的信息,利用用户名做键,利用密码做值
        static Map<String,String> map = new HashMap<String,String>();
        //初始化map
        static{
            map.put("zzsxt", "zzsxt");
            map.put("bjsxt", "bjsxt");
            map.put("whsxt", "whsxt");
        }
        static int count=0;//第几位访客
        //构造方法
        public ServerThread(Socket socket){
            this.socket=socket;
        }
        /**
         * 处理客户端请求
         */
        @Override
        public void run() {
            ObjectInputStream ois =null;
            DataOutputStream dos=null;
            try {
                InputStream ips = socket.getInputStream();
                ois = new ObjectInputStream(ips);
                User user = (User)ois.readObject();
                //2.判断用户名和密码是否正确
                String userName = user.getUserName();//获取用户输入的用户名 aa
                String password = user.getPassword();//获取用户输入的密码
                String upass=map.get(userName);
                String message;
                if(upass!=null&&upass.equals(password)){
                    count++;//计数
                    message="恭喜你,登陆成功!您是第"+count+"位访客";
                }else{
                    message="用户名或密码有误!";
                }
                //3.创建输出流向客户端发送消息
                OutputStream ops = socket.getOutputStream();
                dos = new DataOutputStream(ops);
                dos.writeUTF(message);
                dos.flush();
            } catch (IOException |ClassNotFoundException e) {
                e.printStackTrace();
            }finally{
                try {
                    ois.close();
                    dos.close();
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /**
     * 面临的问题:
     *     当多个用户同时登陆时,只能排队等待。
     * 解决方案:使用多线程进行解决,为每一个客户请求创建线程,为其提供服务。
     * 
     * 服务器端:
     * 1.获取客户端发送的user对象(封装了用户名和密码)
     * 2.判断用户名和密码是否合法
     * 3.如果合法,向客户端发送"恭喜你,登陆成功!";否则向客户端发送"用户名或密码有误!"
     * 4.释放资源
     * 
     */
    public class LoginServer {
        
        public static void main(String[] args) {
            //1.获取客户端发送的用户名和密码信息
            ServerSocket serverSocket=null;
            try {
                serverSocket = new ServerSocket(6666);
                while(true){
                    Socket socket = serverSocket.accept();
                    //启动线程,处理用户请求
                    new ServerThread(socket).start();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }finally{
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    TCP与UDP的区别:

    1.TCP与UDP基本区别
      1.基于连接与无连接,TCP是面向连接,UDP是不面向连接;
      2.TCP要求系统资源较多效率低,UDP较占用资源少; 
      3.UDP程序结构较简单,TCP点到点的通信,UDP可以广播发送 ;
      4.流模式(TCP)与数据报模式(UDP); 
      5.TCP保证数据正确性,UDP可能丢包(发送不管对方是否准备好,接收方收到也无确认); 
      6.TCP保证数据顺序,UDP不保证 ;


      
    2.UDP应用场景:
      1.面向数据报方式
      2.网络数据大多为短消息 
      3.拥有大量Client
      4.对数据安全性无特殊要求
      5.网络负担非常重,但对响应速度要求高
     
    3.具体编程时的区别
       1.socket()的参数不同 
       2.UDP Server不需要调用listen和accept 
       3.UDP收发数据用sendto/recvfrom函数 
       4.TCP:地址信息在connect/accept时确定 
       5.UDP:在sendto/recvfrom函数中每次均 需指定地址信息 
       6.UDP:shutdown函数无效

  • 相关阅读:
    Redis详解(三)- redis的六大数据类型详细用法
    Redis详解(二)- redis的配置文件介绍
    《OR Talk NO.11 | 清能互联赖晓文:电力系统中的运筹优化应用》
    《OR Talk NO.10 | 浙江大学徐金明:分布式优化算法何时能在性能上与集中式算法相媲美?》
    《OR Talk NO.9 | 深圳大学龚元浩:比几何流快一万倍的曲率滤波算法》
    《OR Talk NO.4 | Attain.ai 创始人李玉喜:强化学习遇见组合优化》
    《OR Talk NO.3 | 滴滴 AI Labs 秦志伟:深度强化学习在网约che交易市场中的应用》
    《OR Talk NO.2 | 胡武华博士:运筹优化理论在物流行业中的应用实践》
    《KDD 2018 | Conventional Tutorials》
    《OR Talk NO.13 | MIT 博士与你分享电商供应链算法实战心得》
  • 原文地址:https://www.cnblogs.com/kuangzhisen/p/7053689.html
Copyright © 2011-2022 走看看