网络通信(二)

本文详细介绍了Java中UDP和TCP通信的特点、使用DatagramSocket和ServerSocket进行数据包发送与接收的方法,以及多发多收的实现过程,对比了两者在连接方式和可靠性上的差异。
摘要由CSDN通过智能技术生成

UDP通信

  • 特点:无连接,不可靠通信。通信效率高
  • 不事先建立连接,数据按照包发,一包数据包含:自己的IP、程序端口,目的地址、程序端口和数据(限制在64KB内)等。
  • Java提供了一个java.net.DatagramSocket类来实现UDP通信。

DatagramSocket:用于创建客户端、服务端

构造器说明
public DatagramSocket()创建客户端的Socket对象,系统会随机分配一个端口号
public DatagramSocket(int port)创建服务端的Socket对象,并指定端口号
方法说明
public void send(DatagramPacket dp)发送数据包
public void receive(DatagramPacket p)使用数据包接收数据

 DatagramPacket:创建数据包

构造器说明
public DatagramPacket(byte[ ] buf,int length,InetAddress,int port)创建发出去的数据包对象
public DatagramPacket(byte[ ] buf,int length)创建用来接收数据的数据包
方法说明
public int getLength()获取数据包,时间接收到的字节个数

Client类

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class Client {
    public static void main(String[] args) throws Exception {
        // 创建客户端对象
        DatagramSocket socket = new DatagramSocket();

        // 创建数据包对象要发出去的数据
        /* public DatagramPacket(byte buf[],int length,InetAddress address,int port)
            参数一:封装要发出去的数据
            参数二:发送出去的数据大小(字节个数)
            参数三:服务端的IP地址(找到服务端主机)
            参数四:服务端程序的端口
         */
        byte[] bytes = "我是客户端".getBytes();
        DatagramPacket packet = new DatagramPacket(bytes,bytes.length, InetAddress.getLocalHost(),6666);

        // 开始正式发送这个数据包的数据出去了
        socket.send(packet);

        System.out.println("客户端发送数据完毕");
        socket.close();
    }
}

Server类

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class Server {
    public static void main(String[] args) throws Exception {
        System.out.println("———————服务端启动———————");

        // 创建一个服务端对象 注册端口
        DatagramSocket socket = new DatagramSocket(6666);

        // 创建一个数据包对象,用于接收数据的
        byte[] buffer = new byte[1024 * 64];
        DatagramPacket packet = new DatagramPacket(buffer,buffer.length);

        // 开始正式使用数据包来接收客户端发来的数据
        socket.receive(packet);

        // 从字节数组中,把接收的数据之间打印出来
        // 接收多少就倒出多少
        // 获取本次数据包接收了多少数据
        int len = packet.getLength();

        String rs = new String(buffer,0,len);
        System.out.println(rs);

        System.out.println(packet.getAddress().getHostAddress());
        System.out.println(packet.getPort());

        socket.close(); // 释放资源
    }
}

使用UDP通信实现:发送消息、接收消息

客户端实现步骤

  1. 创建DatagramSocket对象(客户端对象)
  2. 创建DatagramPacket对象封装需要发送的数据(数据包对象)
  3. 使用DatagramSocket对象的send方法,传入DatagramPacket对象
  4. 释放资源

服务端实现步骤

  1. 创建DatagramSocket对象指定端口(服务端对象)
  2. 创建DatagramPacket对象接收数据(数据包对象)
  3. 使用DatagramSocket对象的receive方法,传入DatagramPacket对象
  4. 释放资源

UDP通信多发多收

客户端实现步骤

  1. 创建DatagramSocket对象(客户端对象)
  2. 使用while死循环不断的接收用户的数据输入,如果用户输入exit则退出程序
  3. 如果用户输入的不是exit,包数据封装成DatagramPacket
  4. 使用DatagramSocket对象的send方法将数据包大小进行发送
  5. 释放资源

接收端实现步骤

  1. 创建DatagramSocket对象指定端口(服务端对象)
  2. 创建DatagramPacket对象接收数据(数据包对象)
  3. 使用DatagramSocket对象的receive方法,传入DatagramPacket对象
  4. 使用while死循环不断的进行第三步

Client类

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws Exception {
        // 创建客户端对象
        DatagramSocket socket = new DatagramSocket();

        // 创建数据包对象要发出去的数据
        /* public DatagramPacket(byte buf[],int length,InetAddress address,int port)
            参数一:封装要发出去的数据
            参数二:发送出去的数据大小(字节个数)
            参数三:服务端的IP地址(找到服务端主机)
            参数四:服务端程序的端口
         */
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请说:");
            String msg = sc.next();

            // 一旦发现用户输入了exit命令,就退出客户端
            if (msg.equals("exit")){
                System.out.println("退出成功");
                socket.close();
                break;
            }
            byte[] bytes = msg.getBytes();
            DatagramPacket packet = new DatagramPacket(bytes,bytes.length, InetAddress.getLocalHost(),6666);

            // 开始正式发送这个数据包的数据出去了
            socket.send(packet);
        }
    }
}

Server类

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class Server {
    public static void main(String[] args) throws Exception {
        System.out.println("———————服务端启动———————");

        // 创建一个服务端对象 注册端口
        DatagramSocket socket = new DatagramSocket(6666);

        // 创建一个数据包对象,用于接收数据的
        byte[] buffer = new byte[1024 * 64];
        DatagramPacket packet = new DatagramPacket(buffer,buffer.length);

        while (true) {
            // 开始正式使用数据包来接收客户端发来的数据
            socket.receive(packet);

            // 从字节数组中,把接收的数据之间打印出来
            // 接收多少就倒出多少
            // 获取本次数据包接收了多少数据
            int len = packet.getLength();

            String rs = new String(buffer,0,len);
            System.out.println(rs);

            System.out.println(packet.getAddress().getHostAddress());
            System.out.println(packet.getPort());
        }
    }
}

TCP通信

  • 特点:面向连接、可靠通信
  • 通信双方事先会采用“三次握手”方式简历可靠连接,实现端到端的通信;底层能保证数据成功传给服务端
  • Java提供了一个java.net.Socket类来实现TCP通信

TCP通信——客户端开发

  • 客户端程序就是通过java.net包下的Socket类来实现的
构造器说明
public Socket(String host,int port)根据指定的服务器ip、端口号请求与服务端建立连接,连接通过,就获得了客户端socket
方法说明
public OutputStream getOutputStream()获得字节输出流对象
public InputStream geInputStream()获得字节输入流对象

客户端发送消息

  1. 创建客户端的Socket对象,请求与服务端的连接
  2. 使用socket对象调用getOutputStream()方法得到字节输出流
  3. 使用字节输出流完毕数据的发送
  4. 释放资源:关闭socket管道

TCP通信——服务端程序的开发

  • 服务端是通过java.net包下的ServerSocket类来实现的

ServerSpclet

构造器说明
public ServerSocket(int port)为服务端程序注册端口
方法说明
public Socket accept()阻塞等待客户端的连接请求,一旦与某个客户端成功连接,则返回服务端这边的Socket对象

服务端实现接收消息 

  1. 创建ServerSocket对象,注册服务端端口
  2. 调用ServerSocket对象的accept()方法,等待客户端的连接,并得到Socket管道对象
  3. 通过Socket对象调用getInputStream()方法得到字节输入流、完成数据的接收
  4. 释放资源:关闭socket管道

 Client类

import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Client {
    public static void main(String[] args) throws Exception {
        // 创建Socket对象,并同时请求与服务端程序的连接
        Socket socket = new Socket("127.0.0.1",8888);

        // 从socket通信管道中得到一个字节输出流,用来发送数据给服务端程序
        OutputStream os = socket.getOutputStream();

        // 把低级的字节输出流包装成数据输出流
        DataOutputStream dos = new DataOutputStream(os);

        // 开始写数据出去
        dos.writeUTF("在吗?");
        dos.close();

        socket.close(); // 释放连接器资源
    }
}

Server类

import java.io.DataInputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws Exception {
        System.out.println("------服务端启动成功------");
        // 创建ServerSocket的对象,同时为服务端注册端口
        ServerSocket serverSocket = new ServerSocket(8888);

        // 使用serverSocket对象,调用一个accept方法,等待客户端连接请求
        Socket socket = serverSocket.accept();

        // 从socket通信管道中得到一个字节输入流
        InputStream is = socket.getInputStream();

        // 把原始的字节输入流包装成数据输入流
        DataInputStream dis = new DataInputStream(is);

        // 使用数据输入流读取客户端发送过来的消息
        String rs = dis.readUTF();
        System.out.println(rs);
        // 获取客户端IP地址
        System.out.println(socket.getRemoteSocketAddress());

        dis.close();
        socket.close();
    }
}

TCP通信多发多收

  • 使用TCP通信实现:多发多收消息
  1. 客户端使用死循环,让用户不断输入消息
  2. 服务端也使用死循环,控制服务端收完消息,继续等待接收下一个消息

Client类

import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws Exception {
        // 创建Socket对象,并同时请求与服务端程序的连接
        Socket socket = new Socket("127.0.0.1",8888);

        // 从socket通信管道中得到一个字节输出流,用来发送数据给服务端程序
        OutputStream os = socket.getOutputStream();

        // 把低级的字节输出流包装成数据输出流
        DataOutputStream dos = new DataOutputStream(os);

        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请说:");
            String msg = sc.nextLine();

            // 一旦发现用户输入了exit命令,就退出客户端
            if (msg.equals("exit")){
                System.out.println("退出成功");
                dos.close();
                socket.close();
                break;
            }
            // 开始写数据出去
            dos.writeUTF("在吗?");
            dos.flush();
        }
    }
}

Server类

import java.io.DataInputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws Exception {
        System.out.println("------服务端启动成功------");
        // 创建ServerSocket的对象,同时为服务端注册端口
        ServerSocket serverSocket = new ServerSocket(8888);

        // 使用serverSocket对象,调用一个accept方法,等待客户端连接请求
        Socket socket = serverSocket.accept();

        // 从socket通信管道中得到一个字节输入流
        InputStream is = socket.getInputStream();

        // 把原始的字节输入流包装成数据输入流
        DataInputStream dis = new DataInputStream(is);

        while (true) {
            try {
                // 使用数据输入流读取客户端发送过来的消息
                String rs = dis.readUTF();
                System.out.println(rs);
            } catch (Exception e) {
                System.out.println(socket.getRemoteSocketAddress() + "离线了");
                dis.close();
                socket.close();
                break;
            }
        }
    }
}

  • 19
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值