java中使用UDP接收的数据放在哪里了呢,

Python025

java中使用UDP接收的数据放在哪里了呢,,第1张

先了解下网络七层协议,知道网络通讯是怎么回事。

第7层 应用层:OSI中的最高层。为特定类型的网络应用提供了访问OSI环境的手段。应用层确定进程之间通信的性质,以满足用户的需要。应用层不仅要提供应用进程所需要的信息交换和远程操作,而且还要作为应用进程的用户代理,来完成一些为进行信息交换所必需的功能。它包括:文件传送访问和管理FTAM、虚拟终端VT、事务处理TP、远程数据库访问RDA、制造报文规范MMS、目录服务DS等协议;

第6层 表示层:主要用于处理两个通信系统中交换信息的表示方式。为上层用户解决用户信息的语法问题。它包括数据格式交换、数据加密与解密、数据压缩与恢复等功能;

第5层 会话层:—在两个节点之间建立端连接。为端系统的应用程序之间提供了对话控制机制。此服务包括建立连接是以全双工还是以半双工的方式进行设置,尽管可以在层4中处理双工方式 ;

第4层 传输层:—常规数据递送-面向连接或无连接。为会话层用户提供一个端到端的可靠、透明和优化的数据传输服务机制。包括全双工或半双工、流控制和错误恢复服务;

第3层 网络层:—本层通过寻址来建立两个节点之间的连接,为源端的运输层送来的分组,选择合适的路由和交换节点,正确无误地按照地址传送给目的端的运输层。它包括通过互连网络来路由和中继数据 ;

第2层 数据链路层:—在此层将数据分帧,并处理流控制。屏蔽物理层,为网络层提供一个数据链路的连接,在一条有可能出差错的物理连接上,进行几乎无差错的数据传输。本层指定拓扑结构并提供硬件寻址;

第1层 物理层:处于OSI参考模型的最底层。物理层的主要功能是利用物理传输介质为数据链路层提供物理连接,以便透明的传送比特流。

数据发送时,从第七层传到第一层,接收数据则相反。

上三层总称应用层,用来控制软件方面。下四层总称数据流层,用来管理硬件。

我自己写的代码:

import java.io.IOException

import java.net.DatagramPacket

import java.net.DatagramSocket

import java.net.InetAddress

import java.net.SocketException

import java.net.UnknownHostException

public class UdpRecvDemo

{

    public static void main(String[] args) throws IOException

    {

        Recv()

    }

    

    public static void Recv() throws IOException

    {

        System.out.println("接受开始......")

        DatagramSocket ds = new DatagramSocket(3388)

        while(true)

        {

            byte[]buf = new byte[1024]

            DatagramPacket dp = new DatagramPacket(buf,buf.length)

            ds.receive(dp)

            System.out.println(ds)

            String ip = dp.getAddress().getHostAddress()

            int port = dp.getPort()

            String text = new String(dp.getData(),0,dp.getLength())

            if(text.equals("exit"))

                {

                    System.out.println(ip+"退出会话......")

                    break

                }

            System.out.println(ip+":"+port+"===>me "+text)

        }

        ds.close()

    }

}

Socket套接字,是由系统提供用于网络通信的技术(操作系统给应用程序提供的一组API叫做Socket API),是基于TCP/IP协议的网络通信的基本操作单元。基于Socket套接字的网络程序开发就是网络编程。

socket可以视为是应用层和传输层之间的通信桥梁;

传输层的核心协议有两种:TCP,UDP;socket API也有对应的两组,由于TCP和UDP协议差别很大,因此,这两组API差别也挺大。

分类:

Socket套接字主要针对传输层协议划分为如下三类:

流套接字:使用传输层TCP协议

TCP,即Transmission Control Protocol(传输控制协议),传输层协议;

TCP的特点:

有连接:像打电话,得先接通,才能交互数据;

可靠传输:传输过程中,发送方知道接收方有没有收到数据.(打电话就是可靠传输);

面向字节流:以字节为单位进行传输.(非常类似于文件操作中的字节流);

全双工:一条链路,双向通信;

有接收缓冲区,也有发送缓冲区。

大小不限

对于字节流来说,可以简单的理解为,传输数据是基于IO流,流式数据的特征就是在IO流没有关闭的情况下,是无边界的数据,可以多次发送,也可以分开多次接收。

数据报套接字:使用传输层UDP协议

UDP,即User Datagram Protocol(用户数据报协议),传输层协议。

UDP的特点:

无连接:像发微信,不需要接通,直接就能发数据;

不可靠传输:传输过程中,发送方不知道接收方有没有收到数据.(发微信就是不可靠传输);

面向数据报:以数据报为单位进行传输(一个数据报都会明确大小)一次发送/接收必须是一个完整的数据报,不能是半个,也不能是一个半;

全双工:一条链路,双向通信;

有接收缓冲区,无发送缓冲区;

大小受限:一次最多传输64k;

对于数据报来说,可以简单的理解为,传输数据是一块一块的,发送一块数据假如100个字节,必须一次发送,接收也必须一次接收100个字节,而不能分100次,每次接收1个字节。

原始套接字

原始套接字用于自定义传输层协议,用于读写内核没有处理的IP协议数据。

二、UDP数据报套接字编程

UDPSocket中,主要涉及到两类:DatagramSocket、DatagramPacket

DatagramSocket API

DatagramSocket 创建了一个UDP版本的Socket对象,用于发送和接收UDP数据报,代表着操作系统中的一个socket文件,(操作系统实现的功能–>)代表着网卡硬件设备的抽象体现。

DatagramSocket 构造方法:

方法签名 方法说明

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

DatagramSocket(int port) 创建一个UDP数据报套接字的Socket,绑定到本机指定的端口(一般用于服务端)

DatagramSocket 方法:

方法签名 方法说明

void receive(DatagramPacket p) 从此套接字接收数据报(如果没有接收到数据报,该方法会阻塞等待)

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

void close() 关闭此数据报套接字

DatagramPacket API

代表了一个UDP数据报,是UDP Socket发送和接收的数据报,每次发送/接收数据报,都是在传输一个DatagramPacket对象。

DatagramPacket 构造方法:

方法签名 方法说明

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

DatagramPacket(byte[] buf, int offset, int length,SocketAddress address) 构造一个DatagramPacket以用来发送数据报,发送的数据为字节数组(第一个参数buf)中,从0到指定长度(第二个参数length)。address指定目的主机的IP和端口号

DatagramPacket 方法:

方法签名 方法说明

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

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

byte[] getData() 获取数据报中的数据

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

InetSocketAddress API

InetSocketAddress ( SocketAddress 的子类 )构造方法:

方法签名 方法说明

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

示例1:写一个简单的客户端服务程序,回显服务(EchoSever)

在这里插入图片描述

构建Socket对象有很多失败的可能:

端口号已经被占用,同一个主机的两个程序不能有相同的端口号(这就好比两个人不能拥有相同的电话号码);

此处,多个进程不能绑定同一个端口号,但是一个进程可以绑定多个端口,(这就好比一个人可以拥有多个手机号),一个进程可以创建多个Socket对象,每个Socket都绑定自己的端口。

每个进程能够打开的文件个数是有上限的,如果进程之间已经打开了很多文件,就可能导致此时的Socket文件不能顺利打开;

在这里插入图片描述

这个长度不一定是1024,假设这里的UDP数据最长是1024,实际的数据可能不够1024.

在这里插入图片描述

这里的参数不再是一个空的字节数组了,response是刚才根据请求计算的得到的响应,是非空的,DatagramPacket 里面的数据就是String response的数据。

response.getBytes().length:这里拿到的是字节数组的长度(字节的个数),而response.length得到的是字符的长度。

五元组

一次通信是由5个核心信息描述的:源IP、 源端口、 目的IP、 目的端口、 协议类型。

站在客户端角度:

源IP:本机IP;

源端口:系统分配的端口;

目的IP:服务器的IP;

目的端口:服务器的端口;

协议类型:TCP;

站在服务器的角度:

源IP:服务器程序本机的IP;

源端口:服务器绑定的端口(此处手动指定了9090);

目的IP:包含在收到的数据报中(客户端的IP);

目的端口:包含在收到的数据报中(客户端的端口);

协议类型:UDP;