• 网络编程


    http://www.jd.com:80/index.html

    URL(Uniform Resource Locator):统一资源定位符,它是指向互联网“资源”的指针。
    组成部分:
      1.协议(http,https,ftp...),在://前面的部分
      2.主机域名部分: www.jd.com 192.168.1.23
      3.端口部分:80
      4.资源路径(资源名称): index.html /test/index.html
    java.net.URL
      构造函数:
        URL(String spec)根据 String 表示形式创建 URL 对象。
          URL url = new URL("http://www.jd.com:80/test/index.html");
        URL(String protocol, String host, int port, String file)根据指定 protocol、host、port 号和 file 创建 URL 对象。
          URL url = new URL("http","www.jd.com",80,"/test/index.html");
      常用的方法:
        getHost()获取此 URL 的主机名(如果适用)。
        getFile() 获取此 URL 的文件名。
        getPort() 获取此 URL 的端口号。
        getProtocol()获取此 URL 的协议名称。
        openStream()打开到此 URL 的连接并返回一个用于从该连接读入的 InputStream。

    public class TestURL {
        public static void main(String[] args) {
            try {
                URL url = new URL("http://www.jd.com:8080/test/index.html");
                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 defaultPort = url.getDefaultPort();
                System.out.println("默认端口:"+defaultPort);
                String file = url.getFile();
                System.out.println("文件路径:"+file);
                System.out.println("---------读取京东主页内容-----------");
                URL jingdong = new URL("https://www.jd.com/index.html"); 
                InputStream  ips = jingdong.openStream();
                InputStreamReader isr = new InputStreamReader(ips,"UTF-8");//将字节流转换为字符流
                BufferedReader br = new BufferedReader(isr);
                String str;
                while((str=br.readLine())!=null){
                    System.out.println(str);
                }
                br.close();
                isr.close();
                ips.close();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            
        }
    }

    java.lang.*:java的核心类
    java.util.*:工具包
    java.text.*:格式化输出的类 (SimpleDataFormat)
    java.io.*:保存与IO流操作相关类和接口
    java.net.*:保存与网络通信相关类和接口
    IPv4地址是有32为二进制组成,IPv6是128为的二进制组成,用于表示唯一表示网络上的计算机
    端口号:用于表示一台计算机上不同的服务,取值范围0~66535
     0~1023系统服务占用
     常用的端口:
       ftp的端口号:21
       www服务器:80
       oracle:1521
      mysql:3306
      sqlserver:1433
    java.net.InetAddress类:此类表示互联网协议 (IP) 地址。 没有端口
    构造函数:没有
    常用方法:
      获取InetAddress对象的方法
       getByName(String host)在给定主机名的情况下确定主机的 IP地址。
      getAllByName(String host) 在给定主机名的情况下,根据系统上配置的名称服务返回其 IP 地址所组成的数组。
      getLocalHost():返回本地主机。
    实例方法:
      getHostName() 获取此 IP 地址的主机名。

      getHostAddress() 返回 IP 地址字符串(以文本表现形式)。
      toString() 将此 IP 地址转换为 String。 主机名/IP地址

    public class TestInetAddress {
        public static void main(String[] args) {
            try {
                InetAddress  inetAddress = InetAddress.getLocalHost();//获取本机IP地址
                System.out.println(inetAddress);//2013-20161115CZ/192.168.1.47
                InetAddress inetAddress2 = InetAddress.getByName("LY");//根据主机名获取IP地址
                System.out.println(inetAddress2);
                InetAddress inetAddress3 = InetAddress.getByName("www.baidu.com");//根据主机名获取IP地址
                System.out.println(inetAddress3);
                InetAddress[] inetAddresses =  InetAddress.getAllByName("www.qq.com");
                for (InetAddress inetAddress4 : inetAddresses) {
                    String hostName = inetAddress4.getHostName();
                    System.out.println("主机名:"+hostName);
                    String hostAddress = inetAddress4.getHostAddress();
                    System.out.println("IP地址:"+hostAddress);
                }
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
        }
    }

    java.net.InetSocketAddress:此类实现 IP套接字地址(IP 地址 + 端口号)。主要用于Socket编程
      构造函数:
        InetSocketAddress(InetAddress addr, int port) 根据 IP 地址和端口号创建套接字地址。
        InetSocketAddress(int port) 创建套接字地址,其中 IP 地址为通配符地址,端口号为指定值。
        InetSocketAddress(String hostname, int port) ** 根据主机名和端口号创建套接字地址。
      常用方法:
        getAddress()获取 InetAddress。
        getPort()获取端口号。
        getHostName() 获取 hostname。

    public class TestInetSocketAddress {
        public static void main(String[] args) {
            //本机
            InetSocketAddress  inetSocketAddress = new InetSocketAddress("127.0.0.1",8888);
            String hostName = inetSocketAddress.getHostName();
            int port = inetSocketAddress.getPort(); 
            System.out.println("hostName:"+hostName);
            System.out.println("Port:"+port);
            //淘宝
            try {
                InetAddress  inetAddress = InetAddress.getByName("www.taobao.com");
                InetSocketAddress  remoteAddress = new InetSocketAddress(inetAddress,80);
                String remoteHostName = remoteAddress.getHostName();
                int remotePort = remoteAddress.getPort();
                System.out.println(remoteHostName+"---"+remotePort);
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
        }
    }

    Socket(套接字):套接字是两台机器间通信的端点。
    java.net.Socket
      常用的构造函数:
        Socket(InetAddress address, int port) 创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
        Socket(String host, int port) 创建一个流套接字并将其连接到指定主机上的指定端口号。
      常用方法:
        getOutputStream() 返回此套接字的输出流。
        getInputStream() 返回此套接字的输入流
        close(): 关闭此套接字。
    客户端发送数据的步骤:
      1.创建一个和服务器端通信的套接字
        Socket socket = new Socket("127.0.0.1",8888);
      2.使用套接字获取一个输出流
        OutputStream ops = socket.getOutputStream();//
      3.使用输出流发送数据

    public class HelloClient {
        public static void main(String[] args) {
    //        InetAddress localhost = InetAddress.getByName("127.0.0.1");
    //        Socket socket = new Socket(localhost, 8888);
            Socket socket=null;
            OutputStream ops=null;
            OutputStreamWriter osw=null;
            try {
                //1.创建一个套接字(127.0.0.1:服务器端的地址,8888:服务器端口)
                socket = new Socket("127.0.0.1",8888);
                //2.从套接字中获取输出流,用于输出数据
                ops = socket.getOutputStream();//
                osw = new OutputStreamWriter(ops);
                osw.write("客户端---->长江长江,我是黄河!");
                osw.flush();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally{
                try {
                    osw.close();
                    ops.close();
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    服务器端读取的步骤:
      1.创建一个服务器端的套接字:
        ServerSocket serverSocket = new ServerSocket(8888);
      2.调用服务器端套接字的accept(),侦听并接受到此套接字的连接。
        Socket socket = serverSocket.accept();
      3.通过套接字getInputStream方法获取输入流。
        InputStream ips = socket.getInputStream();
      4.同输入流读取数据
      ...
    java.net.ServerSocket类:此类实现服务器套接字
      构造函数:
        ServerSocket(int port)创建绑定到特定端口的服务器套接字。
      常用方法:
        accept()侦听并接受到此套接字的连接。

    public class HelloServer {
        public static void main(String[] args) {
            try {
                //1.创建服务器端套接字,其中参数8888为服务器的端口号
                ServerSocket  serverSocket = new ServerSocket(8888);
                //2.调用accept()方法,侦听并接受到此套接字的连接。
                Socket  socket = serverSocket.accept();
                //3.通过getInputStream()获取一个套接字输入流,用于读取数据
                InputStream ips = socket.getInputStream();
                InputStreamReader isr = new InputStreamReader(ips);
                BufferedReader br = new BufferedReader(isr);
                String str = br.readLine();
                System.out.println("服务器端收到的消息:"+str);
                //4.关闭资源
                br.close();
                isr.close();
                ips.close();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 双向通信
     * 客户端:
     * 
     */
    public class SimpleClient {
        public static void main(String[] args) {
            System.out.println("客户端启动了....");
            try {
                Socket  socket = new Socket("127.0.0.1",6666);
                DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
                DataInputStream  dis = new DataInputStream(socket.getInputStream());
                dos.writeUTF("hello, i am client!");
                dos.flush();
                String message = dis.readUTF();
                System.out.println(message);
                //释放资源
                dos.close();
                dis.close();
                socket.close();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            
        }
    }
     
    public class SimpleServer {
        /**
         * 服务器端
         * @param args
         */
        public static void main(String[] args) {
            try {
                System.out.println("服务器端启动了.....");
                ServerSocket serverSocket = new ServerSocket(6666);
                Socket socket = serverSocket.accept();
                DataInputStream  dis = new DataInputStream(socket.getInputStream());
                DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
                String message = dis.readUTF();
                System.out.println(message);
                dos.writeUTF("hello ,i am server!");
                dis.close();
                dos.close();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    登录:

    /**
     * User实体对象:用于封装用户信息
     * @author Administrator
     */
    public class User implements Serializable {
        private String username;
        private String password;
        
        public User() {
            super();
        }
    
        public User(String username, String password) {
            super();
            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;
        }
        
        
    }
    public class LoginClient {
        public static void main(String[] args) {
            System.out.println("------客户端------");
            Scanner input = new Scanner(System.in);
            System.out.println("请输入用户名:");
            String username = input.next();
            System.out.println("请输入密码:");
            String password = input.next();
            User user = new User(username,password);//将用户名和密码封装到user对象中
            try {
                //1.创建一个Socket对象
                Socket socket = new Socket("127.0.0.1",8888);
                //2.创建对象输出流,用于输出user对象
                ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                oos.writeObject(user);
                oos.flush();
                
                //接受服务器的数据
                //3.创建DataInputStream对象,用于读取服务器端响应的消息
                DataInputStream dis = new DataInputStream(socket.getInputStream());
                //读取消息
                String message = dis.readUTF();
                System.out.println(message);
                //关闭流和socket
                oos.close();
                dis.close();
                socket.close();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            
            
        }
    }
    public class LoginServer {
        public static void main(String[] args) {
            System.out.println("------服务器端------");
            try {
                //1.创建ServerSocket对象
                ServerSocket serverSocket = new ServerSocket(8888);
                //2.调用accept()方法,返回Socket
                Socket socket = serverSocket.accept();
                //3.创建对象输入流,用于读取客户端发送的数据
                ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                User user = (User)ois.readObject();
                //4.判断用户名和密码是否正确
                String message;
                if("zzsxt".equals(user.getUsername())&&"123456".equals(user.getPassword())){
                    message="欢迎您,登陆成功!";
                }else{
                    message="用户名或密码有误,请重新登陆!";
                }
                //4.创建DataOutputStream对象,将message消息输出到客户端
                DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
                dos.writeUTF(message);
                dos.flush();
                //5.关闭socket和流
                ois.close();
                dos.close();
                socket.close();
                serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

    上传的客户端:
    1.使用输入流将D:/mp3/test.mp3读取
    2.使用套接字中输出流将D:/mp3/test.mp3输出
    3.使用套接字的输入流读取服务器端反馈的消息

    使用缓冲流(BufferedInputStream,BufferedOutputStream,BufferedReader,BufferedWriter)
    Socket的shutdownOutput()方法关闭输出流,这样对端的输入流上的read操作就会返回-1,避免阻塞

    public class UploadClient {
        public static void main(String[] args) throws Exception{
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:/mp3/test.mp3"));
            Socket socket = new Socket(InetAddress.getLocalHost(), 8888);
            BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
            int len;
            //使用缓冲字节输入流读取
            while((len=bis.read())!=-1){
                bos.write(len);//使用缓冲字节输出流写入Socket
            }
            bos.flush();
            socket.shutdownOutput();
            System.out.println("客户发送完毕!");
            DataInputStream dis  = new DataInputStream(socket.getInputStream());
            String message = dis.readUTF();
            System.out.println(message);
            
            bis.close();
            bos.close();
            dis.close();
            socket.close();
        }
    }

    1.使用套接字的输入流将文件读取出来
    2.使用输出流将从套接字中读取的内容写入到指定位置
    3.使用套接字的输出流向客户端输出反馈消息

    public class UploadServer {
        public static void main(String[] args) throws Exception{
            ServerSocket  serverSocket = new ServerSocket(8888);
            Socket socket = serverSocket.accept();
            //用于读取客户端发送的文件数据
            BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:/test.mp3"));
            int len;
            while((len=bis.read())!=-1){
                bos.write(len);
            }
            bos.flush();
            System.out.println("服务器端文件接受完毕!");
            //获取套接字的输出流,用于向客户端发送反馈消息
            DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); 
            dos.writeUTF("服务器端接受完毕!");
            dos.flush();
            
            bis.close();
            bos.close();
            dos.close();
            socket.close();
            serverSocket.close();
         }
    }
        private String username;
        private String password;
        
        public User() {
            super();
        }
    
        public User(String username, String password) {
            super();
            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 LoginServer {
        //用于保存用户名和密码,用户名做键,密码做值
        static Map<String,String> map = new HashMap<String,String>();
        //使用静态块进行初始化
        static{
            map.put("zzsxt", "zzsxt");
            map.put("bjsxt", "bjsxt");
            map.put("shsxt", "shsxt");
        }
        
        public static void main(String[] args) throws Exception {
            System.out.println("------服务器端------");
            //1.创建ServerSocket对象
            ServerSocket serverSocket = new ServerSocket(8888);
            int count=0;
            while(true){
                Socket socket = serverSocket.accept();//监听客户端请求,并返回一个套接字
                //使用对象输入流读取客户端发送的数据
                ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
                User user = (User)ois.readObject();
                //获取用户名和密码
                String uname = user.getUsername();// whsxt
                String upass = user.getPassword(); //123
                //根据客户端用户输入的用户名进行查找
                String password = map.get(uname);
                if(upass.equals(password)){//密码相同
                    dos.writeUTF("登陆成功!
    欢迎您,!"+uname);
                }else{
                    dos.writeUTF("用户名或密码有误,请重新输入!");
                }    
                System.out.println("第"+(++count)+"位访客,用户信息:"+user);
                dos.flush();
                //关闭资源
                ois.close();
                dos.close();
                socket.close();
            }
        }
    }
    public class LoginClient {
        public static void main(String[] args) {
            System.out.println("------客户端------");
            Scanner input = new Scanner(System.in);
            System.out.println("请输入用户名:");
            String username = input.next();
            System.out.println("请输入密码:");
            String password = input.next();
            User user = new User(username,password);//将用户名和密码封装到user对象中
            try {
                //1.创建一个Socket对象
                Socket socket = new Socket("127.0.0.1",8888);
                //2.创建对象输出流,用于输出user对象
                ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                oos.writeObject(user);
                oos.flush();
                
                //接受服务器的数据
                //3.创建DataInputStream对象,用于读取服务器端响应的消息
                DataInputStream dis = new DataInputStream(socket.getInputStream());
                //读取消息
                String message = dis.readUTF();
                System.out.println(message);
                //关闭流和socket
                oos.close();
                dis.close();
                socket.close();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            
            
        }
    }
    利用多线程实现同时处理多个用户请求:为每一个客户端的请求单独创建一个线程
    public class User implements Serializable {
        private String username;
        private String password;
        
        public User() {
            super();
        }
    
        public User(String username, String password) {
            super();
            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 + "]";
        }
        
        
    }
    /**
     *HashMap与Hashtable的区别
     *1.HashMap是非线程安全,而Hashtable是线程安全的适合在多线程中使用 
     *2.HashMap键和值都可以为null,Hashtable则不然
     */
    public class LoginThread extends Thread{
        private Socket socket;
        
        public LoginThread(Socket socket){
            this.socket=socket;
        }
        static int count=0;//计数
        //用于保存用户名和密码,用户名做键,密码做值
        static Map<String,String> map = new Hashtable<String,String>();
        //使用静态块进行初始化
        static{
            map.put("zzsxt", "zzsxt");
            map.put("bjsxt", "bjsxt");
            map.put("shsxt", "shsxt");
        }
        
        @Override
        public void run() {
            try {
                //使用对象输入流读取客户端发送的数据
                ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
                User user = (User)ois.readObject();
                //获取用户名和密码
                String uname = user.getUsername();// whsxt
                String upass = user.getPassword(); //123
                //根据客户端用户输入的用户名进行查找
                String password = map.get(uname);
                if(upass.equals(password)){//密码相同
                    dos.writeUTF("登陆成功!
    欢迎您,!"+uname);
                }else{
                    dos.writeUTF("用户名或密码有误,请重新输入!");
                }    
                System.out.println("第"+(++count)+"位访客,用户信息:"+user);
                dos.flush();
                //关闭资源
                ois.close();
                dos.close();
                socket.close();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     *客户端
     */
    public class LoginClient {
        public static void main(String[] args) {
            System.out.println("------客户端------");
            Scanner input = new Scanner(System.in);
            System.out.println("请输入用户名:");
            String username = input.next();
            System.out.println("请输入密码:");
            String password = input.next();
            User user = new User(username,password);//将用户名和密码封装到user对象中
            try {
                //1.创建一个Socket对象
                Socket socket = new Socket("127.0.0.1",8888);
                //2.创建对象输出流,用于输出user对象
                ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                oos.writeObject(user);
                oos.flush();
                
                //接受服务器的数据
                //3.创建DataInputStream对象,用于读取服务器端响应的消息
                DataInputStream dis = new DataInputStream(socket.getInputStream());
                //读取消息
                String message = dis.readUTF();
                System.out.println(message);
                //关闭流和socket
                oos.close();
                dis.close();
                socket.close();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            
            
        }
    }
    /**
     * 单线程存在的问题:当多个用户同时访问时,用户只能按照访问顺序进行等待。
     * 解决方案:
     * 利用多线程实现同时处理多个用户请求:为每一个客户端的请求单独创建一个线程
     * 
     */
    public class LoginServer {
    
        
        public static void main(String[] args) throws Exception {
            System.out.println("------服务器端------");
            //1.创建ServerSocket对象
            ServerSocket serverSocket = new ServerSocket(8888);
            int count=0;
            while(true){
                Socket socket = serverSocket.accept();//监听客户端请求,并返回一个套接字
                LoginThread loginThread = new LoginThread(socket);
                //启动线程
                loginThread.start();
            }
        }
    }
    /**
     * 聊天的客户端
     */
    public class ChartClient {
        public static void main(String[] args) throws Exception{
    //        InputStreamReader isr = new InputStreamReader(System.in);//将键盘输入的内容转为字符流 System.in:标准输入流
    //        BufferedReader input = new BufferedReader(isr);
            Scanner input = new Scanner(System.in);
            Socket socket = new Socket(InetAddress.getLocalHost(),6666);
            //获取套接字中输入流,用于读取服务器端的数据
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            //获取套接字中输出流,用于发送客户端的数据
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            while(true){
                //获取用户输入
    //            String clientMessage = input.readLine();
                String clientMessage = input.nextLine();
                //如果客户端输入内容为end的话,结束会话.
                if("end".equals(clientMessage)){
                    break;
                }
                //将客户的消息输出
                bw.write(clientMessage+"
    ");// 
    必须添加,防止服务器端使用readLine()方法读取时阻塞
                bw.flush();
                //获取服务器的消息
                String serverMessage = br.readLine();
                if(serverMessage!=null){
                    System.out.println("服务器端说:"+serverMessage);
                }
            }
            //关闭流和套接字
            br.close();
            bw.close();
            socket.close();
        }
    }
    /**
     * 聊天的服务器端
     */
    public class ChartServer {
        public static void main(String[] args) throws Exception{
            Scanner input = new Scanner(System.in);
            //创建ServerSocket对象,并指定监听端口6666
            ServerSocket serverSocket = new ServerSocket(6666);
            //监听6666端口,并返回一个套接字
            Socket socket = serverSocket.accept();
            //获取套接字中输入流,用于读取客户端的数据
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            //获取套接字中输出流,用于发送服务器端的数据
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            while(true){
                //获取客户端的数据
                String clientMessage = br.readLine();
                if(clientMessage!=null){
                    System.out.println("客户端说:"+clientMessage);
                }
                //获取用户输入
                String serverMessage = input.nextLine();
                //如果服务器端输入内容为end的话,结束会话.
                if("end".equals(serverMessage)){
                    break;
                }
                //将客户的消息输出
                bw.write(serverMessage+"
    ");// 
    必须添加,防止服务器端使用readLine()方法读取时阻塞
                bw.flush();
            }
            //关闭流和套接字
            br.close();
            bw.close();
            socket.close();
        }
    }

    单项一次通信:
    客户端:顾客
    单项通信:顾客--->客服发送消息--->客服获取消息并展示
    java.net.DatagramSocket:此类表示用来发送和接收数据报包的套接字。 (发送电报的电台)
      作用:发送和接受数据报包
      构造函数:
        DatagramSocket():构造数据报套接字并将其绑定到本地主机上任何可用的端口。
        DatagramSocket(int port)创建数据报套接字并将其绑定到本地主机上的指定端口。
      常用方法:
        send(DatagramPacket p)从此套接字发送数据报包。
        receive(DatagramPacket p)从此套接字接收数据报包。
        close() 关闭此数据报套接字。

    java.net.DatagramPacket:此类表示数据报包。 类似于信封(封装信和收件人地址信息)
      作用:用于封装内容数据和目的地的地址
      构造函数:
        DatagramPacket(byte[] buf, int length, InetAddress address, int port)
      构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。

    public class AskClient {
        public static void main(String[] args) throws Exception{
            //1.创建数据报包的套接字DatagramSocket
            DatagramSocket datagramSocket = new DatagramSocket();
            String str="亲,在吗?";
            byte[] content =str.getBytes();
            InetAddress inetAddress = InetAddress.getLocalHost();
            //2.创建数据报包:包含有内容,发送内容的长度,目的地IP,目的地的端口
            DatagramPacket datagramPacket = new DatagramPacket(content,content.length,inetAddress,6666);
            //3.使用send方法发送数据报包
            datagramSocket.send(datagramPacket);
            //4.关闭套接字
            datagramSocket.close();
        }
    }


    服务器端:客服
    java.net.DatagramPacket:数据报包用来实现无连接包投递服务
      构造函数:
        DatagramPacket(byte[] buf, int length) 构造 DatagramPacket,用来接收长度为 length 的数据包。
        DatagramPacket(byte[] buf, int length, InetAddress address, int port)
      构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
      常用方法:
        getAddress() 获取发送方的IP地址
        getData() 返回数据缓冲区。
        getPort() 获取端口
        getLength() 返回将要发送或接收到的数据的长度。

    public class AskServer {
        public static void main(String[] args) throws Exception{
            //1.创建一个数据报套接字
            DatagramSocket datagramSocket = new DatagramSocket(6666);
            //2.创建一个数据报包
            byte[] content = new byte[1024];
            DatagramPacket datagramPacket =  new DatagramPacket(content, content.length);
            //3.调用套接字的receive接收数据报包
            datagramSocket.receive(datagramPacket);
            //4.从数据报包中获取数据
            InetAddress inetAddress=datagramPacket.getAddress();
            byte[] data = datagramPacket.getData();
            int port = datagramPacket.getPort();
            int length = datagramPacket.getLength();
            System.out.println("访问者IP地址:"+inetAddress);
            System.out.println("内容:"+new String(data,0,length));
            System.out.println("访问者端口:"+port);
            System.out.println("长度:"+length);
            //5.关闭套接字
            datagramSocket.close();
        }
    }

    双向一次通信

    public class AskClient {
        public static void main(String[] args) throws Exception{
            //1.创建数据报包的套接字DatagramSocket
            DatagramSocket datagramSocket = new DatagramSocket(8888);
            String str="亲,在吗?";
            byte[] content =str.getBytes();
            InetAddress inetAddress = InetAddress.getLocalHost();
            //2.创建数据报包:包含有内容,发送内容的长度,目的地IP,目的地的端口
            DatagramPacket datagramPacket = new DatagramPacket(content,content.length,inetAddress,6666);
            //3.使用send方法发送数据报包
            datagramSocket.send(datagramPacket);
            
            //接收消息
            byte[] content2 = new byte[1024];
            DatagramPacket  datagramPacket2 = new DatagramPacket(content2, content2.length);
            datagramSocket.receive(datagramPacket2);
            byte[] data = datagramPacket2.getData();
            System.out.println("客服说:"+new String(data,0,data.length));
            //4.关闭套接字
            datagramSocket.close();
            
            
        }
    }
    public class AskServer {
        public static void main(String[] args) throws Exception{
            //1.创建一个数据报套接字
            DatagramSocket datagramSocket = new DatagramSocket(6666);
            //2.创建一个数据报包
            byte[] content = new byte[1024];
            DatagramPacket datagramPacket =  new DatagramPacket(content, content.length);
            //3.调用套接字的receive接收数据报包
            datagramSocket.receive(datagramPacket);
            //4.从数据报包中获取数据
            InetAddress inetAddress=datagramPacket.getAddress();
            byte[] data = datagramPacket.getData();
            System.out.println("顾客说:"+new String(data,0,data.length));
             //发送消息
            String str2 = "亲,在的!";
            byte[] content2 = str2.getBytes();
            DatagramPacket datagramPacket2 = new DatagramPacket(content2, content2.length,InetAddress.getByName("localhost"),8888);
            datagramSocket.send(datagramPacket2);
            datagramSocket.close();
        }
    }

    利用UDP实现多次双向交互
    多次双向

    UDP和TCP通信的区别
    1.是否面向连接:TCP是面向连接,点对点的通信, 而UDP是非连接的
    2.可靠性:TCP传输数据内容可靠,而UDP数据的顺序无法确定,不可靠
    3.传输大小:TCP无限制,UDP单包的传输大小限制在64K以内。
    4.传输效率: UDP>TCP

    public class UdpClient {
        public static void main(String[] args) throws Exception{
            Scanner input = new Scanner(System.in);
            //1.创建数据报套接字
            DatagramSocket datagramSocket = new DatagramSocket(6666);
            while(true){
                String content = input.nextLine();
                byte[] bs = content.getBytes();
                //2.创建数据报包
                DatagramPacket datagramPacket = new DatagramPacket(bs, bs.length, InetAddress.getLocalHost(), 8888);
                //3.发送数据
                datagramSocket.send(datagramPacket);
                if("bye".equals(content)){
                    break;
                }
                //4.接受数据报包
                byte[] bs2 = new byte[1024];
                DatagramPacket datagramPacket2 = new DatagramPacket(bs2, bs2.length);
                datagramSocket.receive(datagramPacket2);
                //5.获取数据报包中数据
                byte[] data = datagramPacket2.getData();
                System.out.println("客服说:"+new String(data,0,data.length));
            }
            //6.关闭套接字
            datagramSocket.close();
        }
    }
    /**
     * 客服
     * @author Administrator
     *
     */
    public class UdpServer {
        public static void main(String[] args) throws Exception{
            Scanner input = new Scanner(System.in);
            //1.创建数据报套接字
            DatagramSocket datagramSocket = new DatagramSocket(8888);
            while(true){
                //2.接受数据报包
                byte[] bs2 = new byte[1024];
                DatagramPacket datagramPacket2 = new DatagramPacket(bs2, bs2.length);
                datagramSocket.receive(datagramPacket2);
                //3.获取数据报包中数据
                byte[] data = datagramPacket2.getData();
                System.out.println("顾客说:"+new String(data,0,data.length));
                
                String content = input.nextLine();
                byte[] bs = content.getBytes();
                //4.创建数据报包
                DatagramPacket datagramPacket = new DatagramPacket(bs, bs.length, InetAddress.getLocalHost(), 6666);
                //5.发送数据
                datagramSocket.send(datagramPacket);
                if("bye".equals(content)){
                    break;
                }
                
            }
            //6.关闭套接字
            datagramSocket.close();
        }
    }
  • 相关阅读:
    Microsoft EBooks
    JavaScript 数据访问(通译自High Performance Javascript 第二章) [转]
    time random sys os模块
    configparser logging collections 模块
    序列化模块和hashlib模块
    内置方法
    面向对象进阶
    property classmethod staticmethod的用法
    归一化设计,抽象类和接口类,接口隔离操作
    面向对象的三大属性
  • 原文地址:https://www.cnblogs.com/fwdsz/p/6792702.html
Copyright © 2020-2023  润新知