您的位置:首页 > 编程语言 > Java开发

java nio socket通信简单入门示例

2015-11-22 12:11 429 查看
      

      基本的Java套接字对于小规模系统可以很好地运行,但当涉及到要同时处理上千个客户端的服务器时,可能就会产生一些问题.由于创建、维护和切换线程需要的系统开销,一客户一线程方式在系统扩展性方面受到了限制。使用线程池可以节省那种系统开销,同时允许实现者利用并行硬件的优势。但对于连接生存期比较长的协议来说,线程池的大小仍然限制了系统可以同时处理的客户端数量。考虑一个在客户端之间传递消息的即时消息服务器(Instant
Messaging)。客户端必须不停地连接服务器以接收即时消息,因此线程池的大小限制了系统可以同时服务的客户端总数。如果增加线程池的大小,将带来更多的线程处理开销,而不能提升系统的性能,因为在大部分的时间里客户端是处于闲置状态的。

      如果这就是所有问题,可能NIO还不是必要的。不幸的是,在使用线程的扩展性方面还涉及一些更加难以把握的挑战。其中一个挑战就是程序员几乎不能对什么时候哪个线程将获得服务进行控制。你可以设置一个线程实例的优先级(priority)(高优先级的线程相对于低优先级的线程有优先权),但是这个优先级只是一种"建议"--下一个选择执行的线程完全取决于具体实现。因此,如果程序员想要保证某些连接优先获得服务,或想要指定一定的服务顺序,线程可能就很难做到。

    我们需要一种方法来一次轮询一组客户端,以查找哪个客户端需要服务。这正是NIO中将要介绍的Selector和Channel抽象的关键点。一个Channel实例代表了一个"可轮询的(pollable)"I/O目标,如套接字(或一个文件、设备等)。Channel能够注册一个Selector类的实例。Selector的select()方法允许你询问"在一组信道中,哪一个当前需要服务(即,被接受,读或写)?"大量的细节将在后文中介绍,但这就是使用Selector和Channel的基本动机。这两个类都包含在java.nio.channels包中。

摘自《java tcp/ip socket编程》

下面自己实现了一个单线程的通信。

server:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

/*
* Server
*/
public class NioTcpServer1
{
public static void main(String[] args) throws Exception
{
//open ServerSocketChannel
ServerSocketChannel server = ServerSocketChannel.open();
// bind port
server.bind(new InetSocketAddress(10000));
//set noblocking
server.configureBlocking(false);
//open selector
Selector selector = Selector.open();
//register accept event
server.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("=======server start=======");
while (true)
{
while (selector.select() > 0)
{
Iterator<SelectionKey> iter = selector.selectedKeys()
.iterator();
while (iter.hasNext())
{
SelectionKey key = iter.next();
//avoid duplication
iter.remove();
//accept
if (key.isAcceptable())
{
SocketChannel channel = ((ServerSocketChannel) (key
.channel())).accept();
channel.configureBlocking(false);
//register read and write
channel.register(selector, SelectionKey.OP_READ
| SelectionKey.OP_WRITE);
System.out.println("server accept client");
channel.write(ByteBuffer.wrap("server already \r\n".getBytes()));
}
//read
if (key.isReadable())
{

SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(20);
int len = 0;
while (0 != (len = channel.read(buffer)))
{

System.out.println(new String(buffer.array(), 0,
len));
buffer.clear();
}
}
//write
if (key.isWritable())
{
System.out.print("server#: ");
BufferedReader read = new BufferedReader(
new InputStreamReader(System.in));

String line = read.readLine();

SocketChannel channel = (SocketChannel) key.channel();
//send some data
channel.write(ByteBuffer.wrap((line + "\r\n").getBytes()));
}
//set network delay
Thread.sleep(2000);
}
}
}

}
}


client:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
/*
* Client
*/
public class NioTcpClient1
{
public static void main(String[] args)throws Exception
{
//get socketchannel
SocketChannel client = SocketChannel.open();
//set no blocking
client.configureBlocking(false);
//connect to remote address
client.connect(new InetSocketAddress("localhost", 10000));
//open selector
Selector selector = Selector.open();
//register connection event
client.register(selector, SelectionKey.OP_CONNECT);

System.out.println("=====client start====");

while(true)
{
if(selector.select()>0)
{
Iterator<SelectionKey> iter = selector.selectedKeys().iterator();

while(iter.hasNext())
{
SelectionKey key = iter.next();
//avoid duplication
iter.remove();
//obtain current channel
SocketChannel channel = (SocketChannel) key.channel();
//connect
if(key.isConnectable())
{
//register read and write
channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
//finish connect
channel.finishConnect();
System.out.println("client connection server");
channel.write(ByteBuffer.wrap("client prepare \r\n".getBytes()));
}
//read
if(key.isReadable())
{
ByteBuffer buffer = ByteBuffer.allocate(20);
int len = -1;
while(0 != (len = channel.read(buffer)))
{
System.out.println(new String(buffer.array(), 0, len));
buffer.clear();
}
}
//write
if(key.isWritable())
{
System.out.print("client#: ");
BufferedReader read = new BufferedReader(
new InputStreamReader(System.in));

String line = read.readLine();
//send some data
channel.write(ByteBuffer.wrap((line + "\r\n").getBytes()));
}
//set network delay
Thread.sleep(2000);
}

}

}

}
}


效果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: