JAVA网络编程(UDP入门篇)

网络编程:通过计算机语言实现资源的共享

网络编程模型数据一层层的封装打包

应用层:eg:应用程序,qq
表示层:
会话层:
传输层:
网络层:数据传输
数据链路层:数据帧,使用交换机传递数据
物理层 : 将数据转化为1,0数据

应用程序:网络编程+IO+多线程

此博客的主角是网路层

java针对网络编程提供的类都在java.net下面

网络编程的要素

 A:IP地址  找到对应的应用程序 
 B:端口号  对应的应用程序的标识  
 C:协议    通过某个规则协议进行

IP地址:是每台计算机在网络中的唯一标识

 eg:192.1668.32.80
 注意:
     计算机在网络中的唯一标识肯定不是这样的:
     所以得转化成二进制的数据,计算机才能够识别:
     11000000 10101000 00100000 01010000
那为什么每次我们配置ip地址不配成二进制的? 
     因为二进制的数据我们并不常用,且不方便记忆,并推出了记忆ip地址的方案:“点分十进制”

ip地址的组成:

网络号+主机端号

IP地址的分类:

A:0.0.0.0~127.255.255.255   
B:128.0.0.0~191.255.255.255
C:192.0.0.0~223.255.255.255
D:不常见
E:不常见

A类:第一段表示网络号段,后三段表示主机号码

网络号码:256*256*256  16777216(可以给这么多的计算机使用)
稀少:一般是国家使用,eg 军队 电信

B类:前两段表示网络号段,后两端表示主机号码

网络号码:256*256  65536
eg:大学校园网

C类:前一段表示网络号段,后三段表示主机号码

网络号码:256
eg:家庭,

局域网IP地址的常见配置

192.168.x.x (常见)
10.x.x.x (一般公司开头)

特殊地址:

x.x.x.0 网络号
x.x.x.255 广播号

InetAddress

package com.net;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * 如果一个类没有构造方法是什么情况?
 * 1:单例模式
 * 2:类中的成员都是静态的(Arrays,Math,Collections)
 * 3:通过一个静态方法返回本身对象。
 * class Demo{
 *  private Demo();
 *  public static Demo getDemo(){
 *      return new Demo();
 *  }
 * }
 * @author yuliyang
 * @version $Id: InetAddressDemo.java, v 0.1 2016年11月21日 下午10:03:43 yuliyang Exp $
 */
public class InetAddressDemo {
    public static void main(String[] args) throws UnknownHostException {
        //根据主机名获取到IP地址对象
        //InetAddress address = InetAddress.getByName("yly");
        InetAddress address = InetAddress.getByName("192.168.31.223");
        System.out.println(address);
        //获取主机名
        String hostNam = address.getHostName();
        //获取IP地址
        String ipAddress = address.getHostAddress();
        System.out.println(hostNam + "---" + ipAddress);

    }
}

端口号:每一个进程的逻辑地址,是一个标识号
一个进程是一个应用程序,,所以,我们说端口号也是一个应用程序的标识号

范围

   0-65535之间
   0-1024之间不要随意使用,因为它被保留或者被系统进程占用,

协议

通信的规则

UDP(效率):把数据打包,不建立连接,导致数据不可靠,且数据有限制,64k=32768个汉字,但是速度快效率高。

TCP(安全):建立连接通道,三次握手协议,只要通道没有断开,数据没有限制,数据可靠,但是耗时速度慢,

一般的应用程序又有UDP(类似于群聊)又有TCP(类似于单聊)协议

1:简单的UDP代码

send端


package com.net.udp;

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

/**
 * UDP发送数据的步骤
 * A:创建发送端的socket服务对象
 * B:创建数据,并将数据打包
 * C:通过socket对象的发送功能发送数据包
 * D:释放资源
 * 
 */
public class SendDemo {
    public static void main(String[] args) throws IOException {
        //A:创建发送端的socket服务对象
        DatagramSocket dSocket = new DatagramSocket();
        /**
         *  B:创建数据,并将数据打包
         *  buf:要发送的数据信息
         *  length:发送的数据长度
         *  address:表示要发到哪里去,对于的那个IP地址
         *  port:端口号
         * getBytes()使用平台的默认字符集将此 String 编码为 byte 序列,
         * 并将结果存储到一个新的 byte 数组中
         */
        byte[] buf = "hello test socket".getBytes();
        int length = buf.length;
        InetAddress address = InetAddress.getByName("192.168.31.222");
        int port = 10010;
        DatagramPacket p = new DatagramPacket(buf, length, address, port);
        //C:通过socket对象的发送功能发送数据包
        dSocket.send(p);
        //D:关闭
        dSocket.close();
    }
}

receiver

package com.net.udp;

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

/**
 * UDP协议接收数据步骤
 * A:创建接收端的socket对象
 * B:创建一个数据包用于接收数据
 * C:接收数据
 * D:解析数据,并显示在控制台
 * E:释放资源
 * 
 */
public class ReceiveDemo {
    public static void main(String[] args) throws IOException {
        //A:创建接收数据的socket对象,并指定端口号(端口号随意只要与send端一致就行)
        DatagramSocket ds = new DatagramSocket(10086);
        /**
         * B:设置缓冲区
         * new String(byte[] buf,int index,int length);
         * 通过使用平台默认的字符集解码指定的byte数组
         * buf;要解码的数组
         * index:要解码的第一个buf的索引
         * length:要解码的byte数(并不是buf的长度)
         * p.getLength:将要发送或接收到的数据的长度。
         */
        byte[] buf = new byte[1024];
        int length = buf.length;
        DatagramPacket dp = new DatagramPacket(buf, length);
        //C接收数据
        ds.receive(dp); //阻塞式方式,所以会一直在运行
        //D:解析数据
        InetAddress address = dp.getAddress();
        String ip = address.getHostName();
        //返回缓冲区
        byte[] byss = dp.getData();
        //返回实际长度
        int len = dp.getLength();
        String s = new String(byss, 0, len);
        System.out.println(ip + "--" + s);
        //E:释放资源
        ds.close();
    }
}

如果想要不同的电脑都看到结果的话,就将IP地址改为广播地址X.X.X.255,就实现了不同电脑都可以看到你发送的消息了,

另外增强版:主要模拟qq发送消息实现,此处增加IO以及线程实现聊天功能

聊天控制端

package com.net.udp4;

import java.io.IOException;
import java.net.DatagramSocket;

/**
 * 多线程改进聊天
 */
public class ChatDemo {
    public static void main(String[] args) throws IOException {
        DatagramSocket sendSocket = new DatagramSocket();
        DatagramSocket receiveSocket = new DatagramSocket(12580);
        SendThread sendT = new SendThread(sendSocket);
        ReceiveThread receiveT = new ReceiveThread(receiveSocket);
        Thread send = new Thread(sendT);
        Thread receive = new Thread(receiveT);
        send.start();
        receive.start();
    }
}

增强版send端

package com.net.udp4;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class SendThread implements Runnable {
    DatagramSocket sendSocket;

    public SendThread(DatagramSocket sendSocket) {
        this.sendSocket = sendSocket;
    }

    @Override
    public void run() {
        //封装键盘录入
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line = null;
        try {
            while ((line = br.readLine()) != null) {
                if ("88".equals(line)) {
                    break;
                }
                byte[] buf = line.getBytes();
                //改成广播地址192.168.31.255
                DatagramPacket p = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.31.255"), 12580);
                sendSocket.send(p);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        sendSocket.close();
    }
}

增强版接收端

package com.net.udp4;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class ReceiveThread implements Runnable {
    DatagramSocket receiveSocket;
    public ReceiveThread(DatagramSocket receiveSocket) {
        this.receiveSocket = receiveSocket;
    }
    @Override
    public void run() {
        while (true) {
            byte[] buf = new byte[1024];
            /**
             * buf - 保存传入数据报的缓冲区。
             * len - 要读取的字节数。
             */
            DatagramPacket p = new DatagramPacket(buf, buf.length);
            try {
                receiveSocket.receive(p);
            } catch (IOException e) {
                e.printStackTrace();
            }
            String ip = p.getAddress().getHostAddress();
            String name = p.getAddress().getHostName();
            String parse = new String(p.getData(), 0, p.getLength());
            System.out.println("ip地址为:" + ip + ";计算机名为:" + name + ";发的消息为  " + parse);
            //接收端相当于服务器,所以不能一次执行之后就结束,且不需要关闭
            //receiveSocket.close();
        }
    }
}

大致实现的功能展示(很简陋) 222是我自己,159 是另外一台电脑:
这里写图片描述
这样,大概的功能就展现出来了,我就可以看到自己发送的消息,以及别人发送的消息了,只是样式很丑啦。。。。哈哈哈哈哈哈。
–end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值