java网络编程、udp、tcp

1.网络编程三要素

1.IP地址

设备在网络中的地址,是唯一的标识。

2.端口

应用程序在设备中唯一的标识。

3.协议

数据在网络中传输的规则,常见的协议有UDP协议和TCP协议。

2.IP

IP:全称”互联网协议地址”,也称IP地址。是分配给上网设备的数字标签。常见的IP分类为:ipv4和ipv6

IPv6:由于互联网的蓬勃发展,IP地址的需求量愈来愈大,而IPv4的模式下IP的总数是有限的。 采用128位地址长度,分成8组。

InetAddress 的使用

为了方便我们对IP地址的获取和操作,Java提供了一个类InetAddress 供我们使用 InetAddress:此类表示Internet协议(IP)地址

3.端口

端口:应用程序在设备中唯一的标识。

端口号:用两个字节表示的整数,它的取值范围是0~65535。 其中0~1023之间的端口号用于一些知名的网络服务或者应用。 我们自己使用1024以上的端口号就可以了。 注意:一个端口号只能被一个应用程序使用。 

4.协议

协议:计算机网络中,连接和通信的规则被称为网络通信协议

UDP协议

1.用户数据报协议(User Datagram Protocol)

2.UDP是面向无连接通信协议。 速度快,有大小限制一次最多发送64K,数据不安全,易丢失数据。

TCP协议

1. 传输控制协议 (Transmission Control Protocol)

2. TCP协议是面向连接的通信协议。 速度慢,没有大小限制,数据安全。

5.UDP通信

大致步骤

udp发送端步骤

1.创建发送端的DatagramSocket对象

2.创建数据,并把数据打包(DatagramPacket)

3.调用DatagramSocket对象的方法发送数据

4.释放资源

UDP接收端步骤

1.创建接收端的DatagramSocket对象

2.创建一个箱子,用于接收数据

3.调用DatagramSocket的方法接收数据并将数据放入箱子中

4.解析数据包,并把数据在控制台显示

5.释放资源

6.UDP通信---单播

客户端代码:

public class ClientDemo {
    private static String host = "127.0.0.1";
    private static int port = 10000;
    private static Scanner sc = new Scanner(System.in);

    public static void main(String[] args) {
        DatagramSocket ds = null;

        String msg;
        try {
            ds = new DatagramSocket();// 创建连接对象
            do {
                System.out.println("请输入要发送的消息");
                msg = sc.nextLine();
                byte[] bytes = msg.getBytes(StandardCharsets.UTF_8);
                DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName(host), port); // 创建一个包裹 并指定 ip地址和端口号

                ds.send(dp); // 发送数据
            } while (!"886".equals(msg));
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            ds.close();
        }
    }
}

服务端代码:

public class ServerDemo {
    public static void main(String[] args) throws IOException {
        DatagramSocket ds = new DatagramSocket(10000); //指定监听的端口号

        byte[] bytes = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
        while (true) {
            ds.receive(dp); //这里如果没有 发送端来连接 会在这里阻塞 死等

            int length = dp.getLength();
            byte[] data = dp.getData();
            String msg = new String(data, 0, length);

            if("886".equals(msg)){
                System.out.println("接收端stop");
                ds.close();
                break;
            }
            System.out.println("接收端:" + msg);
        }
    }
}

7.UDP通信---组播

组播地址:224.0.0.0 ~ 239.255.255.255 其中224.0.0.0 ~ 224.0.0.255 为预留的组播地址

客户端代码

public class clientDemo {
    public static void main(String[] args) throws IOException {
        DatagramSocket ds = new DatagramSocket();

        byte[] bytes = "你好 我是xxx".getBytes(StandardCharsets.UTF_8);
        InetAddress address = InetAddress.getByName("224.0.1.0"); // 创建组播地址
        int port = 10000;

        DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port); // 创建 包裹 制动组播地址 和端口号

        ds.send(dp); // 发送

        ds.close();
    }
}

服务端1代码

public class ServerDemo1 {
    public static void main(String[] args) throws IOException {
        MulticastSocket ms = new MulticastSocket(10000); // 定义组播通信对象 并指定端口号

        DatagramPacket dp = new DatagramPacket(new byte[1024], 1024);
        ms.joinGroup(InetAddress.getByName("224.0.1.0")); // 将本机加入到组播中

        ms.receive(dp);

        byte[] data = dp.getData();
        int length = dp.getLength();

        System.out.println("接收端1:");
        System.out.println(new String(data, 0, length));
    }
}

服务端2代码

public class ServerDemo2 {
    public static void main(String[] args) throws IOException {
        MulticastSocket ms = new MulticastSocket(10000); // 定义组播通信对象 并指定端口号

        DatagramPacket dp = new DatagramPacket(new byte[1024], 1024);
        ms.joinGroup(InetAddress.getByName("224.0.1.0")); // 将本机加入到组播中

        ms.receive(dp);

        byte[] data = dp.getData();
        int length = dp.getLength();

        System.out.println("接收端2:");
        System.out.println(new String(data, 0, length));
    }
}

8.UDP通信---广播

广播地址:255.255.255.255

客户端代码

public class clientDemo {
    public static void main(String[] args) throws IOException {
        DatagramSocket ds = new DatagramSocket();

        byte[] bytes = "你好 我是xxx".getBytes(StandardCharsets.UTF_8);
        InetAddress address = InetAddress.getByName("255.255.255.255");// 指定255.255.255.255 说明是广播地址 
        int port = 10000;

        DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port); // 创建包裹

        ds.send(dp);

        ds.close();
    }
}

服务端代码

// 组播代码
public class ServerDemo1 {
    public static void main(String[] args) throws IOException {
        MulticastSocket ms = new MulticastSocket(10000); // 创建组播连接对象

        DatagramPacket dp = new DatagramPacket(new byte[1024], 1024); // 创建包裹
        ms.joinGroup(InetAddress.getByName("224.0.1.0")); // 将本机加入到 组播中

        ms.receive(dp);

        byte[] data = dp.getData();
        int length = dp.getLength();

        System.out.println("接收端1:");
        System.out.println(new String(data, 0, length));
    }
}

// 组播代码
public class ServerDemo1 {
    public static void main(String[] args) throws IOException {
        MulticastSocket ms = new MulticastSocket(10000); // 创建组播连接对象

        DatagramPacket dp = new DatagramPacket(new byte[1024], 1024); // 创建包裹
        ms.joinGroup(InetAddress.getByName("224.0.1.0")); // 将本机加入到 组播中

        ms.receive(dp);

        byte[] data = dp.getData();
        int length = dp.getLength();

        System.out.println("接收端2:");
        System.out.println(new String(data, 0, length));
    }
}


//注意:组播 和 单播不能同时监听统一端口

//单播代码
public class ServerDemo3 {
    public static void main(String[] args) throws IOException {
        DatagramSocket ds = new DatagramSocket(10000); // 创建单播连接对象

        DatagramPacket dp = new DatagramPacket(new byte[1024], 1024); // 创建 包裹

        ds.receive(dp);

        byte[] data = dp.getData();
        int length = dp.getLength();

        System.out.println("单播的接受端:");
        System.out.println(new String(data, 0, length));
    }
}

9.TCP通信

TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象。

通信之前要保证连接已经建立。

通过Socket产生IO流来进行网络通信。    

TCP发送数据步骤

发送数据的步骤

① 创建客户端的Socket对象(Socket)与指定服务端连接

Socket(String host, int port)

② 获取输出流,写数据

OutputStream getOutputStream()

③ 释放资源

void close()   

TCP接收数据 接收数据的步骤

接收数据的步骤

① 创建服务器端的Socket对象(ServerSocket)

ServerSocket(int port)

② 监听客户端连接,返回一个Socket对象

Socket accept()

③ 获取输入流,读数据,并把数据显示在控制台

InputStream getInputStream()

④ 释放资源

void close()

10.TCP三次握手

11.TCP四次挥手

12.TCP通信---代码

客户端代码

public class ClientSocket {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 10000);// 创建 socket对象 指定发送的IP地址和端口号

        OutputStream os = socket.getOutputStream(); // 获取 输出流 可以将数组 输出到网络通道中

        os.write("hello".getBytes());
        socket.shutdownOutput(); // 发送结束标志 表示客户端已经 发送完毕(如果不声明 服务端将无法获取停止标志 意味着服务端 将会一直在这个线程中死循环)

        InputStream inputStream = socket.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
        String s;
        while ((s = br.readLine()) != null){
            System.out.println(s);
        }


        os.close();
        br.close();
        socket.close();
    }
}

服务端代码

public class ServerSocketDemo {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(10000); // 创建tcp连接 并指定监听端口

        Socket accept = ss.accept(); // 接受客户端的数据 如果没有连接 将会死等 阻塞状态
        InputStream is = accept.getInputStream();

        int b;
        while ((b = is.read()) != -1){
            System.out.print((char) b); // 获取客户端的数据并打印
        }

        OutputStream os = accept.getOutputStream();
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os)); // 给客户端 回数据
        bw.write("你谁啊?");
        bw.newLine();
        bw.flush();

        is.close();
        bw.close();
        ss.close();
    }
}

13.TCP实现图片上传(多线程上传)

要求:

客户端:将本地文件上传到服务器。接收服务器的反馈。 

服务器:接收客户端上传的文件,上传完毕之后给出反馈。

客户端代码

public class clientDemo {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 10000); // 创建 socket对象 指定发送的IP地址和端口号

        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("src/main/resources/a1.jpeg")); // 指定本地数组地址

        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream()); // 使用字节缓冲流 写数据 效率高


        int len;
        byte[] bytes = new byte[1024 * 8];

        while ((len = bis.read(bytes)) != -1){
            bos.write(bytes, 0, len);
        }
        socket.shutdownOutput(); // 结束标志

        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); // 使用转换流 将字节流变成 字符流

        String line;
        while ((line = br.readLine()) != null){ //将服务端的 回文 显示出来
            System.out.println(line);
        }


        bis.close();
        br.close();
        socket.close();
    }
}

服务端代码

// 使用 线程池的方式 创建多线程
public class serverDemo {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(10000);

        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                3,// 核心线程数
                10, // 最大线程数
                60, // 临时线程的空闲时间 超过多少时间销毁
                TimeUnit.SECONDS, // 临时线程的空闲时间的单位 超过多少时间销毁的单位
                new ArrayBlockingQueue<>(5), // 阻塞队列 最多5个线程阻塞
                Executors.defaultThreadFactory(), //创建线程的方式
                new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
        );


        while (true){
            Socket accept = ss.accept();

            MyTask myTask = new MyTask(accept);

            pool.submit(myTask);
        }
    }
}

线程代码

public class MyTask implements Runnable{
    private Socket accept; //定义 tcp通信对象
    public MyTask(Socket a){
        this.accept = a;
    }

    @Override
    public void run() {
        BufferedOutputStream bos = null;
        try {
            InputStream is = accept.getInputStream();
            BufferedInputStream bis = new BufferedInputStream(is);

            bos = new BufferedOutputStream(new FileOutputStream("src/main/resources/"+ UUID.randomUUID().toString() +".jpeg"));

            int len;
            byte[] bytes = new byte[1024];
            while ((len = bis.read(bytes)) != -1){
                bos.write(bytes, 0 ,len);
            }
// 给客户端回消息
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
            bw.write("上传完成");
            bw.newLine();
            bw.flush();


        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                accept.close();
                if(bos != null) {
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值