• 网络编程


    网络编程三要素:
        A:IP地址
        B:端口
        C:协议
    
    
    举例:
        我想要和林青霞说话了。肿么办?
        A:我要找到林青霞。
        B:对她说话,要对耳朵说
        C:我说什么呢?"I Love You"
         但是,她没学过英语,听不懂
         我没必要说英语,说汉语就可以了:我爱你
         
    
    IP地址:
        网络中计算机的唯一标识
        
        计算机只能识别二进制的数据,所以我们的IP地址应该是一个二进制的数据。
        但是我们配置的IP地址不是二进制的,为什么呢?
            IP:192.168.1.100
            换算:11000000 10101000 00000001 01100100
        假如真是:11000000 10101000 00000001 01100100
        我们如果每次使用网络就这样配置IP地址,记忆起来很麻烦
        所以为了方便表示IP地址,我们就把IP地址每一个字节上的数据换算成为十进制,然后用.隔开来表示:
            “点分十进制”
                
        IP地址的组成:网络号段+主机号段
            A类:一个号段为网络号段+后三段的主机号段
                一个网络号:256*256*256=16777216
            B类:前二号段为网络号段+后两段的主机号
                一个网络号:256*256=65536
            C类:前3号段为网络号段+后一段的主机号段
                一个网络号:256
                
        两个DOS命令:
            ipconfig:查看本机地址
            ping 后面跟ip地址:测试本机与指定的IP地址间的通信是否有问题
            
        特殊的ip地址
            127.0.0.1 回环地址(表示本机)
            x.x.x.255广播地址
            x.x.x.0网络地址
            
    为了方便使用IP,java提供InetAccess
        
    端口:
        正在运行的程序的标识
        有效端口:0~65535,其中0~1024系统使用或者保留。可以使用360查看各个程序的端口
                
    
    协议:
        通信的规则
        
        UDP:
            把数据打包
            数据有限制64k
            不建立连接
            速度快
            不可靠
            
        TCP:
            建立连接通道
            数据无限制
            速度慢
            可靠
            
        举例:
            UDP:发短信
            TCP:打电话
        

    InetAccess:

    package com.gz_02;
    
    import java.net.InetAddress;
    import java.net.UnknownHostException;
    
    /*
     * 如果一个类没有构造方法:
     *     A:成员方法全部是静态的
     *     B:单例模式
     *     C:类中有静态方法返回该类的对象
     * 
     * 
     * 看InetAddress的成员方法:
     *     public static InetAddress getByName(String host) 根据主机名或者IP地址的字符串表示得到I[地址对象
     */
    public class InetAddressDemo {
        public static void main(String[] args) throws UnknownHostException {
            InetAddress address=InetAddress.getByName("192.168.1.100");
            
            //publicStringgetHostName()
            String name=address.getHostName();
            
            //public String getHostAddress()
            String ip=address.getHostAddress();
            
            System.out.println(name+"---"+ip);
        }
    }
    View Code

    UDP:

    package com.gz_03;
    
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    
    /*
     * UDP协议接受数据:
     *     A:创建发送端Socket对象
     *     B:创建一个数据包(接受容器)
     *     C:调用Socket对象的接受方法接受方法
     *     D:解析数据包并显示在数据台
     *     D:释放资源
     *
     */
    public class ReceiveDemo {
        public static void main(String[] args) throws IOException {
            //创建Socket对象
            //DatagramSocket(int port)
            DatagramSocket ds=new DatagramSocket(10670);
            
            //创建一个数据包(接受容器)
            //DatagramPacket(byte[] buf,int length)
            byte[] bys=new byte[1024];
            int length=bys.length;
            
            DatagramPacket dp=new DatagramPacket(bys, length);
            
            //调用Socket对象的接受方法接受数据,在接受到数据前一直被阻塞
            //public void receive(DatagramPacket p)
            ds.receive(dp);
            
            //接受到了数据要显示下
            //解析数据包,并显示在数据台
            //byte[] getData()
            //int getLength()获取数据长度
            byte[] bys2=dp.getData();
            int len=dp.getLength();
            String s=new String(bys2,0,len);
            //获取对方ip
            //public InetAddress getAddress()
            InetAddress address=dp.getAddress();
            String ip=address.getHostAddress();
            System.out.println(ip+":"+s);
            
            //释放资源
            ds.close();
        }
    
    }
    package com.gz_03;
    
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.net.SocketException;
    import java.net.UnknownHostException;
    
    /*
     * UDP协议发送数据:
     *     A:创建发送端Socket对象
     *     B:创建数据,并把数据打包
     *     C:调用Socket对象的发送方法发送数据包
     *     D:释放资源
     */
    public class SendDemo {
        public static void main(String[] args) throws IOException {
            //创建发送端Socket对象
            //DatagrameSocket()
            DatagramSocket ds=new DatagramSocket();
            
            //创建数据,并把数据打包
            //DatagramPacket(byte[] buf,int length,InetAddress address,int port)
            
            //创建数据
            byte[] bys="我是郭祯".getBytes();
            //长度
            int length=bys.length;
            //IP地址对象
    //        InetAddress address=InetAddress.getByName("192.168.1.129");
            InetAddress address=InetAddress.getByName("192.168.1.129");
            //端口
    //        int port=6000;
            int port=10670;
            DatagramPacket dp=new DatagramPacket(bys, length, address, port);
            //调用Socket对象的发送方法发送数据包
            //public void send(DatagreamPacket p)
            ds.send(dp);
            
            //释放资源
            ds.close();
        }
    }
    View Code

    UDP简单聊天:

    package com.gz_06;
    
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.net.UnknownHostException;
    import java.util.Scanner;
    /*
     * UDP协议发送数据:
     *     A:创建发送端Socket对象
     *     B:创建数据,并把数据打包
     *     C:调用Socket对象的发送方法发送数据包
     *     D:释放资源
     */
    public class SendThread implements Runnable {
        private DatagramSocket ds;
        public SendThread(DatagramSocket ds){
            this.ds=ds;
        }
        @Override
        public void run() {    
            try{
                while(true){
                    Scanner input=new Scanner(System.in);
                    String str=input.nextLine();
                    DatagramPacket dp=null;
                    try {
                        dp=new DatagramPacket(str.getBytes(), str.getBytes().length, InetAddress.getByName("192.168.1.100"), 12306);
                    } catch (UnknownHostException e) {
                        e.printStackTrace();
                    }
                    ds.send(dp);
                }
            }catch(IOException e){
                e.printStackTrace();
            }finally{
                ds.close();
            }
            
            
        }
    
    }
    package com.gz_06;
    
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    /*
     * UDP协议接受数据:
     *     A:创建发送端Socket对象
     *     B:创建一个数据包(接受容器)
     *     C:调用Socket对象的接受方法接受方法
     *     D:解析数据包并显示在数据台
     *     D:释放资源
     *
     */
    public class ReceieveThread implements Runnable {
        private DatagramSocket ds;
        public ReceieveThread(DatagramSocket ds){
            this.ds=ds;
        }
        @Override
        public void run() {
            try{
                while(true){
                    byte[] buff=new byte[1024];
                    DatagramPacket dp=new DatagramPacket(buff, buff.length);
                    ds.receive(dp);
                    byte[] b=dp.getData();
                    InetAddress ia=dp.getAddress();
                    String ip=ia.getHostAddress();
                    System.out.println(ip+":"+new String(b,0,dp.getLength()));
                }
            }catch(IOException e){
                e.printStackTrace();
            }finally{
                ds.close();
            }
            
        }
    
    }
    package com.gz_06;
    
    import java.io.IOException;
    import java.net.DatagramSocket;
    
    public class CharRoom {
        public static void main(String[] args) throws IOException{
            DatagramSocket st=new DatagramSocket();
            DatagramSocket ds=new DatagramSocket(12306);
            
            SendThread sd=new SendThread(st);
            ReceieveThread re=new ReceieveThread(ds);
            
            new Thread(sd).start();
            new Thread(re).start();
        }
    
    }
    View Code

    TCP:

    package com.gz_07;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.Socket;
    
    /*
     * A:创建发送端的Socket对象
     *     这一步如果成功,就说明连接已经成功了
     * B:获取输出流,写数据
     * C:释放资源
     *
     *Connection refused
     *连接被拒绝。tcp一定要服务器被开启,因为tcp要建立连接
     *而ucp不需要,ucp不保证数据一定过去对面接收到
     */
    public class ClientDemo {
        public static void main(String[] args) throws IOException {
            //创建发送端的Socket对象
            //Socket(InetAdderss address,int port)
            //Socket(String host,int port)
            Socket s=new Socket("192.168.1.100",8888);
            
            //获取输出流,写数据
            OutputStream os=s.getOutputStream();
            os.write(("hello,tcp,我来了").getBytes());
            InputStream in=s.getInputStream();
            byte[] b=new byte[1024];
            int t=in.read(b);//阻塞式
            String str=new String(b,0,t);
            System.out.println(str);
            
            s.close();
        }
    }
    package com.gz_07;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    /*
     * TCP协议接受数据
     *     A:创建接收端的Socket对象
     *     B:监听客户端连接返回一个对应的Socket对象
     *     C:获取输入流读取数据,显示在控制台
     *     D:释放资源
     */
    public class ServerDemo {
        public static void main(String[] args) throws IOException {
            //ServerSocket(port)
            ServerSocket s=new ServerSocket(8888);
            
            Socket ss=s.accept();//阻塞式方法,侦听并接受到此套间的连接,返回对应的Socket对象
            
            InputStream is=ss.getInputStream();
            
            byte[] bys=new byte[1024];
            int len=is.read(bys);
            String str=new String(bys,0,len);
            String str1=ss.getInetAddress().getHostAddress();
            System.out.println(str1+":"+str);
            OutputStream os=ss.getOutputStream();
            os.write("收到了".getBytes());
            ss.close();
            //s.close();服务器不应该关闭
        }
    }
    View Code

    关于反馈:

    package com.gz_08;
    
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class ServerDemo02 {
        public static void main(String[] args) throws IOException {
            ServerSocket ss=new ServerSocket(8888);
            
            Socket s=ss.accept();//阻塞式 排除
            System.out.println(s.getInetAddress().getHostAddress());
            BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
            BufferedWriter bw=new BufferedWriter(new FileWriter("copy.txt"));
            String line=null;
            while((line=br.readLine())!=null){
                //阻塞式 阻塞了 无法判断得到的输入流是否是结束的,所以一直在等待,怎么办呢?
                //方式一:自定义一个结束标记,这里收到结束标记就不等待了。自定义结束标记如果文件中存在自定义结束标记就会出问题。其他还好
                //方式二:java api提供了一个方法s.shutdownOutput(); 写入关闭,也就是完成
    //            if("over".equals(line)){
    //                break;
    //            }
                bw.write(line);
                bw.newLine();
                bw.flush();
            }
            
            //接受到了数据,我希望给出一个反馈
            OutputStream os=s.getOutputStream();
            os.write("完成上传!".getBytes());
            
            //经过测试,我们发现:程序不是按照我们想要的流程走。它迟迟不给出反馈。这是为什么呢?我们有几个阻塞式方法,问题肯定是出现在那里的
            //判断是在这里的while循环的read方法处阻塞了
            s.close();
        }
    }
    package com.gz_08;
    
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.net.Socket;
    import java.net.UnknownHostException;
    
    public class ClientDemo02 {
        public static void main(String[] args) throws UnknownHostException, IOException {
            Socket s=new Socket("192.168.1.100",8888);
            
            BufferedReader br=new BufferedReader(new FileReader("src/网络编程三要素"));
            BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
            
            String line=null;
            while((line=br.readLine())!=null){
                bw.write(line);
                bw.newLine();
                bw.flush();
            }
    //        bw.write("over");
    //        bw.newLine();
    //        bw.flush();
            s.shutdownOutput();//写入完成
            
            BufferedReader fr=new BufferedReader(new InputStreamReader(s.getInputStream()));
            byte[] b=new byte[1024];
            String str=fr.readLine();
            System.out.println(str);
            br.close();
            bw.close();
        }
    }
    View Code

    多线程模拟:

    package com.gz_09;
    
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.net.Socket;
    
    public class UploadClient {
        public static void main(String[] args) throws IOException {
            // 创建客户端Socket对象
            Socket s = new Socket("192.168.1.100", 11101);
    
            // 封装文本文件
            // BufferedReader br = new BufferedReader(new FileReader(
            // "InetAddressDemo.java"));
            BufferedReader br = new BufferedReader(new FileReader(
                    "TCP编程"));
            // 封装通道内流
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                    s.getOutputStream()));
    
            String line = null;
            while ((line = br.readLine()) != null) { // 阻塞
                bw.write(line);
                bw.newLine();
                bw.flush();
            }
    
            // Socket提供了一个终止,它会通知服务器你别等了,我没有数据过来了
            s.shutdownOutput();
    
            // 接收反馈
            BufferedReader brClient = new BufferedReader(new InputStreamReader(
                    s.getInputStream()));
            String client = brClient.readLine(); // 阻塞
            System.out.println(client);
    
            // 释放资源
            br.close();
            s.close();
        }
    }
    package com.gz_09;
    
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class UploadServer {
        public static void main(String[] args) throws IOException {
            // 创建服务器Socket对象
            ServerSocket ss = new ServerSocket(11101);
    
            while (true) {
                Socket s = ss.accept();
                new Thread(new UserThread(s)).start();
            }
        }
    }
    package com.gz_09;
    
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.net.Socket;
    
    public class UserThread implements Runnable {
        private Socket s;
    
        public UserThread(Socket s) {
            this.s = s;
        }
    
        @Override
        public void run() {
            try {
                // 封装通道内的流
                BufferedReader br = new BufferedReader(new InputStreamReader(
                        s.getInputStream()));
                // 封装文本文件
                // BufferedWriter bw = new BufferedWriter(new
                // FileWriter("Copy.java"));
    
                // 为了防止名称冲突
                String newName = System.currentTimeMillis() + ".java";
                BufferedWriter bw = new BufferedWriter(new FileWriter(newName));
    
                String line = null;
                while ((line = br.readLine()) != null) { // 阻塞
                    bw.write(line);
                    bw.newLine();
                    bw.flush();
                }
    
                // 给出反馈
                BufferedWriter bwServer = new BufferedWriter(
                        new OutputStreamWriter(s.getOutputStream()));
                bwServer.write("文件上传成功");
                bwServer.newLine();
                bwServer.flush();
    
                // 释放资源
                bw.close();
                s.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    }
    View Code

     前面一直以为使用TCP同一个Socket不可以多次通信。现在发现单纯使用flush方法不使用shutdownInput或者shutdownOutput也可以在服务器读取多次并回复多次。

    代码:

    package com.client;
    
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.net.Socket;
    import java.net.UnknownHostException;
    
    import com.hh.ReadDemo;
    import com.hh.WriterDemo;
    
    public class ClientDemo {
        /**
         * 项目需求分析:
         *     客户端发送数据支持对线程,所以服务器接收数据也应该是多线程
         * 现在主要是想测试一下直接使用一个Tcp进行聊天并且多条语句
         */
        private Socket s=null;
        DataInputStream dis=null;
        DataOutputStream dos=null;
        public static void main(String[] args) {
            ClientDemo cd=new ClientDemo();
            cd.init();
            System.out.println("可以和服务器进行交流了");
            //while(true){ 不能新建太多线程,所以我尝试将while循环卸载线程的run方法
                new Thread(new ReadDemo(cd.s)).start();
                new Thread(new WriterDemo(cd.s)).start();
            //}
            
        }
        public void init(){
            try {
                s=new Socket("127.0.0.1",8888);
                dis=new DataInputStream(s.getInputStream());
                dos=new DataOutputStream(s.getOutputStream());
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
    //    public void write(){
    //        Scanner sc=new Scanner(System.in);
    //        String s=sc.next();
    //        try {
    //            dos.writeUTF(s);
    //            dos.flush();
    //        } catch (IOException e) {
    //            e.printStackTrace();
    //        }
    //    }
    //    public void read(){
    //        try {
    //            String s=dis.readUTF();
    //            System.out.println(s);
    //        } catch (IOException e) {
    //            e.printStackTrace();
    //        }
    //    }
        
    }
    package com.server;
    
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    import com.hh.ReadDemo;
    import com.hh.WriterDemo;
    
    public class ServerDemo {
        public static void main(String[] args) {
            try {
                ServerSocket server=new ServerSocket(8888);
                Socket s=server.accept();
                //while(true){
                    new Thread(new ReadDemo(s)).start();
                    new Thread(new WriterDemo(s)).start();
                //}
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    package com.hh;
    
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.net.Socket;
    
    public class ReadDemo implements Runnable{
        private Socket s;
        private DataInputStream dis=null;
        private DataOutputStream dos=null;
        public ReadDemo(Socket s){
            this.s=s;
            try {
                dis=new DataInputStream(s.getInputStream());
                dos=new DataOutputStream(s.getOutputStream());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void run() {
            try {
                while(true){
                    String str=dis.readUTF();
                    System.out.println(str);
                }
                
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    }
    package com.hh;
    
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.net.Socket;
    import java.util.Scanner;
    
    public class WriterDemo implements Runnable{
        private Socket s;
        private DataInputStream dis=null;
        private DataOutputStream dos=null;
        public WriterDemo(Socket s){
            this.s=s;
            try {
                dis=new DataInputStream(s.getInputStream());
                dos=new DataOutputStream(s.getOutputStream());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void run() {
            while(true){
                Scanner sc=new Scanner(System.in);
                try {
                    String str=sc.next();
                    dos.writeUTF(str);
                    dos.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            
        }
    }
    View Code
  • 相关阅读:
    谈谈服务限流算法的几种实现
    使用 MongoDB 存储日志数据
    MongoDB存储引擎选择
    下载一线视频
    spring-boot-starter-redis配置详解
    SpringBoot学习笔记(6) SpringBoot数据缓存Cache [Guava和Redis实现]
    Guava 源码分析(Cache 原理)
    分布式链路跟踪 Sleuth 与 Zipkin【Finchley 版】
    Dubbo x Cloud Native 服务架构长文总结(很全)
    区块链使用Java,以太坊 Ethereum, web3j, Spring Boot
  • 原文地址:https://www.cnblogs.com/aigeileshei/p/5604185.html
Copyright © 2020-2023  润新知