• Java基础之网络编程


    1、网络编程概述
        (1)网络模型
            OSI参考模型
            TCP/IP参考模型
        (2)网络通讯要素
            IP地址
            端口号
            传输协议
        (3)网络通讯前提:
            **找到对方IP
            **数据要发送到指定端口。为了标示不同的应用程序,所以给这些网络应用程序都用数字进行标示,这个表示就叫端口。
            **定义通信规则。这个规则称为通信协议,国际组织定义了通用协议TCP/IP
        (4)计算机网络:
            是指将地理位置不同的具有独立功能的多台计算机及其外部设备,
            通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,
            实现资源共享和信息传递的计算机系统。
        (5)IP地址:
            IP地址 = 网络号码+主机地址

            A类IP地址:第一段号码为网络号码,剩下的三段号码为本地计算机的号码
            B类IP地址:前二段号码为网络号码,剩下的二段号码为本地计算机的号码
            C类IP地址:前三段号码为网络号码,剩下的一段号码为本地计算机的号码

            特殊地址:
            127.0.0.1 回环地址,可用于测试本机的网络是否有问题. ping 127.0.0.1   
            ipconfig:查看本机IP地址
            xxx.xxx.xxx.0 网络地址
            xxx.xxx.xxx.255 广播地址

            A类    1.0.0.1---127.255.255.254      10.X.X.X是私有地址(私有地址就是在互联网上不使用,而被用在局域网络中的地址)    (2)127.X.X.X是保留地址,用做循环测试用的。
            B类    128.0.0.1---191.255.255.254    172.16.0.0---172.31.255.255是私有地址。169.254.X.X是保留地址。
            C类    192.0.0.1---223.255.255.254    192.168.X.X是私有地址
            D类    224.0.0.1---239.255.255.254     
            E类    240.0.0.1---247.255.255.254
        (6)各种网络分类方式
            A:按网络覆盖范围划分
              局域网(几米至10公里以内)   城域网(10~100公里)   广域网(几百公里到几千公里)   国际互联网
            B:按网络拓扑结构划分
              总线型网络   星形网络   环型网络   树状网络   混合型网络
            C:按传输介质划分
              有线网   无线网
            D:按网络使用性质划分
              公用网   专用网
        (7)虚拟专用网络(Virtual Private Network ,简称VPN)指的是在公用网络上建立专用网络的技术。
            其之所以称为虚拟网,主要是因为整个VPN网络的任意两个节点之间的连接并没有传统专网
            所需的端到端的物理链路,而是架构在公用网络服务商所提供的网络平台,如Internet、
            ATM(异步传输模式〉、Frame Relay (帧中继)等之上的逻辑网络,
            用户数据在逻辑链路中传输。它涵盖了跨共享网络或公共网络的封装、
            加密和身份验证链接的专用网络的扩展。VPN主要采用了隧道技术、加解密技术、
            密钥管理技术和使用者与设备身份认证技术。
        (8)网络模型:
            ****OSI模型
                应用层
                表示层
                会话层
                传输层
                网络层
                数据连接层
                物理层
            ****TCP/IP模型
                应用层
                传输层
                网际层
                主机至网络层
    2、TCP和UDP
        (1)UDP和TCP的区别:
            UDP
            将数据及源和目的封装成数据包中,不需要建立连接
            每个数据报的大小在限制在64k内
            因无连接,是不可靠协议
            不需要建立连接,速度快
            TCP
            建立连接,形成传输数据的通道。
            在连接中进行大数据量传输
            通过三次握手完成连接,是可靠协议
            必须建立连接,效率会稍低
            注:三次握手:
            第一次:我问你在么?
            第二次:你回答在。
            第三次:我反馈哦我知道你在。
    3、Socket(UDP传输)
        **Socket就是为网络服务提供的一种机制。
        **通信的两端都有Socket。
        **网络通信其实就是Socket间的通信。
        **数据在两个Socket间通过IO传输。
        **玩Socket主要就是记住流程,代码查文档就行
        (1)UDP传输:DatagramSocket与DatagramPacket
            **发送端:
            建立DatagramSocket服务;
            提供数据,并将数据封装到字节数组中;
            创建DatagramPacket数据包,并把数据封装到包中,同时指定IP和接收端口
            通过Socket服务,利用send方法将数据包发送出去;
            关闭DatagramSocket和DatagramPacket服务。
            **接收端:
            建立DatagramSocket服务,并监听一个端口;
            定义一个字节数组和一个数据包,同时将数组封装进数据包;
            通过DatagramPacket的receive方法,将接收的数据存入定义好的数据包;
            通过DatagramPacke关闭t的方法,获取发送数据包中的信息;
            关闭DatagramSocket和DatagramPacket服务。
            DatagramSocket与DatagramPacket方法摘要:
            *****DatagramSocket
            构造方法:
            DatagramSocket()
                构造数据报套接字并将其绑定到本地主机上任何可用的端口。
            DatagramSocket(int port)
                创建数据报套接字并将其绑定到本地主机上的指定端口。
            DatagramSocket(int port, InetAddress laddr)
                创建数据报套接字,将其绑定到指定的本地地址。
            方法摘要:
            void close()
                关闭此数据报套接字。
            InetAddress getInetAddress()
                返回此套接字连接的地址。
            InetAddress getLocalAddress()
                获取套接字绑定的本地地址。
            int getPort()
                返回此套接字的端口。
            void receive(DatagramPacket p)
                从此套接字接收数据报包。
            void send(DatagramPacket p)
                从此套接字发送数据报包。
            ****DatagramPacket
            构造方法:
            DatagramPacket(byte[] buf, int length)
                构造 DatagramPacket,用来接收长度为 length 的数据包。
            DatagramPacket(byte[] buf, int length, InetAddress address, int port)
                构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
            InetAddress getAddress()
                返回某台机器的 IP 地址,此数据报将要发往该机器或者是从该机器接收到的。
            byte[] getData()
                返回数据缓冲区。
            int getLength()
                返回将要发送或接收到的数据的长度。
            int getPort()
                返回某台远程主机的端口号,此数据报将要发往该主机或者是从该主机接收到的。    
            代码示例:
            ****发送端:
            class UDPSend
            {
                public static void main(String[] args) throws Exception
                {
                    DatagramSocket ds = new DatagramSocket();
                    byte[] buf = "这是UDP发送端".getBytes();
                    DatagramPacket dp = new DatagramPacket(
                        buf,buf.length,InetAddress.getByName("192.168.1.253"),10000);
                    ds.send(dp);
                    ds.close();
                }
            }
            ****接收端
            class UDPRece
            {
                public static void main(String[] args) throws Exception
                {
                    DatagramSocket ds = new DatagramSocket(10000);
                    byte[] buf = new byte[1024];
                    DatagramPacket dp = new DatagramPacket(buf,buf.length);
                    ds.receive(dp);//将发送端发送的数据包接收到接收端的数据包中
                    String ip = dp.getAddress().getHosyAddress();//获取发送端的ip
                    String data = new String(dp.getData(),0,dp.getLength());//获取数据
                    int port = dp.getPort();//获取发送端的端口号
                    sop(ip+":"+data+":"+port);
                    ds.close();
                }
            }
            需求1:UDP键盘录入数据,并发送给接收端
            发送端:
            class UDPSend
            {
                public static void main(String[] args) throws Exception
                {

                    DatagramSocket ds = new DatagramSocket();
                    BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
                    String line = null;
                    while((line = bufr.readLine())!=null)
                    {
                        if("886".equals(line))
                            break;
                        byte[] buf = line.getBytes();
                        DatagramPacket dp = new DatagramPacket(
                            buf,buf.length,InetAddress.getByName("192.168.1.253"),10000);
                        ds.send(dp);
                    }
                    ds.close();
                }
                    
            }
            接收端:
            class UDPRece
            {
                public static void main(String[] args) throws Exception
                {
                    DatagramSocket ds = new DatagramSocket(10000);
                    while(true)
                    {
                        byte[] buf = new byte[1024];
                        DatagramPacket dp = new DatagramPacket(buf,buf.length);
                        ds.receive(dp);//将发送端发送的数据包接收到接收端的数据包中
                        String ip = dp.getAddress().getHosyAddress();//获取发送端的ip
                        String data = new String(dp.getData(),0,dp.getLength());//获取数据
                        int port = dp.getPort();//获取发送端的端口号
                        sop(ip+":"+data+":"+port);
                        ds.close();
                    }
                }
                
            }
            需求2:编写简单的聊天工具
            思路:
                使用多线程技术
            发送端:
            class UDPSend implements Runnable
            {
                private DatagramSocket ds;
                public UDPSend(){}
                public UDPSend(DatagramSocket ds)
                {
                    this.ds=ds;
                }
                public void run()
                {
                    try
                    {
                        BufferedReader bufr = new BufferedReader(
                                    new InputStreamReader(System.in));
                        String line = null;
                        while((line = bufr.readLine())!=null)
                        {
                            if("886".equals(line))
                                break;
                            byte[] buff = line.getBytes();
                            DatagramPacket dp = new DatagramPacket(
                            buf,buf.length,InetAddress.getByName("192.168.1.253"),10000);
                            ds.send(dp);
                        }
                    }
                    catch(Exception e)
                    {
                        throw new RuntimeException("发送失败");
                    }
                }
            }
            接收端:
            class UDPRece implements Runnable
            {
                private DatagramSocket ds;
                public UDPSend(){}
                public UDPSend(DatagramSocket ds)
                {
                    this.ds=ds;
                }
                public void run()
                {
                    try
                    {
                        while(true)
                        {    
                            byte[] buf = new byte[1024];
                            DatagramPacket dp = new DatagramPacket(buf,buf.length);
                            ds.receive(dp);//将发送端发送的数据包接收到接收端的数据包中
                            String ip = dp.getAddress().getHosyAddress();//获取发送端的ip
                            String data = new String(dp.getData(),0,dp.getLength());//获取数据
                            int port = dp.getPort();//获取发送端的端口号
                            sop(ip+":"+data+":"+port);        
                        }
                    }
                    catch(Exception e)
                    {
                        throw new RuntimeException("接收失败");
                    }
                }
            }
            测试类:
            class UDPTest
            {
                public static void main(String[] args)
                {
                    DatagramSocket sendSocket = new DatagramSocket();
                    DatagramSocket receSocket = new DatagramSocket(10000);

                    new Thread(new UDPSend(sendSocket)).start();
                    new Thread(new UDPRece(receSocket)).start();
                }
            }
        (2)TCP传输
            Socket和ServerSocket
            建立客户端和服务器端
            建立连接后,通过Socket中的IO流进行数据的传输
            关闭socket
            同样,客户端与服务器端是两个独立的应用程序。
            ****Socket
            **构造方法:
            Socket()
                通过系统默认类型的 SocketImpl 创建未连接套接字
            Socket(InetAddress address, int port)
                创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
            Socket(String host, int port)
                创建一个流套接字并将其连接到指定主机上的指定端口号。
            **方法摘要:
            void close()
                关闭此套接字。
            InetAddress getInetAddress()
                返回套接字连接的地址。
            InputStream getInputStream()
                返回此套接字的输入流。
            OutputStream getOutputStream()
                返回此套接字的输出流。
            int getPort()
                返回此套接字连接到的远程端口。
            void shutdownInput()
                此套接字的输入流置于“流的末尾”。
            void shutdownOutput()
                禁用此套接字的输出流。
            String toString()
                将此套接字转换为 String。
            ****ServerSocket
            **构造方法:
            ServerSocket()
                创建非绑定服务器套接字。
            ServerSocket(int port)
                创建绑定到特定端口的服务器套接字。
            方法摘要:
            Socket accept()
                侦听并接受到此套接字的连接。
            void close()
                关闭此套接字。
            InetAddress getInetAddress()
                返回此服务器套接字的本地地址。
            ****TCP传输流程:
            **客户端:
            建立Socket服务,并制定要连接的主机和端口;
            获取Socket流中的输出流OutputStream,将数据写入流中,通过网络发送给服务端;
            获取Socket流中的输出流InputStream,获取服务端的反馈信息;
            关闭资源。
            **服务端:
            建立ServerSocket服务,并监听一个端口;
            通过ServerSocket服务的accept方法,获取Socket服务对象;
            使用客户端对象的读取流获取客户端发送过来的数据;
            通过客户端对象的写入流反馈信息给客户端;
            关闭资源;
            ****代码示例:
            客户端:
            class TCPClient
            {
                public static void main(String[] args)
                {
                    Socket s = new Socket("192.168.1.253",10000);
                    OutputStream os = s.getOutputStream();
                    out.write("这是TCP发送的数据".getBytes());
                    s.close();
                }
            }
            服务端:
            class TCPServer
            {
                public static void main(String[] args)
                {
                    ServerSocket ss = new ServerSocket(10000);
                    Socket s = ss.accept();

                    String ip = s.getInetAddress().getHostAddress();
                    sop(ip);

                    InputStream is = s.getInputStream();
                    byte[] buf = new byte[1024];
                    int len = is.read(buf);
                    sop(new String(buf,0,len));
                    s.close();
                    ss.close();
                }
            }
            TCP需求1:客户端给服务端发送数据,服务端接收到后反馈信息给客户端
            客户端:
            class TCPClient
            {
                public static void main(String[] args)
                {
                    Socket s = new Socket("192.168.1.253",10000);
                    OutputStream os = s.getOutputStream();
                    out.write("这是TCP发送的数据".getBytes());
                    
                    InputStream is = s.getInputStream();
                    byte[] buf = new byte[1024];
                    int len = is.read(buf);
                    sop(new String(buf,0,len));
                    s.close();
                }
            }
            服务端:
            class TCPServer
            {
                public static void main(String[] args)
                {
                    ServerSocket ss = new ServerSocket(10000);
                    Socket s = ss.accept();

                    String ip = s.getInetAddress().getHostAddress();
                    sop(ip);

                    InputStream is = s.getInputStream();
                    byte[] buf = new byte[1024];
                    int len = is.read(buf);
                    sop(new String(buf,0,len));

                    OutputStream os = s.getOutputStream();
                    out.write("这是TCP发送的数据".getBytes());

                    s.close();
                    ss.close();
                }
            }
            TCP需求2:建立一个文本转换服务端,客户给服务端发送文本,服务端将数据转换成大写后返回给客户端
                  当客户端输入over时,转换结束
            客户端:
            class TCPClient
            {
                public static void main(String[] args)
                {
                    Socket s = new Socket("192.168.1.253",10000);
                    BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
                    BufferedWriter bufOut = new BufferedWriter(new OutputStreamWriter(
                                            s.getOutputStream()));
                    BufferedReader bufIn = new BufferedReader(new InputStreamReader(
                                            s.getInputStream()));
                    String line = null;
                    while((line = bufr.readLine())!=null)
                    {
                        if("over".equals(line))
                            break;
                        bufOut.write(line);
                        bufOut.newLine();
                        bufOut.flush();
                        String retVal = bufIn.readLine();
                        sop("server:"+retVal);
                    }
                    bufr.close();
                    s.close();
                }
            }
            服务端:
            class TCPServer
            {
                public static void main(String[] args)
                {
                    ServerSocket ss = new ServerSocket(10000);
                    Socket s = ss.accept();

                    String ip = s.getInetAddress().getHostAddress();
                    sop(ip);
                    
                    BufferedReader bufIn = new BufferedReader(new InputStreamReader(
                                            s.getInputStream()));
                    BufferedWriter bufOut = new BufferedWriter(new OutputStreamWriter(
                                            s.getOutputStream()));

                    while((line = bufIn.readLine())!=null)
                    {
                        bufOut.write(line.toUpperCase());
                        bufOut.newLine();
                        bufOut.flush();
                    }
                    s.close();
                    ss.close();
                }
            }
            **需求3:拷贝文件
            客户端:
            class TCPClient
            {
                public static void main(String[] args)
                {
                    Socket s = new Socket("192.168.1.253",10000);
                    BufferedReader bufr = new BufferedReader(new FileReader("g:\demo.txt"));
                    PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
                    String line = null;
                    while((line = bufr.readLine())!=null)
                    {
                        pw.println();
                    }
                    s.shutDownOutput();
                    BufferedReader bufIn = new BufferedReader(new InputStreamReader(
                                            s.getInputStream()));
                    String retVal = bufIn.readLine();
                    sop(retVal);
                    bufr.close();
                    s.close();
                }
            }
            服务端:
            class TCPServer
            {
                public static void main(String[] args)
                {
                    ServerSocket ss = new ServerSocket(10000);
                    Socket s = ss.accept();

                    String ip = s.getInetAddress().getHostAddress();
                    sop(ip);
                    
                    BufferedReader bufIn = new BufferedReader(new InputStreamReader(
                                            s.getInputStream()));
                    PrintWriter out = new PrintWriter(new FileWriter"copy.txt",true);
                    String line =null;
                    while((line = bufIn.readLine())!=null)
                    {
                        out.write(line);
                    }
                    PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
                    pw.println("上传成功");
                    out.close();
                    s.close();
                    ss.close();
                }
            }
            需求4:上传图片
            客户端:
            class TCPClient
            {
                public static void main(String[] args)
                {
                    Socket s = new Socket("192.168.1.253",10000);
                    FileInputStream fis = new FileInputStream("g:\1.bmp");
                    OutputStream out = s.getOutputStream();
                    byte[] buf = new byte[1024];
                    int len = 0;
                    while((len = bufr.read())!=-1)
                    {
                        out.write(buf,0,len);
                    }
                    s.shutDownOutput();

                    InputStream in = s.getInputStream();
                    byte[] bufIn = new byte[1024];
                    int lenIn = in.read(bufIn);
                    sop(new String(bufIn,0,lenIn);
                    fis.close();
                    s.close();
                }
            }
            服务端:
            class TCPServer
            {
                public static void main(String[] args)
                {
                    ServerSocket ss = new ServerSocket(10000);
                    Socket s = ss.accept();

                    String ip = s.getInetAddress().getHostAddress();
                    sop(ip);
                    FileOutputStream fos = new FileOutputStream("g:\copy.bmp");
                    InputStream in = s.getInputStream();
                    byte[] bufIn = new byte[1024];
                    int lenIn = 0;
                    while((lenIn=bufIn.read())!=-1)
                    {
                        fos.write(bufIn,0,lenIn)
                    }

                    OutputStream outIn = s.getOutputStream();
                    outIn.write("上传成功".getBytes());
                    fos.close();
                    s.close();
                    ss.close();
                }
            }
            需求5:客户端并发登陆
                客户端通过键盘录入用户名,服务端对这个用户名进行校验
                如果用户存在,在服务端现实xxx已登录,并在客户端现实欢迎xxx
                如果用户不存在,在服务端现实xxx正在尝试登陆,并在客户端现实xxx用户不存在
                最多登陆三次。
            校验端:
            class User implements Runnable
            (
                private Socket s;
                public User(){}
                public User(Socket s)
                {
                    this.s=s;
                }
                public void run()
                {
                    try
                    {
                        BufferedReader bufrIn = new BufferedReader(
                                new InputStream(s.getInputStream()))
                        String name = bufrIn.readLine();
                        if(name==null)
                        {
                            sop("用户名为空");
                            break;
                        }
                        BufferedReader bufr = new BufferedReader(
                                new FileReader("user.txt"));
                        PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
                        String line = null;
                        boolean flag = false;
                        while((line = bufr.reanLine())!=null)
                        {
                            if(line.equals(name))
                            {
                                flag = true;
                                break;
                            }
                            if(flag)
                            {
                                sop(name+"已登陆");
                                pw.println("欢迎"+name);
                                break;
                            }
                            else
                            {
                                sop(name+"正尝试登陆");
                                pw.println(name+"用户不存在");
                            }

                        }
                        s.close();
                    }
                    catch(Exception e)
                    {
                        throw new RuntimeException("用户校验失败");
                    }
                }
            )
            客户端:
            class LoginClient
            {
                public static void main(String[] args)
                {
                    Socket s = new Socket("192.168.1.253",10000);
                    BufferedReader bufr = new BufferedReader(
                                new InputStreamReader(System.in)));
                    PrintWriter out = new PrintWriter(s.getOutputStream(),true);
                    BufferedReader bufIn = new BufferedReader(
                                new InputStreamReader(s.getInputStream()));
                    for(int i=0;i<3;i++)
                    {
                        String line = bufr.readLine();
                        if(line == null)
                        {
                            sop("用户名不能为空!");
                            break;
                        }
                        out.write(line);
                        String retVal = bufIn.readLine();
                        sop(retVal);    
                    }
                    bufr.close();
                    s.close();
                }
            }
            服务端:
            class LoginServer
            {
                public static void main(String[] args)
                {
                    ServerSocket ss = new ServerSocket(10000);
                    while(true)
                    {
                        Socket s = ss.accept();
                        new Thread(new User()).start();
                    }
                }
            }

     
  • 相关阅读:
    redis线程模型
    同步容器和并发容器
    200+面试题
    redis pipeline
    redis事务和脚本
    redis事务
    redis优缺点
    redis持久化策略
    Redis为什么要把所有数据放到内存中?
    redis的过期策略以及内存淘汰机制
  • 原文地址:https://www.cnblogs.com/stsinghua/p/6413817.html
Copyright © 2020-2023  润新知