服务器端:
package test.hhd.Socket;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
public class SocketServer {
private int port = 9000;
private ServerSocketChannel serverSocketChannel;
private Charset charset = Charset.forName("UTF-8");
private Selector selector = null;
public SocketServer() throws IOException {
selector = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().setReuseAddress(true);
serverSocketChannel.socket().bind(
new InetSocketAddress(port));
System.out.println("服务器启动");
}
public void service() throws IOException {
serverSocketChannel.configureBlocking(false);
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (selector.select() > 0) {
/* 得到已经被捕获了的SelectionKey的集合 */
Iterator iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey key = null;
try {
key = (SelectionKey) iterator.next();
iterator.remove();
if (key.isAcceptable()) {
ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
SocketChannel sc = ssc.accept();
System.out.println("客户端机子的地址是 "
+ sc.socket().getRemoteSocketAddress()
+ " 客户端机机子的端口号是 "
+ sc.socket().getLocalPort());
sc.configureBlocking(false);
ByteBuffer buffer = ByteBuffer.allocate(1024);
sc.register(selector, SelectionKey.OP_READ , buffer);//buffer通过附件方式,传递
}
if (key.isReadable()) {
reveice(key);
}
if (key.isWritable()) {
//send(key);
}
} catch (IOException e) {
e.printStackTrace();
try {
if (key != null) {
key.cancel();
key.channel().close();
}
} catch (ClosedChannelException cex) {
e.printStackTrace();
}
}
}
}
}
/* 接收 */
public void reveice(SelectionKey key) throws IOException {
if (key == null)
return;
//***用channel.read()获取客户端消息***//
//:接收时需要考虑字节长度
SocketChannel sc = (SocketChannel) key.channel();
String content = "";
ByteBuffer buf = ByteBuffer.allocate(128);
int bytesRead = sc.read(buf); //read into buffer.
while (bytesRead >0) {
buf.flip(); //make buffer ready for read
content += charset.decode(buf);
buf.clear(); //make buffer ready for writing
bytesRead = sc.read(buf);
}
System.out.println("接收:" + content.trim());
}
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
new SocketServer().service();
}
}
读取线程:
package test.hhd.Socket;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
public class ReadThread implements Runnable {
// 监听器,如果缓冲区有数据,通知程序接收
private Selector selector;
private Charset charset = Charset.forName("UTF-8");
String imei;
public ReadThread(Selector selector, String imei) {
this.selector = selector;
this.imei = imei;
new Thread(this).start();
}
@Override
public void run() {
try {
// 轮询访问selector
while (true) {
selector.select();//如果队列有新的Channel加入,那么Selector.select()会被唤醒
// 获得selector中选中的项的迭代器
Iterator ite = this.selector.selectedKeys().iterator();
while (ite.hasNext()) {
SelectionKey key = (SelectionKey) ite.next();
// 删除已选的key,以防重复处理
ite.remove();
// 连接事件发生
if (key.isConnectable()) {
SocketChannel channel = (SocketChannel) key.channel();
// 如果正在连接,则完成连接
if (channel.isConnectionPending()) {
channel.finishConnect();
}
// 设置成非阻塞
channel.configureBlocking(false);
//给服务端发送信息
channel.write(ByteBuffer.wrap(new String("SocketChannel与ByteBuffer应用!").getBytes(charset)));
//在和服务端连接成功之后,为了可以接收到服务端的信息,需要给通道设置读的权限。
channel.register(this.selector, SelectionKey.OP_READ );
} else if (key.isReadable()) {
read(key);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 处理读取服务端发来的信息 的事件
*
* @param key
* @throws IOException
*/
public void read(SelectionKey key) throws IOException {
// 服务器可读取消息:得到事件发生的Socket通道
SocketChannel channel = (SocketChannel) key.channel();
// 创建读取的缓冲区
ByteBuffer buffer = ByteBuffer.allocate(10);
channel.read(buffer);
byte[] data = buffer.array();
String msg = new String(data).trim();
System.out.println("服务端收到信息:" + msg);
}
public static final String btyetoString(byte[] bArray) {
StringBuffer sb = new StringBuffer(bArray.length);
String sTemp;
for (int i = 0; i < bArray.length; i++) {
sTemp = Integer.toHexString(0xFF & bArray[i]);
if (sTemp.length() == 1) {
sb.append(0);
}
sb.append(sTemp.toUpperCase());
sb.append(" ");
}
return sb.toString();
}
}
客户端:
package test.hhd.Socket;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import org.apache.commons.logging.Log;
public class SocketClient {
// 信道选择器
private Selector selector;
// 与服务器通信的信道
SocketChannel socketChannel;
// 要连接的服务器Ip地址
private String hostIp;
// 要连接的远程服务器在监听的端口
private int hostListenningPort;
String imei;
public SocketClient(String HostIp, int HostListenningPort, String imei) throws IOException {
this.hostIp = HostIp;
this.hostListenningPort = HostListenningPort;
this.imei = imei;
initialize();
}
/**
* 初始化
*
* @throws IOException
*/
private void initialize() throws IOException {
try {
// 获得一个Socket通道
SocketChannel channel = SocketChannel.open();
// 设置通道为非阻塞
channel.configureBlocking(false);
// 获得一个通道管理器
this.selector = Selector.open();
// 客户端连接服务器,其实方法执行并没有实现连接,需要在listen()方法中调
//用channel.finishConnect();才能完成连接
channel.connect(new InetSocketAddress(hostIp, hostListenningPort));
//将通道管理器和该通道绑定,并为该通道注册SelectionKey.OP_CONNECT事件。
channel.register(selector, SelectionKey.OP_CONNECT);
} catch (Exception e) {
e.printStackTrace();
}
// 启动读取线程
new ReadThread(selector, imei);
}
}
应用执行:
package test.hhd.Socket;
import java.io.IOException;
public class SocketApp {
/**
* @param args
*/
public static void main(String[] args) {
new Thread() {
@Override
public void run() {
try {
new SocketClient("127.0.0.1", 9000, "dddd");
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}.start();
}
}