DatagramChannel的用法

本文提供了一个使用Java NIO的DatagramChannel进行网络编程的示例,包括数据接收和服务端响应过程。通过两个类TestDatagramSocketChannel和SendTest展示了如何实现数据包的接收与发送,特别关注了读写操作的切换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

注:本文参照孙卫琴编写的<<网络编程详解>>

一、先给出一个Demo

1、TestDatagramSocketChannel用来接受数据,等待数据,数据长度为10时写出数据

package com.yezi.datagramtest;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;

public class TestDatagramSocketChannel {
	
	private int port[]={8888};
	
	private Selector selector;
	
	public TestDatagramSocketChannel() throws IOException{
		selector = Selector.open();
		for(int i=0;i<port.length;i++){
			DatagramChannel datagramChannel = DatagramChannel.open();
			datagramChannel.socket().bind(new InetSocketAddress(port[i]));
			datagramChannel.configureBlocking(false);
			datagramChannel.register(selector,SelectionKey.OP_READ);  //设置成读取操作
		}
	}
	
	public void testChannel() throws IOException{
		byte bytes[] = new byte[1024];
		int length=0;
		while(true){
			int num = selector.select();
			if(num>0){
				Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
				if(iterator.hasNext()){
					SelectionKey selectionKey = iterator.next();
					DatagramChannel datagramChannel=null;
					if(selectionKey.isReadable()){
						datagramChannel = (DatagramChannel)selectionKey.channel();
						ByteBuffer buffer = ByteBuffer.allocate(3);
						datagramChannel.receive(buffer);
						buffer.flip();  //读取准备
						int readLength = buffer.limit();	
						byte byteread[]=new byte[readLength];
						buffer.get(byteread,0,readLength);
						System.arraycopy(byteread, 0, bytes,length,readLength);
						length+=readLength;
						if(length==10){ //读取的数据达到10哥字节,设置成写出
							datagramChannel.register(selector,SelectionKey.OP_WRITE);
						}
					}else if(selectionKey.isWritable()){
						datagramChannel = (DatagramChannel)selectionKey.channel();
						SocketAddress socketAddress = new InetSocketAddress("127.0.0.1",9998);
						datagramChannel.connect(socketAddress);
						String string = "123456789";
						byte []t= string.getBytes("UTF-8");
						ByteBuffer write = ByteBuffer.wrap(t);
						while(write.hasRemaining()){
							datagramChannel.send(write,socketAddress);
						}
						datagramChannel.register(selector,SelectionKey.OP_READ);
					}
					iterator.remove();
				}
			}
		}
	}
	
	public static void main(String []args) throws IOException{
		new TestDatagramSocketChannel().testChannel();
	}
}


2、发送数据,当写入数据为10时进行数据,线程读取数据

package com.yezi.datagramtest;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.SocketException;

public class SendTest implements Runnable{
	
	private DatagramSocket datagramSocket;
	
	public SendTest(int port) throws SocketException{
		datagramSocket = new DatagramSocket(port);
	}
	
	public void test(String str,SocketAddress address) throws Exception{
		byte [] bytes = str.getBytes("utf-8");
		int sendLength=0;
		DatagramPacket datagramPacket = new DatagramPacket(bytes,0,2,address);
		while(sendLength<bytes.length){
		    datagramSocket.send(datagramPacket);
		    sendLength+=datagramPacket.getLength();
		    int remain = bytes.length-sendLength;
		    int length = (remain>2)?2:remain;
		    datagramPacket.setData(bytes,sendLength,length);
		}
	}
	
	public static void main(String []args) throws Exception {
		SendTest sed = new SendTest(9998);
		new Thread(sed).start();
	    sed.test("1234567890",new InetSocketAddress("127.0.0.1",8888));
	}

	@Override
	public void run() {
		while(true){
			byte[] bytes = new byte[1024];
			DatagramPacket datagramPacket = new DatagramPacket(bytes,0,20);
			try {
				datagramSocket.receive(datagramPacket);
				System.out.println(new String(datagramPacket.getData(),0,datagramPacket.getLength()));
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}


二、在没有绑定固定的远程地址和端口只能使用receive和send方法,绑定了远程地址和端口能使用read和write方法

1、没有绑定固定远程地址和端口,只能使用recive和send

       datagramChannel.send(write,socketAddress);  发送方法

       datagramChannel.receive(buffer);  读取方法,返回SocketAddress

 2、绑定固定的远程地址和远程端口

       TestDatagramSocketChannel的构造函数中加入

       SocketAddress socketAddress = new InetSocketAddress("127.0.0.1",9998);
       datagramChannel.connect(socketAddress);

       后可以直接使用int readLength = datagramChannel.read(buffer);代替datagramChannel.receive(buffer); 

       使用datagramChannel.write(write);代替datagramChannel.send(write,socketAddress);发送数据

三、常见的问题

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值