zoukankan      html  css  js  c++  java
  • 23.网络.md


    目录

    1.基本概念

    • 定义:网络号+主机号。是四个32位的二进制数据,为方便记忆划分为四个8位。
      Demo:

    连接特定的 DNS 后缀 . . . . . . . : hollysys.net

    本地链接 IPv6 地址. . . . . . . . : fe80::a1e4:76bc:79be:9806%11
    IPv4 地址 . . . . . . . . . . . . : 172.21.32.29
    子网掩码 . . . . . . . . . . . . : 255.255.255.0
    默认网关. . . . . . . . . . . . . : 172.21.32.254

    这里的172.21.32三位都是网络号,最后的29是主机号。划分的依据是子网掩码中,255段都表示这是网络号段,最后的0是主机号段。

    • 要素:

      • IP

      • 端口

      • 协议

    • 分类:
      类别 | 内容 | 数量 | 使用范围
      -------|--------------------------------------------------|-----------------
      A类 | 一个网络号+三个主机号 | 2^24个 | 国家使用
      B类 | 两个个网络号+两个个主机号 | 2^12个 | 事业单位使用

      C类 | 三个网络号+一个主机号 | 2^8个 | 私人使用

    2.常用函数

    package per.liyue.code.net;
    
    
    import java.net.InetAddress;
    import java.net.UnknownHostException;
    
    
    public class GetIpAddress {
    	public static void main(String[] args) throws UnknownHostException{
    		//这个类没有构造,所以静态函数获取对象
    		InetAddress ip = InetAddress.getLocalHost();
    		//获取ip地址
    		System.out.println("我的Ip地址:" + ip.getHostAddress());
    		//获取机器名
    		System.out.println("我的Ip机器名:" + ip.getHostName());
    		
    		//获取其他机器的IP信息-getByName既可以填出机器名,也可以填充IP
    		String otherIp = "172.21.32.20";
    		String nameIp = "AMS97-PC";
    		InetAddress getIP = InetAddress.getByName(otherIp);
    		System.out.println("目标机器的IP是:" + getIP.getHostName());
    		InetAddress getName = InetAddress.getByName(nameIp);
    		System.out.println("目标机器的IP是:" + getName.getHostAddress());
    		
    		//可以用于获取某个域名下的IP
    		InetAddress[] a = InetAddress.getAllByName("www.hollysys.com");
    		for (InetAddress inetAddress : a) {
    			System.out.println("net:" + inetAddress.getHostAddress());
    		}
    	}
    }
    

    3.端口

    • 端口范围:0~65535,其中
      • 0~1023:系统端口:系统紧密绑定

      • 1024~49151:注册端口:系统松散绑定

      • 1024~65535:可用,如果出错则换另一个

    4.协议

    不同的协议对应不同的Scoket:
    *
    *

    4.1UDP

    4.1.1特点

    • 不需要建立连接
    • 每包大小64K
    • 速度快,非可靠(丢包)
    • 不区分客户端服务端,之区分发送端和接收端

    4.1.2代码步骤

    步骤

    • 发送端:

      • 建立服务DatagramSocket()

      • 创建数据包public DatagramPacket(byte buf[], int length,

                        InetAddress address, int port)    * 发送数据DatagramSocket.send()
        
      • 关闭资源

    • 接收端:

      • 建立服务绑定端口:public DatagramSocket(int port)

      • 创建数据包接收:public DatagramPacket(byte buf[], int length)

      • 用阻塞方法接收数据:DatagramSocket.receive()

      • 关闭资源

    4.1.3UDPDemo

    Demo:

    package per.liyue.code.udptest;
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.net.SocketException;
    import java.net.UnknownHostException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Timer;
    /*
     * Udp发送类,用于发送数据
     */
    public class UdpSender {
        public static void main(String[] args) throws IOException {
            //建立socket
            DatagramSocket socketSend = new DatagramSocket();
            
            //创建数据包
            String sendConcent = "这是我发送的一包数据";
            /*
             * 这里使用DatagramPacket来存放发送数据,使用的构造是:
             * public DatagramPacket(byte buf[],         //缓冲数组存放发送数据
             *                          int length,         //要用缓冲数组的长度
             *                          InetAddress address,//目标IP地址
             *                          int port            //目标端口
             *                         )
             * 
             * */
            DatagramPacket packetSend = new DatagramPacket(sendConcent.getBytes(), sendConcent.getBytes().length, InetAddress.getLocalHost(), 10001);
            
            //发送数据
            socketSend.send(packetSend);
            socketSend.close();
            System.out.println("数据已经发送,时间:" + new SimpleDateFormat("yyyy-MM-DD HH-mm-ss").format(new Date()));
        }
    }
    
    package per.liyue.code.udptest;
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.SocketException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    /*
     * Udp接收数据类,用于接收数据
     */
    public class UdpReceive {
        public static void main(String[] args) throws IOException {
            //建立socket
            DatagramSocket socketReceive = new DatagramSocket(10001);
            
            System.out.println("接收端开启监听...");
            
            //数据包接收
            byte[] bufRecive = new byte[1024];
            /*
             * 用DatagramPacket来接收数组,这里要用构造:
             * public DatagramPacket(byte buf[], //缓冲数组来接收,数据实际存放于数组中
             *                          int length) //缓冲数组长度    
             */
            DatagramPacket packetReceive = new DatagramPacket(bufRecive, bufRecive.length);
            
            //这个方法是阻塞的:This method blocks until a datagram is received。收到数据才执行
            socketReceive.receive(packetReceive);
            socketSend.close();
            //要注意的是
            System.out.println("接收到数据:" + new String(bufRecive, 0, packetReceive.getLength()));
            System.out.println("接收时间:" + new SimpleDateFormat("yyyy-MM-DD HH-mm-ss").format(new Date()));
            
        }
    }
    

    4.1.4通信格式

    一般的通信中,数据内容有规定的格式,否则当垃圾数据处理,例如飞秋的为:

    version:time:sender:ip:flag:concnet

    • 这里的版本号强制使用1.0
    • 时间使用系统时间
    • 发送人随意
    • ip是给对方显示地址
    • flag强制为32
    • concent是真正的内容
    package per.liyue.code.udptest;
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.net.SocketException;
    public class UdpSendFeiQ {
        public static void main(String[] args) throws IOException {
            DatagramSocket send = new DatagramSocket();
            
            String concent = getconcent("飞啊飞");
            System.out.println("发送内容: " + concent);
            DatagramPacket packet = new DatagramPacket(concent.getBytes(), concent.getBytes().length,
                                                       InetAddress.getByName("172.21.32.20"), 2425);
            send.send(packet);
            send.close();
        }
        /*
         * 飞秋的数据格式:version:time:sender:ip:flag:concnet
         *                 1.0                    32
         */
        
        public static String getconcent(String concent) {
            StringBuilder builder = new StringBuilder();
            builder.append("1.0:");
            builder.append(System.currentTimeMillis() + ":");
            builder.append("172.21.32.30:");
            builder.append("超人:");
            builder.append("32:");
            builder.append(concent);
            return builder.toString();
        }
    }
    

    广播地址:在UDP中将主机号修改为255就是网络广播地址,会群发。例如飞秋的地址为:

    172.21.32.255

    4.1.5 群发Demo:

    package per.liyue.code.udptest;
    
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.lang.Runnable;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.net.SocketException;
    import java.net.UnknownHostException;
    
    
    public class ChatSender implements Runnable {
    	@Override
    	public void run() {
    		try {
    			//
    			DatagramSocket send = new DatagramSocket();
    			
    			//
    			BufferedReader read = new BufferedReader(
    									new InputStreamReader(System.in));
    			String line = null;
    			DatagramPacket packet = null;
    			while((line = read.readLine()) != null){
    				packet = new DatagramPacket(line.getBytes(), line.getBytes().length,
    											InetAddress.getLocalHost(), 10001);
    				send.send(packet);
    			}
    			send.close();
    		} catch (SocketException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (UnknownHostException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		
    		
    	}
    }
    
    
    
    package per.liyue.code.udptest;
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.SocketException;
    public class ChatReceive implements Runnable {
        @Override
        public void run() {
            try {
                // TODO Auto-generated method stub
                DatagramSocket socket = new DatagramSocket(10001);
                byte[] concent = new byte[1024];
                DatagramPacket packet = new DatagramPacket(concent, concent.length);
                
                boolean flag = true;
                while (flag) {
                    socket.receive(packet);
                    System.out.println(
                            packet.getAddress().getHostName() + "说:" + 
                            new String(concent, 0, concent.length));
                }
                socket.close();
                
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    
    package per.liyue.code.udptest;
    public class ChatMain {
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            ChatReceive receive = new ChatReceive();
            ChatSender send = new ChatSender();
            new Thread(receive).start();
            new Thread(send).start();
        }
    }
    

    4.1.6丢失数据的情况

    • 带宽不够
    • cpu处理能力不足

    目录

    目录


    4.2TCP

    • 面向连接:建立连接
    • 大数据,数据传输时候没有大小限制
    • 效率相对低:三次握手机制,可靠
    • 区分客户端服务的

    4.2.1三次握手机制

    发送数据之前要检查通路是否正常,所以是可靠连接。

    4.2.2通信范例

    • 客户端:发送命令方-》Socket类
    • 服务端:接收命令方-》ServerSocket类

    4.2.2.1单次通信

    Demo:
    单次建立连接通信:

    package per.liyue.code.tcptest;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.InetAddress;
    import java.net.Socket;
    import java.net.UnknownHostException;
    public class Client {
        public static void main(String[] args) throws UnknownHostException, IOException {
            //建立socket链接,指定IP和端口号
            Socket socket = new Socket(InetAddress.getLocalHost(), 10001);
            //获取到输出流
            OutputStream out = socket.getOutputStream();
            
            String conent = "我是客户端,向服务端发送数据了!";
            //这里用输出流的写方法发送
            out.write(conent.getBytes());
            //关闭资源,输出流是从Socket中获取,所以关闭Socket就可以了
            socket.close();
        }
    }
    
    package per.liyue.code.tcptest;
    import java.io.BufferedInputStream;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    public class Server {
        public static void main(String[] args) throws IOException {
            //建立服务端监听端口
            ServerSocket sSocket = new ServerSocket(10001);
            
            //accept方法本身也是阻塞的方法
            Socket socket = sSocket.accept();
            //因为ServerSocket本身没有流对象的获取,所以要从Socket中获取,客户端发送的时候已经将流发送
            
            InputStream in = socket.getInputStream();
            
            byte[] b = new byte[1024];
            int length = in.read(b);
            //打印接收内容
            System.out.println("服务器接收到的数据:" + new String(b, 0, length));
            //关闭资源,输入流和Socket都是通过ServerSocket获取,所以关闭一个即可
            sSocket.close();
        }
    }
    

    注意:为什么不对ServerSocket提供getInputStream和getOutputStream,因为如果ServerSocket本身有提供,在多客户端连接时候,服务端回复的话一个输入输出不能辨别出回复到哪个客户端。所以设计了Socket提供。

    4.2.2.2持久化通信

    Demo:

    package per.liyue.code.tcptest;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.net.InetAddress;
    import java.net.Socket;
    import java.net.UnknownHostException;
    import com.sun.imageio.plugins.common.InputStreamAdapter;
    /*
     * TCp实现客户端和服务器互相通信
     */
    public class ClientChat {
        public static void main(String[] args) {
            try {
                System.out.println("客户端已经打开,准备发送...");
                
                //创建
                Socket socket = new Socket(InetAddress.getLocalHost(), 10001);
                
                OutputStream out = socket.getOutputStream();
                //将字符流转换为字节流方便传输
                OutputStreamWriter send = new OutputStreamWriter(out);
                
                //获取键盘输入流,将输入的字节流转化为字符流
                InputStreamReader in =  new InputStreamReader(System.in);
                BufferedReader bufRead = new BufferedReader(in);
                
                String line = null;
                while((line=bufRead.readLine()) != null){
                    /*
                     * 将输入的内容发送
                     * 注意:因为接收的时候也以readLine来接收,这个方法以回车换行来判断,
                     *       但是这里的获取输入并不会增加换行回车,所以得手动增加
                     */
                    send.write(line + "
    ");
                    //这里不能忘记刷新,否则内容只存在于缓存数组中
                    send.flush()  
                }
                socket.close();
                
            } catch (UnknownHostException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            
        }
    }
    
    package per.liyue.code.tcptest;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.ServerSocket;
    import java.net.Socket;
    public class ServerChat {
        public static void main(String[] args) {
            
            try {
                System.out.println("服务端已经打开,等待接收...");
                
                //创建ServerSocket
                ServerSocket sSocket = new ServerSocket(10001);
                //获取Socket对象
                Socket socket = sSocket.accept();
                //获取输入流
                InputStream in =  socket.getInputStream();
                InputStreamReader inRead = new InputStreamReader(in);
                
                //将收到的字节流转换为字符流方便输出
                BufferedReader read = new BufferedReader(inRead);
                
                String line = null;
                while ((line = read.readLine()) != null) {
                    System.out.println("服务端收到:" + line);
                }
                sSocket.close();  
                
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
    }
    

    4.2.2.3持久化相互通信

    Demo:

    package per.liyue.code.tcptest;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.net.InetAddress;
    import java.net.Socket;
    import java.net.UnknownHostException;
    import com.sun.imageio.plugins.common.InputStreamAdapter;
    /*
     * TCp实现客户端和服务器互相通信
     */
    public class ClientChat {
        public static void main(String[] args) {
            try {
                System.out.println("客户端已经打开,准备发送...");
                /*
                 * 输出流准备
                 */
                //创建
                Socket socket = new Socket(InetAddress.getLocalHost(), 10001);
                
                OutputStream out = socket.getOutputStream();
                //将字符流转换为字节流方便传输
                OutputStreamWriter send = new OutputStreamWriter(out);
                
                //获取键盘输入流,将输入的字节流转化为字符流
                InputStreamReader in =  new InputStreamReader(System.in);
                BufferedReader bufRead = new BufferedReader(in);
                
                String line = null;
                
                /*
                 * 输入准备
                 */
                //获取输入流
                //获取输入内容
                BufferedReader readFormServer = new BufferedReader(
                                        new InputStreamReader(socket.getInputStream())
                                                         );
                
                while((line=bufRead.readLine()) != null){
                    /*
                     * 将输入的内容发送
                     * 注意:因为接收的时候也以readLine来接收,这个方法以回车换行来判断,
                     *       但是这里的获取输入并不会增加换行回车,所以得手动增加
                     */
                    send.write(line + "
    ");
                    //这里不能忘记刷新,否则内容只存在于缓存数组中
                    send.flush();
                    
                    //收到服务端
                    String lineRead = readFormServer.readLine();
                    System.out.println("客户端收到:" + lineRead);    
                }
                socket.close();
                
            } catch (UnknownHostException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            
        }
    }
    
    package per.liyue.code.tcptest;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.net.ServerSocket;
    import java.net.Socket;
    public class ServerChat {
        public static void main(String[] args) {
            
            try {
                System.out.println("服务端已经打开,等待接收...");
                
                /*
                 * 获取输入准备
                 */
                //创建ServerSocket
                ServerSocket sSocket = new ServerSocket(10001);
                //获取Socket对象
                Socket socket = sSocket.accept();
                //获取输入流
                InputStream in =  socket.getInputStream();
                InputStreamReader inRead = new InputStreamReader(in);
                
                //将收到的字节流转换为字符流方便输出
                BufferedReader read = new BufferedReader(inRead);
                
                String line = null;            
                /*
                 * 输出准备
                 */
                //获取输出流
                OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream());
                //获取准备输出的数据
                BufferedReader write = new BufferedReader(new InputStreamReader(System.in));
                
                while ((line = read.readLine()) != null) {
                    System.out.println("服务端收到:" + line);
                    
                    String lineWrite = write.readLine();
                    out.write("服务端说:" + lineWrite + "
    ");
                    out.flush();
                }
                sSocket.close();
                
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
    }
    
  • 相关阅读:
    IT运维监控解决方案介绍
    Apdex——衡量服务器性能的标准
    服务器监控(包括性能指标与web应用程序)
    使用厂商MIB库查找设备OID值并实施监控的方法
    华为USG6550 MIB CPU MEM
    LInux下实时网络流量监控工具nload教程
    11gR2 集群(CRS/GRID)新功能—— SCAN(Single Client Access Name)
    如何实现网卡bond
    LeetCode(31)-Factorial Trailing Zeroes
    activiti自己定义流程之整合(五):启动流程时获取自己定义表单
  • 原文地址:https://www.cnblogs.com/bugstar/p/8492825.html
Copyright © 2011-2022 走看看