UDP socket

目录

UDP socket api的使用

核心的类:

1.DatagramSocket 

2.DatagramPacket

DatagramSocket方法:

DatagramPacket方法:

回显服务器

服务器代码实现

代码:

分析:

总结:


        封装和分用是网络数据传输过程中不可或缺的流程。

操作系统提供的api:TCP api,UDP api

操作系统提供进行网络编程的api也叫”socket api“”网络编程套接字“

UDP socket api的使用

核心的类:

1.DatagramSocket 

该类是UDP Socket用于发送和接收UDP数据报

负责对socket文件读写,借助网卡发送接收数据。

操作系统中有一类文件,叫做socket文件抽象表示了”网卡“这样的硬件设备

进行网络通信最核心的硬件设备:网卡

通过网卡发送数据,就是写socket文件;通过网卡接收数据,就是读socket文件。

DatagramSocket():创建一个UDP数据报套接字的Socket,绑定到本机任意一个随机端口(客户端)

DatagramSocket(int port):创建一个UDP数据报套接字的Socket,绑定到指定端口(服务器)

2.DatagramPacket

该类是UDP Socket发送和接收的数据报

UDP面向数据报,每次发送接收数据的基本单位,就是一个UDP数据报

DatagramPacket(byte[ ] buf, int length):构造一个DatagramPacket用来接收数据报,接收的数据保存在字节数组(第一个参数)接收指定长度(第二个参数)

DatagramPacket(byte[ ] buf, int offest, int length, SocketAddress address):SocketAddress address => 目的主机的IP和端口号。

构造UDP发送的数据报时,需要传入SocketAddress可以用InetSocketAddress来创建。

InetSocketAddress(SocketAddress的子类)

   InetSocketAddress(InetAddress addr,int port):创建一个socket地址,包含IP地址和端口号

DatagramSocket方法:

void receive(DatagramPacket p):从此套接字,接收数据包(没有接收到,阻塞等待)

void send(DatagramPacket p):从此套接字,发送数据包(不会阻塞等待,直接发送)

DatagramPacket方法:

InetAddress getAddress():接收的数据报中,获取发送端主机IP地址。/ 从发送的数据报中,获取接收端主机IP地址。

int getPort():接收的数据报中,获取发送端主机端口号。/ 从发送的数据报中,获取接收端主机端口号。

byte[] getDate():获取数据报中的数据。

回显服务器

网络编程中,最简单的程序 => 网络编程中的hello world。

客户端发什么请求服务器返回什么响应(没有什么业务逻辑)

1.socket api的使用

2.典型的服务器客户端的基本工作流程

服务器代码实现

代码:

public class UdpEchoServer {
    private DatagramSocket socket = null;
    //第一步:创建DatagramSocket对象
    public UdpEchoServer(int port) throws SocketException {
        socket = new DatagramSocket(port);
    }
    //服务器的启动逻辑
    public void start() throws IOException {
        System.out.println("服务器启动!");
        //每次循环,就是处理一个请求响应的过程
        while(true){
            //1.读取请求并解析
            DatagramPacket requsetPacket = new DatagramPacket(new byte[4096],4096);
            socket.receive(requsetPacket);
            //读取到的字节数组,转换成String方便后续的逻辑处理
            String request = new String(requsetPacket.getData(),0, requsetPacket.getLength());
            //2.根据请求计算响应(对于回显服务器,这一步什么都不用做)
            String response = process(request);
            //3.把响应返回到客户端,构造一个DatagramPacket作为响应对象
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),
                    response.getBytes().length,requsetPacket.getSocketAddress());
            socket.send(responsePacket);
            //打印日志
            System.out.printf("[%s: %d] req:%s,resp:%s\n",
                    requsetPacket.getAddress().toString(),
                    requsetPacket.getPort(),
                    request,
                    response);
        }
    }
    public String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        UdpEchoServer server = new UdpEchoServer(9090);
        server.start();
    }
}

分析:

创建对象的时候手动指定一个端口号(在运行一个服务器程序的时候,通常会手动指定端口)

接下来就要操作网卡,操作网卡都是通过socket对象来完成的。这个程序一旦启动就需要关联上/绑定上一个操作系统的端口号 => 是一个整数,用来区分一个主机上进行网络通信的程序(1024< port<65534)

一个主机上的一个端口号,只能被一个进程绑定。

一个端口已经被金册灰姑娘1绑定了,进程2也想绑定,就会失败,除非1释放这个端口。

一个进程可以绑定多个端口号。 

端口号的socket对象是一一对应的,如果一个进程中多个socket对象就能绑定多个端口。

SocketExpection:网络编程中常见的异常,通常表示socket创建失败。(比如:端口号已经被别的进程占用了)

对于服务器来说,需要不断的接受请求,返回响应,接受请求,返回响应......一个服务器往往是7*24小时运行的,要持续不断运行下去,这里的while true没有退出的必要。如果想重启服务器,可以直接杀进程。

通过这个字节数组保存收到的消息正文(应用层数据包) => 也就是UDP载荷部分

此处socket就从网卡中读取到一个UDP数据报,就能放到requestPacket对象中了。

其中UDP数据报的载荷部分就被放到了requestPacket内置的字节数组里了,另外报头也会被requestPacket其他属性保存。除了UDP报头之外,其他信息,比如收到的数据源IP是啥。

通过requestPacket还能知道数据从哪里来的(源IP,源端口)

如果执行到receive,还没有客户端发请求(阻塞等待)

requsetPacket.getData() => 对应 new byte[4096]

  0 => 从字节数组为0位置开始构造String

requsetPacket.getLength() => 获取到字节数组中有效数据的长度,用来构造String      

基于字节数组构造出string,字节数组中保存的内容可能为二进制数据/文本数据,把文本数据交给String保存恰到好处,就算是二进制数据,Java的string也能保存。

此处是回显服务器,只是单纯的retrun。

requsetPacket => 客户端来的数据报
requsetPacket.getSocketAddress() => 得到InetAddress对象 => 包括ip和端口和服务器对端的ip和端口。

把请求的源IP和源端口,作为响应的目的IP和目的端口,就可以做到把消息返回给客户端了。

总结:

        上述代码中,可以看到UDP是无连接的通信。

        UDP socket自身不保存对端的IP和端口,而是在每个数据报中有一个。另外代码也没有“建立连接”“接受连接”操作。

        面向数据报:send和receive都是通过Datagram Packet为单位

        全双工:一个socket既可以发送也可以接收

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值