java网络编程

12

1.什么是网络

由点和线构成,表示诸多对象间的相互联系。

2.什么是计算机网络

为实现资源共享和信息传递,通过通信线路连接起来的若干主机(Host)。

  • 互联网:(Internet)点与点相连
  • 万维网:(WWW – World Wide Web)端与端相连
  • 物联网:( IoT - Internet of things) 物与物相连

网络编程:让计算机与计算机之间建立连接、进行通信。

3.计算机网络发展

3.1 四个阶段

  • 诞生阶段:一台主机、多个终端
  • 形成阶段:美国国防部高级研究计划局协助开发的ARPANET
  • 互联互通阶段:标准化的网络,OSI参考模型和TCP/IP参考模型
  • 高速发展阶段:光纤及高速网络技术,发展为以因特网( Internet)为代表的互联网。

3.2 分类

  • 局域网
  • 城域网
  • 广域网

4.网络模型

4.1 OSI参考模型

OSI(Open System Interconnection)开放式系统互联

第七层:应用层负责文件访问和管理、可靠运输服务、远程操作服务。(HTTP、FTP、SMTP)

第六层:表示层负责定义转换数据格式及加密,允许选择以二进制或ASCII格式传输。

第五层:会话层负责使应用建立和维持会话,使通信在失效时继续恢复通信。(断点续传)

第四层:传输层负责是否选择差错恢复协议、数据流重用、错误顺序重排。(TCP、UDP)

第三层:网络层负责定义了能够标识所有网络节点的逻辑地址。(IP地址)

第二层:链路层在物理层上,通过规程或协议(差错控制)来控制传输数据的正确性。(MAC)

第一层:物理层为设备之间的数据通信提供传输信号和物理介质。(双绞线、光导纤维)

[wppay]

4.2 TCP/IP模型

一组用于实现网络互连的通信协议,将协议分成四个层次。

第四层:应用层负责传送各种最终形态的数据,是直接与用户打交道的层,典型协议是HTTP、FTP等。

第三层:传输层负责传送文本数据,主要协议是TCP、UDP协议。

第二层:网络层负责分配地址和传送二进制数据,主要协议是IP协议。

第一层:接口层负责建立电路连接,是整个网络的物理基础,典型的协议包括以太网、ADSL等等。

5.通信协议

5.1 TCP协议

TCP协议:Transmission Control Protocol 传输控制协议
• 是一种面向连接的、可靠的、基于字节流的传输层通信协议。数据大小无限制。建立连
接的过程需要三次握手,断开连接的过程需要四次挥手。

http://baijiahao.baidu.com/s?id=1654225744653405133&wfr=spider&for=pc

5.2 UDP协议

UDP协议:User Datagram Protocol 用户数据报协议
• 是一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,每个包的大小64KB。效率高

推荐书:TCP/IP详解

6.IP与端口

6.1 IP

IP协议:Internet Protocol Address 互联网协议地址/网际协议地址

  • 分配给互联网设备的数字标签(唯一标识)。
  • 网络层

IP地址分为两种

  • IPV4:4字节32位整数,并分成4段8位的二进制数,每8位之间用圆点隔开,每8位整数可以转换为一个0~255的十进制整数。
    格式:D.D.D.D 例如:255.255.255.255
  • IPV6:16字节128位整数,并分成8段十六进制数,每16位之间用圆点隔开,每16位整数可以转换为一个0~65535的十进制数。
    格式:X.X.X.X.X.X.X.X 例如:FFFF.FFFF.FFFF.FFFF.FFFF.FFFF.FFFF.FFFF

IPV4的应用分类

  • A类:政府机构,1.0.0.1 ~ 126.255.255.254
  • B类:中型企业,128.0.0.1 ~ 191.255.255.254
  • C类:个人用户,192.0.0.1 ~ 223.255.255.254
  • D类:用于组播,224.0.0.1 ~ 239.255.255.254
  • E类:用于实验,240.0.0.1 ~ 255.255.255.254
  • 回环地址:127.0.0.1,指本机,一般用于测试使用。
  • 查看IP命令:ipconfig
  • 测试IP命令:ping D.D.D.D

6.2 Port-端口号

  • 端口号:在通信实体上进行网络通讯的程序的唯一标识。
  • 端口分类:
    • 公认端口:0~1023
    • 注册端口:1024~49151
    • 动态或私有端口:49152~65535
  • 常用端口:
    • MySql:3306
    • Oracle:1521
    • Tomcat:8080
    • SMTP:25
    • Web服务器:80、443
    • FTP服务器:21

netstat -ano 查看端口号

7.DNS - 域名系统

DNS( Domain Name System):“域名系统”的英文缩写,是一种组织成域层次结构的计算机和网络服务命名系统,它用于TCP/IP网络。

作用:用来将主机名和域名转换为IP地址的工作,DNS就是这样一位翻译官,他的基本工作原理如下:

8.InetAddress类

概念:表示互联网协议(IP)地址对象,封装了与该IP地址相关的所有信息,并提供获取信息的常用方法。

方法:

  • public static InetAddress getLocalHost() 获得本地主机地址对象
  • public static InetAddress getByName(String host) 根据主机名称获得地址对象
  • public static InetAddress[] getAllByName(String host) 获得所有相关地址对象
  • public String getHostAddress() 获取IP地址字符串
  • public String getHostName() 获得IP地址主机名
public class InetAddressDemo {
    public static void main(String[] args) throws IOException {
        //1.表示本机
        InetAddress ia1 = InetAddress.getLocalHost();
        System.out.println("主机名:" + ia1.getHostName()
            + " IP地址:" + ia1.getHostAddress());

        InetAddress ia2 = InetAddress.getByName("192.168.56.1");
        System.out.println("主机名:" + ia2.getHostName()
            + " IP地址:" + ia2.getHostAddress());

        InetAddress ia3 = InetAddress.getByName("127.0.0.1");
        System.out.println("主机名:" + ia3.getHostName()
            + " IP地址:" + ia3.getHostAddress());

        InetAddress ia4 = InetAddress.getByName("localhost");
        System.out.println("主机名:" + ia4.getHostName()
            + " IP地址:" + ia4.getHostAddress());

        //2.局域网的地址
        /*InetAddress ia5 = InetAddress.getByName("xxx,xxx,xxx,xxx");
        System.out.println("主机名:"+ia5.getHostName()
            + " IP地址:"+ia5.getHostAddress());
        System.out.println(ia5.isReachable(3000));*/

        //3.外网地址
        InetAddress ia5 = InetAddress.getByName("www.baidu.com");
        System.out.println("主机名:" + ia5.getHostName()
            + " IP地址:" + ia5.getHostAddress());
        System.out.println(ia5.isReachable(3000));
        System.out.println("----------------------------");
        InetAddress[] ia6 = InetAddress.getAllByName("www.baidu.com");
        for (InetAddress address : ia6) {
            System.out.println("主机名:" + address.getHostName()
                + " IP地址:" + address.getHostAddress());
        }
    }
}

图解局域网,私有和公有IP NAT

9.网络编程

9.1 基于TCP的网络编程

Socket编程:

  • Socket(套接字)是网络中的一个通信节点。
  • 分为客户端Socket与服务器ServerSocket。
  • 通信要求:IP地址+ 端口号。

TCP编程实现客户端发送数据给服务器端

只发送:

public class TCPServer {
    //基于TCP协议的服务器编写步骤
    public static void main(String[] args) throws Exception {
        //1.创建服务器套接字(ServerSocket),并指定端口号
        //自动读取IP地址
        ServerSocket listener = new ServerSocket(10086);
        //2.侦听客户端链接,并返回客户端套接字
        //阻塞方法,没有客户端链接时,不会往下走
        System.out.println("服务器已经启动。。。");
        Socket socket = listener.accept();
        //3.获取输入流(网卡 -> 内存),【输出流】
        /*InputStream is = socket.getInputStream();
        InputStreamReader isr = new InputStreamReader(is, "UTF-8");
        BufferedReader br = new BufferedReader(isr);*/
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
        //4.处理数据
        String line = br.readLine();
        System.out.println(line);
        //5.关闭资源
        br.close();
        socket.close();
        listener.close();
    }
}
public class TcpClient {
    public static void main(String[] args) throws IOException {
        //基于TCP协议的客户端编写步骤
        //1.创建客户端套接字,指定 服务器的地址和端口号
        Socket socket = new Socket("localhost", 10086);
        //2.获取输出流(内存 ——> 网卡) 【输入流】
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"));
        //3.处理流
        bw.write("好久不见");
        //bw.flush();
        //4.关闭
        bw.close();
        socket.close();
    }
}

发送加回复

public class Server {
    public static void main(String[] args) throws Exception {
        //1.创建服务器ServerSocket
        ServerSocket socket = new ServerSocket(10086);
        //2.侦听客户端socket,并返回客户端套接字
        Socket accept = socket.accept();
        //3.获取输入流(内存 -> 网卡)、输出流
        BufferedReader br = new BufferedReader(new InputStreamReader(accept.getInputStream(), "UTF-8"));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream(), "UTF-8"));
        //4.处理数据
        String s = br.readLine();//遇到换行符才返回,要在客户端发送语句后面加换行符
        System.out.println(s);
        bw.write("我是服务端");
        bw.newLine();//****
        bw.flush();
        //5.关闭资源
        bw.close();
        br.close();
        accept.close();
        socket.close();
    }
}
public class Client {
    public static void main(String[] args) throws Exception {
        //1.创建客户端socket
        Socket socket = new Socket("localhost", 10086);
        //2.发送数据流(网卡 -> 内存)
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"));
        //3.处理数据流
        bw.write("我是客户端");
        bw.newLine();
        bw.flush();
        String s = br.readLine();
        System.out.println(s);
        //4.关闭流
        bw.close();//会自动发送换行符
        br.close();
        socket.close();
    }
}

TCP编程实现客户端上传文件给服务器端

public class Server {
    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(10086);
        Socket accept = serverSocket.accept();
        BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("aa.png"));
        byte[] arr = new byte[1024];
        int len;
        while ((len = bis.read(arr)) != -1) {
            bos.write(arr, 0, len);
            bos.flush();
        }
        bos.close();
        bis.close();
        accept.close();
        serverSocket.close();
    }
}

class Client {
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("localhost", 10086);
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.png"));
        byte[] arr = new byte[1024];
        int len;
        while ((len = bis.read(arr)) != -1) {
            bos.write(arr, 0, len);
            bos.flush();
        }
        bis.close();
        bos.close();
        socket.close();
    }
}

多客户端请求

客户之间无法交流

public class ChatServer {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        Socket socket = null;
        ExecutorService es = Executors.newCachedThreadPool();
        ConcurrentHashMap<String, ServerSocket> cm = new ConcurrentHashMap<String, ServerSocket>();
        try {
            serverSocket = new ServerSocket(8888);
            System.out.println("聊天室已经启动");
            while (true) {
                socket = serverSocket.accept();
                System.out.println(serverSocket.getInetAddress().getHostAddress() + "进入聊天室");
                es.submit(new DataSocket(socket));
            }
        } catch (IOException e) {
            System.out.println("服务器崩溃");
        } finally {
            try {
                es.shutdown();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

class DataSocket implements Runnable {
    private Socket socket;

    public DataSocket(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        //接收数据
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
            String line;
            while ((line = br.readLine()) != null) {

                //如果为空,客户但正常关闭
                //客户端非正常关闭,抛出异常
                System.out.println(socket.getInetAddress().getHostAddress() + " " + line);
                if ("拜拜".equals(line)) {
                    break;
                }
            }
            System.out.println(socket.getInetAddress().getHostAddress() + "退出了聊天!");
        } catch (Exception e) {
            System.out.println(socket.getInetAddress().getHostAddress() + "非正常退出");
        } finally {
            try {
                assert br != null;
                br.close();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}


class Clinet {
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("10.9.62.184", 8888);
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        Scanner scanner = new Scanner(System.in);
        while (true) {
            String next = scanner.next();
            bw.write(next);
            bw.newLine();
            bw.flush();
            if ("拜拜".equals(next)) {
                break;
            }
        }
        bw.close();
        socket.close();
        System.out.println("聊天室关闭");
    }
}

多客户端升级

客户端之间可以交流

public class ChatServer {
    public static ConcurrentHashMap<String, Socket> hashMap = new ConcurrentHashMap<>();

    public static void main(String[] args) {
        //主线程负责侦听
        //1 创建ServerSocket,并指定端口号
        ServerSocket listener = null;
        ExecutorService es = Executors.newCachedThreadPool();

        try {
            listener = new ServerSocket(8888);
            //2 侦听
            System.out.println("聊天室已启动...");
            while (true) {
                Socket socket = listener.accept();
                //放入HashMap中
                hashMap.put(socket.getInetAddress().getHostAddress(), socket);
                System.out.println(socket.getInetAddress().getHostAddress() + "进入聊天室了...");
                es.submit(new DataSocket(socket));
            }

        } catch (IOException e) {
            System.out.println("服务器已关闭...");
        } finally {
            //3关闭
            try {
                listener.close();
                es.shutdown();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
public class DataSocket implements Runnable {

    private Socket socket;

    public DataSocket(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        //接收数据
        BufferedReader br = null;
        try {
            InputStream is = socket.getInputStream();
            br = new BufferedReader(new InputStreamReader(is, "utf-8"));
            String line;
            while ((line = br.readLine()) != null) {
                //(1)如果为null ,说明客户端正常关闭了, (2) 如果客户非正常关闭,抛出异常
                ////////////////转发///////////////////
                int pos = line.indexOf(":");
                String ip = line.substring(0, pos);
                if (ChatServer.hashMap.containsKey(ip)) {
                    Socket toSocket = ChatServer.hashMap.get(ip);
                    OutputStream os = toSocket.getOutputStream();
                    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os, "utf-8"));
                    String d = line.substring(pos + 1);
                    bw.write(socket.getInetAddress().getHostAddress() + ":" + d);
                    System.out.println("转发:" + socket.getInetAddress().getHostAddress() + ":" + d);
                    bw.newLine();
                    bw.flush();
                }
                ///////////////////////////////////
                System.out.println(socket.getInetAddress().getHostAddress() + "说:" + line);
                if (line.equals("byebye") || line.equals("886")) {
                    break;
                }
            }
            System.out.println(socket.getInetAddress().getHostAddress() + "退出了聊天");
        } catch (Exception e) {
            System.out.println(socket.getInetAddress().getHostAddress() + "异常退出了聊天");
        } finally {
            try {
                br.close();
                socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
public class ChatClient {
    static boolean flag = true;

    public static void main(String[] args) throws Exception {
        //(1)创建客户端套接字
        Socket socket = new Socket("10.9.62.184", 8888);

        new Thread(new Runnable() {
            @Override
            public void run() {
                //处理数据
                Scanner input = new Scanner(System.in);
                while (true) {
                    String data = input.next();
                    try {
                        //获取输出流
                        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "utf-8"));
                        bw.write(data);
                        bw.newLine();
                        bw.flush();
                        if (data.equals("byebye") || data.equals("886")) {
                            break;
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                flag = false;
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        if (!flag) {
                            break;
                        }
                        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "utf-8"));
                        String s = br.readLine();
                        String ip = s.substring(0, s.indexOf(":"));
                        System.out.println(ip + "说:" + s);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        //(4)关闭
//        bw.close();
//        socket.close();
//        System.out.println("已关闭");
    }
}

TCP+IO+多线程+集合综合案例

客户端与服务端实现:登录注册功能

用户类

public class User implements Serializable {
    private static final long serialVersionUID = 100L;
    private String id;
    private String name;
    private String pwd;
    private int age;
    private double score;

    public User() {
    }

    public User(String id, String name, String pwd, int age, double score) {
        this.id = id;
        this.name = name;
        this.pwd = pwd;
        this.age = age;
        this.score = score;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }
}
//=================服务端===============
public class UserServer {
    public static void main(String[] args) {
        new Thread(new Regist()).start();
        new Thread(new Login()).start();
    }
}

//实现注册
class Regist implements Runnable {
    @Override
    public void run() {
        try {
            //1.创建ServerSocket,指定端括号
            ServerSocket serverSocket = new ServerSocket(10086);
            //2.侦听返回套接字
            System.out.println("注册服务器已启动。。。。");
            Socket socket = serverSocket.accept();
            //3.获取输入输出流
            ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            //4.处理流
            User o = (User) ois.readObject();
            //4.1 读取硬盘上的集合对象
            File file = new File("regist.bin");
            List<User> users;
            if (file.exists()) {
                ObjectInputStream ois2 = new ObjectInputStream(new FileInputStream(file));
                users = (List<User>) ois2.readObject();
                ois2.close();
            } else {
                users = new ArrayList<>();
            }
            //4.2 判断是否存在
            boolean flag = false;
            for (User user : users) {
                if (user.getId().equals(o.getId())) {
                    flag = true;
                    break;
                }
            }
            if (flag) {
                //注册失败
                bw.write("注册失败,用户ID已经存在!");
            } else {
                //注册成功
                bw.write("注册成功!");
                //将注册信息写入硬盘
                users.add(o);
                ObjectOutputStream os3 = new ObjectOutputStream(new FileOutputStream(file));
                os3.writeObject(users);
                os3.close();
            }
            bw.flush();
            bw.close();
            ois.close();
            socket.close();
            serverSocket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

//实现登录
class Login implements Runnable {
    @Override
    public void run() {
        try {
            //1.创建ServerSocket,指定端括号
            ServerSocket serverSocket = new ServerSocket(6666);
            //2.侦听返回套接字
            System.out.println("登录服务器已启动。。。。");
            Socket socket = serverSocket.accept();
            //3.获取输入输出流
            ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            //4.处理流
            User o = (User) ois.readObject();
            //4.1 读取硬盘上的集合对象
            File file = new File("regist.bin");
            List<User> users = null;
            if (file.exists()) {
                ObjectInputStream ois2 = new ObjectInputStream(new FileInputStream(file));
                users = (List<User>) ois2.readObject();
                ois2.close();
            } else {
                users = new ArrayList<>();
            }
            //4.2 判断是否存在
            boolean flag = false;
            for (User user : users) {
                if (user.getId().equals(o.getId()) && user.getPwd().equals(o.getPwd())) {
                    flag = true;
                    break;
                }
            }
            if (flag) {
                //登录成功
                bw.write("登录成功");
            } else {
                //登录失败
                bw.write("登录失败");
            }
            bw.flush();
            bw.close();
            ois.close();
            socket.close();
            serverSocket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
//=================客户端===============
public class RegistClient {
    public static void main(String[] args) throws Exception {
        System.out.println("1.登录,2.注册");
        Scanner scanner = new Scanner(System.in);
        int i = scanner.nextInt();
        switch (i){
            case 1:
                login();

                break;
            case 2:
                regist();

                break;
            default:
                System.out.println("输入错误!");
                break;
        }
    }

    public static void regist() throws Exception {
        //1.创建客户端的socket
        Socket socket = new Socket("127.0.0.1", 10086);
        //2.获取输入输出流
        ObjectOutputStream os = new ObjectOutputStream(socket.getOutputStream());
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        //3.处理数据
        User user = getUser();
        //3.1序列化
        os.writeObject(user);
        os.flush();
        //3.2读取
        String s = br.readLine();
        System.out.println("服务器回复" + s);
        //4.关闭
        br.close();
        os.close();
        socket.close();
    }

    public static User getUser() {
        Scanner input = new Scanner(System.in);
        System.out.println("请输入用户ID");
        String id = input.next();
        System.out.println("请输入密码");
        String pwd = input.next();
        System.out.println("请输入姓名");
        String name = input.next();
        System.out.println("请输入年龄");
        int age = input.nextInt();
        System.out.println("请输入成绩");
        double aDouble = input.nextDouble();
        return new User(id, name, pwd, age, aDouble);
    }

    public static void login() throws Exception {
        //1.创建客户端的socket
        Socket socket = new Socket("localhost", 6666);
        //2.获取输入输出流
        ObjectOutputStream os = new ObjectOutputStream(socket.getOutputStream());
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        //3.处理数据
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入ID");
        String id = scanner.next();
        System.out.println("请输入密码");
        String pwd = scanner.next();
        //3.1序列化
        os.writeObject(new User(id, null, pwd, 0, 0));
        os.flush();
        //3.2读取
        String s = br.readLine();
        System.out.println("服务器回复" + s);
        //4.关闭
        br.close();
        os.close();
        socket.close();
    }
}

9.2 UDP网络编程

UDP(User Datagram Protocal)协议:

  • 无连接、不可靠、每个数据包大小64k
  • 速度快、可实现广播发送

DatagramSocket:表示用来发送和接收数据报包的套接字

DatagramPacket:表示数据报包

DatagramSocket:

  • DatagramSocket() 构建一个数据报套接字绑定到本地主机的任何可用的端口。
  • DatagramSocket(int port) 构建一个数据报套接字绑定到本地主机的指定端口。

方法:

  • void close() 关闭该数据报套接字。
  • void receive(DatagramPacket p) 接收数据报包从这个插座。
  • void send(DatagramPacket p) 从这个套接字发送数据报包。

DatagramPacket

  • DatagramPacket(byte[] buf, int length) 接收数据包长度 length DatagramPacket构建。
  • DatagramPacket(byte[] buf, int length, InetAddress address, int port) 指定主机上的指定端口发送数据包的长度 length数据报包结构。
  • byte[] getData() 返回数据缓冲区。
  • int getLength() 返回要发送的数据的长度或收到的数据的长度。
  • int getPort() 返回远端端口号,这个数据包被发送或从收到的数据报。
  • InetAddress getAddress() 返回的IP地址的机器,这个数据包被发送或从收到的数据报

两端相互发送接收

public class Receiver {
    public static void main(String[] args) throws Exception {
        //1.创建DatagramSocket
        DatagramSocket ds = new DatagramSocket(9999);
        //2.创建接收数据包
        byte[] buf = new byte[10 * 1024];
        DatagramPacket dp = new DatagramPacket(buf, buf.length);
        //3.接收 阻塞方法,直到收到为止
        System.out.println("准备收包。。。");
        ds.receive(dp);
        //4.处理数据
        //getData() 返回的数据
        //getLength() 实际接收的长度
        String s = new String(dp.getData(), 0, dp.getLength());
        System.out.println(dp.getAddress().getHostAddress() + "说:" + s);
        //4.2 收到后回复
        byte[] bytes = "回复你".getBytes();
        DatagramPacket dp2 = new DatagramPacket(bytes, bytes.length, dp.getAddress(), dp.getPort());
        ds.send(dp2);
        //5.关闭
        ds.close();
    }
}
public class Sender {
    public static void main(String[] args) throws Exception {
        //1.创建DatagramSocket
        DatagramSocket ds = new DatagramSocket();
        //2.创建发送的数据包
        byte[] bytes = "hello".getBytes();
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("127.0.0.1"), 9999);
        //3.发送
        ds.send(dp);
        //3.2 接收对方发送
        byte[] arr = new byte[10*1024];
        DatagramPacket dp2 = new DatagramPacket(arr, arr.length);
        ds.receive(dp2);
        //处理数据
        String s = new String(dp2.getData(), 0, dp2.getLength());
        System.out.println(dp2.getAddress().getHostAddress()+"回复:"+s);
        //4.关闭
        ds.close();
    }
}

实现聊天室

public class ChatReceiver {
    public static void main(String[] args) {
        DatagramSocket ds = null;
        try {
            //(1)创建DatagramScoket
            ds = new DatagramSocket(8888);
            //(2)接收
            byte[] buf = new byte[64 * 1024];
            DatagramPacket dp = new DatagramPacket(buf, buf.length);
            System.out.println("聊天室已启动...");
            while (true) {
                //(3)接收
                ds.receive(dp);
                //(4)处理数据
                String data = new String(dp.getData(), 0, dp.getLength());
                System.out.println(dp.getAddress().getHostAddress() + "说:" + data);
                if (data.equals("byebye") || data.equals("886")) {
                    System.out.println(dp.getAddress().getHostAddress() + "退出了聊天");
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //(5)关闭
            ds.close();
        }
    }
}
public class ChatSender {
    public static void main(String[] args) {
        DatagramSocket ds=null;
        try {
            //(1)创建DatagrameSocket
            ds=new DatagramSocket();
            Scanner input=new Scanner(System.in);
            while(true){
                //(2)创建发送数据报包
                String data = input.next();
                DatagramPacket dp=new DatagramPacket(data.getBytes(), data.getBytes().length,
                        //10.9.62.255 广播地址
                        InetAddress.getByName("10.9.62.255"),8888);
                //(3)发送
                ds.send(dp);
                if(data.equals("byebye")||data.equals("886")){
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            ds.close();
        }
    }
}

[/wppay]