• 29(套接字)就是网络编程


    通过java程序实现网络之间的数据传输   底层基于网络来传输的流

    网路模型

    IP地址:确定再网络中的位置  ipv4 由4位0-255之间的数组成的--192.168.0.1   ipv6

    端口:计算机和外部进行数据交互的媒介---端口号(0-65535  16位二进制数) 0-1023这些端口号大部分被

    我们的系统占用了紧密绑定一些服务,

    注册端口:1024到49151.它们松散的绑定一些服务

    动态和/或私有端口:从49152到65535,这些端口时应用程序使用的动态端口,应用程序一般不会主动使用这些端口

    域名:给ip取得好记的名称  通过DNS中央解析器可以映射到对应的IP

    一:InetAddress 类

    java提供了InetAddress类来代表IP地址,InetAddress下还有2个子类:Inet4Address、Inet6Address

    UDP: 底层基于流,底层是通过数据包来进行数据的传输,数据包大小一般不能超过64kb。不会建立连接(不检测连接状态,不检测传输东西是否有用),所以对我们来说

    传输数据不可靠,但是传输速度快。使用场景 :视频聊天 

    创建UDP数据连接采用的类是 DatagramSocket(实现类)   Datagrampacket(数据包类)

    发送端:

    1.创建套接字对象

    2.创建需要发送的数据包(指定要发送的数据长度以及ip地址和端口号)

    3.发送数据包

    4.关流

    public class UDPSenderDemo {
    
        public static void main(String[] args) throws IOException {
            //UDP传输的发送端
            //创建套接字的对象 -------指定要传输的IP和端口
            DatagramSocket ds=new DatagramSocket();
            //创建一个待传输的数据包
            //因为是通过数据包传输的,所以IP地址我只要给数据包指定就好
            //第一个参数是用传输的数据的字节数组
            //第二个参数真正要发送的数据长度(最大和byte数组长度一致)
            //第三个参数指明要传输的IP地址和端口
            DatagramPacket dp=new DatagramPacket("你好".getBytes(), "你好".getBytes().length,new InetSocketAddress("127.0.0.1", 8009));
            //发送数据包
            ds.send(dp);
            //关流  -----底层字节流
            ds.close();
    
    }
    }

    接收端

    1.创建套接字对象(绑定具体的端口号)

    2.创建需要接收的数据包(指定真实接收数据的长度)

    3.接收数据包

    4.关流

    5.解析数据包

    public class UDPReceiverDemo {
    
        public static void main(String[] args) throws IOException {
            //创建接收端套接字对象
            //接收端的套接字的话就是要采用含端口的构造方法,因为不管什么IP地址发送给我数据,我都是通过端口来交互数据
            DatagramSocket ds=new DatagramSocket(8009);
            //创建数据包用于接收数据
            //第二个参数代表实际接收数据的长度,可以设置的小一点
            DatagramPacket dp=new DatagramPacket(new byte[1024], 1024);
            //接收数据把数据放置在数据包中
            ds.receive(dp);
            //关流
            ds.close();
            //解析数据包
            //dp.getData() --获取数据---字节数组
            //dp.getLength()--获取数据的长度
            System.out.println(new String(dp.getData(),0,dp.getLength()));
            //获取IP地址和端口
            System.out.println(dp.getAddress());
            System.out.println(dp.getPort());
            //先开启接收端
            //后开启发送端
    
        }
    
    }

     案例:

    1.通过UDP实现检测的聊天室(通过线程实现)

    public class UDPsenderDemo2 {
        public static void main(String[] args) {
            //开启线程
            new Thread(new Sender()).start();
            new Thread(new Receiver()).start(); 
        }
    }
    
    
    //发送端
    class Sender implements Runnable{
        //声明对象
        DatagramSocket ds;
        Scanner sc;
        @Override
        public void run() {
            // TODO Auto-generated method stub
            //对象初始化
            try {
                ds=new DatagramSocket();    
                sc=new Scanner(System.in);
                while(true) //保证一直发送数据
                {
                    //录入数据
                    byte[]bs=sc.nextLine().getBytes();
                    //创建发送的数据包
                    DatagramPacket dp=new DatagramPacket(bs,bs.length,new InetSocketAddress("127.0.0.1",8090));
                    //发送数据包
                    ds.send(dp);
                }
            } catch (SocketException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
        }
    
    }
    
    //接收端
    class Receiver implements Runnable{
        DatagramSocket ds;
        DatagramPacket dp;
        @Override
        public void run() {
            //对象初始化
            try {
                ds=new DatagramSocket(8090);
                dp=new DatagramPacket(new byte[1024],1024);
            } catch (SocketException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            while(true)
            {
                try {
    
                    //接收数据包
                    ds.receive(dp);
                    //解析数据包    
                    System.out.println(new String(dp.getData(),0,dp.getLength()));
                    System.out.println(dp.getAddress());
                    System.out.println(dp.getPort());
                }
    
                catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }}
    
    
    
    
        }
    
    }

    TCP:底层基于流:建立连接。可靠,传输速度慢

    TCP通过字节流直接传输数据不需要数据包,就没有传输数据的限制

    适用场景:传输文件,和下载电影等

    客户端(Socket)

    1.创建TCP客户端对象

    2.发起链接(指明要发送的IP和端口)

    3.获取自带的字节输出流

    4.根据自带的字节流往服务器端写出数据

    5.通知服务器已经写完、关流

    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.InetSocketAddress;
    import java.net.Socket;
    
    public class TCPClientDemo {
    public static void main(String[] args) throws IOException {
        //创建TCP套接字对象
        Socket s=new Socket();
        //发起链接---指定链接的IP和端口
        s.connect(new InetSocketAddress("127.0.0.1",9008)); //connect会有阻塞
        //获取套接字对象自带的字节输出流
        //写出的数据默认往服务器写
        OutputStream os=s.getOutputStream();
        
        //通过自带的字节输出流写数据
        os.write("服务器你好。。。".getBytes());
        
        //通知服务器数据已写完
        s.shutdownOutput();
        
        //获取自带字节输入流
        InputStream in =s.getInputStream();
        //读取数据
        byte[]bs=new byte[1024];
        int len=-1;
        while((len=in.read(bs))!=-1)
        {
            System.out.println(new String(bs,0,len));
        }
        //通知服务器已经读取完成
        s.shutdownInput();
        //关流
        os.close();
    }
    }

    服务器端(ServiceSocket)

    1.创建TCP服务器端对象。绑定端口

    2.接收链接

    3.获取自带的字节流

    4.通过自带的字节流进行数据读取

    5.通知客户端已经读取完成、关流

    6关流

    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TCPServiceDemo {
    public static void main(String[] args) throws IOException {
        //创建一个TCP服务器端对象---绑定端口
            ServerSocket ss=new ServerSocket(9008);
            //接收链接,为什么呢因为Socket有自带的InputStream
            System.out.println("接收");
            Socket s=ss.accept(); //阻塞
            System.out.println("接收完成");
            //读取传过来的数据
            //获取自带的输入流
            InputStream in=s.getInputStream();
            //自建缓冲区
            byte[]bs=new byte[1024];
            int len=-1;
            while((len=in.read(bs))!=-1)  
            {
                System.out.println(new String(bs,0,len));
            }
            //通知客户端数据以读完
            s.shutdownInput();
            
            //获取一个自带的字节输出流
            OutputStream os =s.getOutputStream();
            //往客户端写出数据
            os.write("你也好".getBytes());
            //通知客户端已经写完
            s.shutdownOutput();
            in.close();
    }
    }

    用TCP实现客户端上传文件,服务端复制文件

    客户端

    package cn.tedu.inernet.tcp;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.InetSocketAddress;
    import java.net.Socket;
    
    public class TCPFileCopyClient {
        public static void main(String[] args) throws IOException {
            //创建TCP客户端对象
            Socket s=new Socket();
            //发起链接
            s.connect(new InetSocketAddress("127.0.0.1", 9009));
            //文件类对象
            File file=new File("D:\1.mp4");
            //把外部文件读取进来
            FileInputStream fis=new FileInputStream
                    (file);
            //获取自带输出流
            OutputStream os=s.getOutputStream();
            //获取文件名称
            //先传文件名长度
            os.write(file.getName().getBytes().length-128);//文件名长度值
            //传文件名内容
            os.write(file.getName().getBytes());
            byte[] bs=new byte[1024*1024*10];
            int len=-1;
            while((len=fis.read(bs))!=-1){
                //往服务器端写数据
                os.write(bs,0,len);
            }
            
            //通知服务器端已写完
            s.shutdownOutput();
            //关流
            os.close();
            fis.close();
        }
    }

    服务端

    package cn.tedu.inernet.tcp;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TCPFileCopyServer {
        public static void main(String[] args) throws IOException {
            //获取TCP服务器端的对象---绑定端口
            ServerSocket ss=new ServerSocket(9009);
            //接收链接
            Socket s=ss.accept();
            //获取自带字节输入流---读取客户端发来的数据
            InputStream in=s.getInputStream();
            //接收文件名长度值
            byte length=(byte)in.read();
            //新建字节数组
            byte[] bts=new byte[length+128];
            //按照这个字节数组读取文件名内容
            in.read(bts);//字节数组里存满了文件名内容
            //创建文件字节输出流对象
            FileOutputStream fos=new FileOutputStream(new File("D:\javase\"+new String(bts)));
            byte[] bs=new byte[1024*1024*10];
            int len=-1;
            while((len=in.read(bs))!=-1){
                //往外部文件写数据
                fos.write(bs, 0, len);
            }
            
            //通知客户端已经读取完毕
            s.shutdownInput();
            //关流
            in.close();
            fos.close();
        }
    
    }
  • 相关阅读:
    const 与 readonly知多少
    js中得~~是什么意思/JS按位非(~)运算符与~~运算符的理解分析
    严格模式详解
    Javascript中的prototype和__proto__的联系区别
    提升页面渲染效率
    window.onload=function(){}和$(function(){})的区别
    gulp的安装和配置
    JS的组成部分、引入页面的方法以及命名规范
    js继承的三种实现
    前端模块化
  • 原文地址:https://www.cnblogs.com/xuwangqi/p/11255047.html
Copyright © 2020-2023  润新知