传输层协议 :User Datagram Protocal
基于报文传输
分类 | TCP | UDP |
---|---|---|
面向连接 | 无连接 | |
只有两端 只能一对一通信 | 可以一对一,一对多,多对一,多对多通信 | |
基于字节流 | 基于报文 | |
重要特性 | 可靠 | 不可爱(尽最大可能交付) |
首部占用空间大 20-60字节之间 | 首部空间小,8字节(记录报文长度) |
UDP的分类
TCP协议已经尽可能的支持了并发 所以大部分还是使用的TCP协议 除非网络很差的情况下使用UDP
服务端
public class udpServer {
public static void main(String[] args) throws Exception {
//DatagramSocket - 用来建立连接,通信的一端
DatagramSocket socket = new DatagramSocket(6789);
//DatagramPacket - 报文
DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
while (true) {
socket.receive(packet);
byte[] msg = Arrays.copyOfRange(packet.getData(), packet.getOffset(), packet.getOffset() + packet.getLength());
System.out.println("Receive data" + new String(msg));
System.out.println("Receive data Form" + packet.getAddress().getHostAddress());
socket.send(packet);
}
}
}
客户端
//单播的通信方式
public class udpClient {
public static void main(String[] args) throws Exception {
//如果使用多播 使用 MulticastSocket
DatagramSocket socket = new DatagramSocket();
InetAddress localHost = InetAddress.getLocalHost();
SocketAddress socketAddress = new InetSocketAddress(localHost, 6789);
byte[] msg = new String("hello udp server").getBytes();
DatagramPacket packet = new DatagramPacket(msg, msg.length, socketAddress);
socket.send(packet);
socket.close();
}
}
服务端
public class udpNettyServer {
public static void main(String[] args) {
EventLoopGroup group = new NioEventLoopGroup();
//可以统一使用bootstrap进行配置
Bootstrap bootstrap = new Bootstrap();
//实现udp协议 使用的通道
bootstrap.group(group).channel(NioDatagramChannel.class)
.localAddress(6789)
.handler(new UdpServerHandler());
try {
ChannelFuture future = bootstrap.bind(6789).sync();
future.channel().closeFuture().await();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
group.shutdownGracefully();
}
}
}
//DatagramPacket 使用的是netty包下的
class UdpServerHandler extends SimpleChannelInboundHandler<DatagramPacket> {
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, DatagramPacket datagramPacket) throws Exception {
System.out.println("receive packet" + datagramPacket.content().toString());
ByteBuf buf = Unpooled.copiedBuffer("Sth", CharsetUtil.UTF_8);
//通过组装bytebuf 获取发送报文的发送者 得到要返回的报文
DatagramPacket packet = new DatagramPacket(buf, datagramPacket.sender());
channelHandlerContext.writeAndFlush(packet);
}
}
客户端
public class udpNettyClient {
public static void main(String[] args) {
EventLoopGroup group = new NioEventLoopGroup();
//可以统一使用bootstrap进行配置
Bootstrap bootstrap = new Bootstrap();
//实现udp协议 使用的通道
bootstrap.group(group).channel(NioDatagramChannel.class)
.remoteAddress("127.0.0.1", 6789)
.handler(new udpClientHandler());
try {
Channel channel = bootstrap.bind(0).sync().channel();
ByteBuf buf = Unpooled.copiedBuffer("Send sth", CharsetUtil.UTF_8);
//通过组装bytebuf 获取发送报文的发送者 得到要返回的报文
DatagramPacket packet = new DatagramPacket(buf, SocketUtils.socketAddress("127.0.0.1", 6789));
channel.writeAndFlush(packet).sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
group.shutdownGracefully();
}
}
}
class udpClientHandler extends SimpleChannelInboundHandler<DatagramPacket> {
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, DatagramPacket datagramPacket) throws Exception {
String resp = datagramPacket.content().toString(CharsetUtil.UTF_8);
System.out.println(resp);
channelHandlerContext.close();
}
}