java udp bind_DatagramChannel java基于UDP的通讯

客户端

import java.net.*;

import java.nio.channels.*;

import java.nio.*;

import java.io.*;

import java.nio.charset.*;

import java.util.*;

public class DatagramChannelClient

{

//DatagramChannel针对面向数据报的可选择通道

private DatagramChannel datagramChannel=null;

//ByteBuffer字节缓冲区 ByteBuffer.allocate(int capacity)设置字节缓冲区的容量

//初始化两个字节缓冲区 sendBuffer和receiveBuffer 用来接受和发送数据

private ByteBuffer sendBuffer=ByteBuffer.allocate(1024);

private ByteBuffer receiveBuffer=ByteBuffer.allocate(1024);

//Charset类

private Charset charset=Charset.forName("GBK");

//Selector SelectableChannel对象的多路复用器

private Selector selector;

public DatagramChannelClient()throws IOException

{

this(7000);

}

public DatagramChannelClient(int port)throws IOException

{

//DatagramChannel类的静态方法open()打开数据报通道

datagramChannel=DatagramChannel.open();

//InetAddress.getLocalhost()返回本地主机的IP地址

InetAddress add=InetAddress.getLocalHost();

//构造方法InetSocketAddress(InetAddress addr,int

port)根据指定的IP地址和端口号来创建套接字地址

InetSocketAddress address=new InetSocketAddress(add,port);

//设置为非阻塞模式 DatagramChannel类的configureBlocking(blooean

block)block为true则通道处于阻塞模式,block为false则通道处于非阻塞模式

datagramChannel.configureBlocking(false);

datagramChannel.socket().bind(address);

//与远程地址相连

address=new InetSocketAddress(add,8000);

//Selector类的静态方法open()打开一个选择器

selector=Selector.open();

}

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

{

// TODO Auto-generated method stub

int port=8793;

if(args.length>0)

{

//在参数中指定端口号

port=Integer.parseInt(args[0]);

}

final DatagramChannelClient client=new

DatagramChannelClient(port);

//receiver线程

Thread receiver=new Thread()

{

//run()方法

public void run()

{

client.receiveFromUser();

}

};

//调用start()方法 线程开始运行

receiver.start();

client.talk();

}

public void receiveFromUser()

{

try

{

//读取用户键盘输入

BufferedReader localReader=new BufferedReader(new

InputStreamReader(System.in));

String msg=null;

//按行读取数据

while((msg=localReader.readLine())!=null)

{

//synchronized关键字

synchronized(sendBuffer)

{

sendBuffer.put(encode(msg+"\r\n"));

}

if(msg.equals("bye"))

{

break;

}

}

}

catch(IOException e)

{

e.printStackTrace();

}

}

public void talk()throws IOException

{

datagramChannel.register(selector, SelectionKey.OP_READ,

SelectionKey.OP_WRITE);

while(selector.select()>0)

{

Set readyKeys=selector.selectedKeys();

Iterator it=readyKeys.iterator();

while(it.hasNext())

{

SelectionKey key=null;

try

{

key=(SelectionKey)it.next();

it.remove();

if(key.isReadable())

{

receive(key);

}

if(key.isWritable())

{

send(key);

}

}

catch(IOException e)

{

e.printStackTrace();

try

{

if(key!=null)

{

key.cancel();

key.channel().close();

}

}

catch(IOException o)

{

o.printStackTrace();

}

}

}

}

}

public void send(SelectionKey key)throws IOException

{

DatagramChannel

datagramChannel=(DatagramChannel)key.channel();

synchronized(sendBuffer)

{

sendBuffer.flip();

datagramChannel.write(sendBuffer);

sendBuffer.compact();

}

}

public void receive(SelectionKey key)throws IOException

{

DatagramChannel

datagramChannel=(DatagramChannel)key.channel();

datagramChannel.read(receiveBuffer);

receiveBuffer.flip();

String receiveData=decode(receiveBuffer);

if(receiveData.indexOf("\n")==-1)

{

return;

}

String

outputData=receiveData.substring(0,receiveData.indexOf("\n")+1);

System.out.println(outputData);

if(outputData.equals("echo:bye\r\n"))

{

key.cancel();

datagramChannel.close();

System.out.println("关闭与服务器的连接");

selector.close();

System.exit(0);

}

ByteBuffer temp=encode(outputData);

receiveBuffer.compact();

}

//解码

public String decode(ByteBuffer buffer)

{

CharBuffer charBuffer=charset.decode(buffer);

return charBuffer.toString();

}

//编码

public ByteBuffer encode(String str)

{

return charset.encode(str);

}

}

服务器端

import java.io.*;

import java.net.*;

import java.nio.*;

import java.nio.channels.*;

import java.nio.charset.*;

public class DatagramChannelServer

{

private int port=8000;

//DatagramChannel 针对面向数据报套接字的可选择通道

private DatagramChannel channel;

private final int MAX_SIZE=1024;

public DatagramChannelServer()throws IOException

{

//调用DatagramChannel类的静态方法DatagramChannel.open()打开数据报通道

channel=DatagramChannel.open();

//socket()检索与此数据报通道关联的数据报套接字

DatagramSocket socket=channel.socket();

//Socketaddress

SocketAddress localAddr=new InetSocketAddress(8000);

//DatagramSocket类的方法bind(SocketAddress addr)

将DatagramSocket绑定到指定的地址和端口

socket.bind(localAddr);

//服务器启动

System.out.println("服务器启动");

}

public String echo(String msg)

{

return "echo:"+msg;

}

public void service()

{

//ByteBuffer字节缓冲区 ByteBuffer.allocate(int capacity)分配一个新的缓冲区

capacity为缓冲区的容量

ByteBuffer receiveBuffer=ByteBuffer.allocate(MAX_SIZE);

while(true)

{

try

{

//清除字节缓冲区 将位置设置为0

receiveBuffer.clear();

InetSocketAddress

client=(InetSocketAddress)channel.receive(receiveBuffer);

//flip()反转缓冲区 首先对当前位置限制 然后将当前位置设置为零

receiveBuffer.flip();

//java.nio.charset.Charset Charset名称必须以字母或数字开头 空字符串不是合法的Charset名称

Charset名称是大小写不敏感的

//forName(String charsetName)返回命名Charset的Charset对象

decoade(ByteBuffer bb)将Charset中的字节解码成unicode字符

String

msg=Charset.forName("GBK").decode(receiveBuffer).toString();

System.out.println(client.getAddress()+":"+client.getPort()+">"+msg);

//DatagramChannel类的send(ByteBuffer src,SocketAddress

target)通过通道发送数据报

channel.send(ByteBuffer.wrap(echo(msg).getBytes()), client);

}

catch(IOException e)

{

e.printStackTrace();

}

}

}

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

{

// TODO Auto-generated method stub

new DatagramChannelServer().service();

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值