Socekt(TCP)服务端传输http协议之NIO非阻塞
作为TCP服务端有三种写法,一是通过阻塞写法直接实例化socket;二是通过NIO非阻塞法实现;三是通过netty来实现(一般用于高并发这快)。我这边使用的是使用NIO非阻塞法实现。
需求:客户端通过socket发送http协议来传输数据,同时也会出现客户端分批发送数据(如以http协议Post形式发送数据,第一次发送请求头,第二次发送实体)如客户端这样发送数据。
解决:可以把发送过来的http协议作为一次平常发送过来的字符串进行处理。
TCP服务端代码:
public class NIOServer {
private InetAddress addr;
private int port;
private Selector selector;
private static int BUFF_SIZE = 1024*1024;
private static ConcurrentHashMap<String,SelectionKey> keyPool=new ConcurrentHashMap<>();
public NIOServer() {
}
public NIOServer(InetAddress addr, int port) {
try{
this.addr = addr;
this.port = port;
startServer();
} catch (Exception e){
log.info("启动失败");
}
}
private void startServer() throws IOException {
this.selector = Selector.open();
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
InetSocketAddress listenAddr = new InetSocketAddress(this.addr, this.port);
serverChannel.socket().bind(listenAddr);
serverChannel.register(this.selector, SelectionKey.OP_ACCEPT);
log.info("NIOServer运行中...");
while (true) {
log.info("服务器等待新的连接和selector选择…");
this.selector.select();
Iterator keys = this.selector.selectedKeys().iterator();
while (keys.hasNext()) {
SelectionKey key = (SelectionKey) keys.next();
keys.remove();
if (!key.isValid()) {
continue;
}
if (key.isAcceptable()) {
this.accept(key);
} else if (key.isReadable()) {
this.read(key);
} else if (key.isWritable()) {
this.write(key);
} else if (key.isConnectable()) {
this.connect(key);
}
}
}
}
private void connect(SelectionKey key) throws IOException {
SocketChannel channel = (SocketChannel) key.channel();
if (channel.finishConnect()) {
log.info("成功连接了");
} else {
keyPool.remove(channel.socket().getRemoteSocketAddress()+"");
log.info("失败连接");
}
}
private void accept(SelectionKey key) throws IOException {
ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
SocketChannel channel = serverChannel.accept();
channel.configureBlocking(false);
channel.register(this.selector, SelectionKey.OP_READ);
SocketAddress remoteAddr = channel.socket().getRemoteSocketAddress();
keyPool.put(remoteAddr+"",key);
log.info("连接到: "+remoteAddr);
}
private void read(SelectionKey key) throws IOException {
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(BUFF_SIZE);
int numRead = channel.read(buffer);
if (numRead == -1) {
log.info("关闭客户端连接: "+channel.socket().getRemoteSocketAddress());
keyPool.remove(channel.socket().getRemoteSocketAddress()+"");
channel.close();
return;
}
String msg = new String(buffer.array()).trim();
log.info("客户端发送的数据: "+msg);
String reMsg= "";
log.info("要返回的数据: "+reMsg);
channel.write(ByteBuffer.wrap(reMsg.getBytes()));
}
private void write(SelectionKey key) throws IOException {
ByteBuffer byteBuffer = ByteBuffer.allocate(BUFF_SIZE);
byteBuffer.flip();
SocketChannel clientChannel = (SocketChannel) key.channel();
while (byteBuffer.hasRemaining()) {
clientChannel.write(byteBuffer);
}
byteBuffer.compact();
}
}
至此解决完成。
|