Java网络编程——使用NIO实现非阻塞Socket通信
https://blog.csdn.net/yanmei_yao/article/details/8586199
JavaSocket学习—NIO实现非阻塞的通信
https://blog.csdn.net/henushang/article/details/84653615
Java Socket(六) 使用多线程实现多客户端的通信
https://blog.csdn.net/u013007900/article/details/50411649
Socket 多线程客户端与服务端(借鉴了他人)
https://blog.csdn.net/m0_38089615/article/details/80444794
java socket通信I/O阻塞>多线程实现非阻塞通信
https://blog.csdn.net/heroboyluck/article/details/78416782
示例代码见附件:很遗憾,太懒,代码内容还是我分的包,如果你要运行的话,还需要自己下一点小的功夫,改变一下包路径。
Server端代码:
-
package com.henushang.socket.chapter4nio;
-
import java.io.IOException;
-
import java.net.InetSocketAddress;
-
import java.nio.ByteBuffer;
-
import java.nio.CharBuffer;
-
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;
-
import java.util.Set;
-
public class EchoServerNoBlock {
-
private int port = 8000;
-
private ServerSocketChannel serverSocketChannel;
-
Selector selector;
-
public EchoServerNoBlock() throws Exception {
-
selector = Selector.open();
-
serverSocketChannel = ServerSocketChannel.open();
-
serverSocketChannel.socket().setReuseAddress(true);
-
serverSocketChannel.configureBlocking(false);// 设置通信为非阻塞模式,没有这一配置,则无法实现非阻塞
-
serverSocketChannel.socket().bind(new InetSocketAddress(port));
-
System.out.println(“等待连接…”);
-
}
-
public void service() throws Exception {
-
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
-
while (selector.select() > 0) {
-
Set<SelectionKey> readyKeys = selector.selectedKeys();
-
Iterator<SelectionKey> iterator = readyKeys.iterator();
-
SelectionKey key = null;
-
while (iterator.hasNext()) {
-
try {
-
key = iterator.next();
-
iterator.remove();
-
if (key.isAcceptable()) {
-
System.out.println(“accept”);
-
ServerSocketChannel ssc = (ServerSocketChannel) key
-
.channel();
-
SocketChannel sc = ssc.accept();
-
System.out.println(“接收到链接”
-
+ sc.socket().getInetAddress() + “:”
-
+ sc.socket().getPort());
-
sc.configureBlocking(false);
-
ByteBuffer buffer = ByteBuffer.allocate(1024);
-
sc.register(selector, SelectionKey.OP_READ
-
| SelectionKey.OP_WRITE, buffer);
-
}
-
if (key.isReadable()) {
-
System.out.println(“read”);
-
receive(key);
-
}
-
if (key.isWritable()) {
-
send(key);
-
}
-
} catch (Exception e) {
-
e.printStackTrace();
-
if (key != null) {
-
key.cancel();
-
key.channel().close();
-
}
-
}
-
}
-
}
-
}
-
/**
-
* 发送消息处理方法
-
* @param key
-
* @throws Exception
-
* @author henushang
-
*/
-
public void send(SelectionKey key) throws Exception {
-
ByteBuffer buffer = (ByteBuffer) key.attachment();
-
SocketChannel socketChannel = (SocketChannel) key.channel();
-
buffer.flip();
-
String data = decode(buffer);
-
if (data.indexOf(“\r\n”) == -1) {
-
return;
-
}
-
String outputData = data.substring(0, data.indexOf(“\n”) + 1);
-
System.out.println(outputData);
-
ByteBuffer outputBuffer = encode(“henushang:” + outputData);
-
while (outputBuffer.hasRemaining()) {
-
socketChannel.write(outputBuffer);
-
}
-
ByteBuffer temp = encode(outputData);
-
buffer.position(temp.limit());
-
buffer.compact();
-
if (outputData.equals(“byt\r\n”)) {
-
key.cancel();
-
socketChannel.close();
-
System.out.println(“关闭连接”);
-
}
-
}
-
/**
-
* 接受链接处理方法
-
* @param key
-
* @throws IOException
-
* @author henushang
-
*/
-
public void receive(SelectionKey key) throws IOException {
-
SocketChannel sc = (SocketChannel) key.channel();
-
ByteBuffer buffer = (ByteBuffer) key.attachment();
-
ByteBuffer readBuffer = ByteBuffer.allocate(32);
-
sc.read(readBuffer);
-
readBuffer.flip();
-
buffer.limit(readBuffer.capacity());
-
buffer.put(readBuffer);
-
}
-
static Charset charset = Charset.forName(“UTF-8″);
-
/**
-
* 解码
-
* @param byteBuffer
-
* @return
-
* @author henushang
-
*/
-
public static String decode(ByteBuffer byteBuffer) {
-
CharBuffer charBuffer = charset.decode(byteBuffer);
-
return charBuffer.toString();
-
}
-
/**
-
* 编码
-
* @param msg
-
* @return
-
* @author henushang
-
*/
-
public static ByteBuffer encode(String msg) {
-
return charset.encode(msg);
-
}
-
}
客户端代码:
-
package com.henushang.socket.chapter4nio;
-
import java.io.BufferedReader;
-
import java.io.IOException;
-
import java.io.InputStreamReader;
-
import java.io.PrintWriter;
-
import java.net.InetAddress;
-
import java.net.InetSocketAddress;
-
import java.nio.channels.SocketChannel;
-
import com.henushang.socket.util.SocketUtils;
-
public class EchoClient {
-
private SocketChannel socketChannel;
-
private int port = 8000;
-
public EchoClient() throws Exception {
-
socketChannel = SocketChannel.open();
-
InetAddress inetAddress = InetAddress.getLocalHost();
-
InetSocketAddress inetSocketAddress = new InetSocketAddress(inetAddress, port);
-
socketChannel.connect(inetSocketAddress);
-
System.out.println(“准备连接服务器”);
-
}
-
public static void main(String[] args) throws Exception {
-
new EchoClient().talk();
-
}
-
public void talk() {
-
try {
-
BufferedReader reader = SocketUtils.getReader(socketChannel.socket());
-
PrintWriter pw = SocketUtils.getWriter(socketChannel.socket());
-
BufferedReader localreaderReader = new BufferedReader(new InputStreamReader(System.in));
-
String msg = null;
-
while ((msg = localreaderReader.readLine()) != null) {
-
System.out.println(msg);
-
pw.println(msg);
-
pw.flush();
-
System.out.println(reader.readLine());
-
if (“bye”.equals(msg)) {
-
break;
-
}
-
}
-
} catch (IOException e) {
-
e.printStackTrace();
-
}finally{
-
SocketUtils.close(socketChannel);
-
}
-
}
-
}
工具类代码:
-
package com.henushang.socket.util;
-
import java.io.BufferedReader;
-
import java.io.IOException;
-
import java.io.InputStream;
-
import java.io.InputStreamReader;
-
import java.io.OutputStream;
-
import java.io.PrintWriter;
-
import java.net.Socket;
-
import java.nio.channels.SocketChannel;
-
public class SocketUtils {
-
public static PrintWriter getWriter(Socket socket) throws IOException {
-
OutputStream os = socket.getOutputStream();
-
return new PrintWriter(os);
-
}
-
public static PrintWriter getWriter(SocketChannel socketChannel) throws IOException {
-
return getWriter(socketChannel.socket());
-
}
-
public static BufferedReader getReader(Socket socket) throws IOException{
-
InputStream is = socket.getInputStream();
-
return new BufferedReader(new InputStreamReader(is, “UTF-8″));
-
}
-
public static BufferedReader getReader(SocketChannel socketChannel) throws IOException{
-
return getReader(socketChannel.socket());
-
}
-
public static void close(Socket socket) {
-
try {
-
if (socket != null) {
-
socket.close();
-
}
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
public static void close(SocketChannel socketChannel) {
-
try {
-
if (socketChannel != null) {
-
socketChannel.close();
-
}
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
public static String echo(String msg) {
-
return “echo:” + msg;
-
}
-
}
这种方式是一个线程在不停的循环检测监听到的事件,然后分别作出相应的处理。可是这种方式只适合那种处理过程时间短的情况,如果某一个操作处理的事件太长的话,则会让其他的事件一直处于等待状态,比如发送或者接收一个很大的文件,这样显然是很不合适的。
使用NIO的NoBlocking的操作方式固然减少了系统使用多线程建立连接的开销,但是也并不是完全适合任何情况的。
所以,在几种方式中没有最好的,只有最合适的。
而做程序也是一样的,没有那个语言是最好的,只有最合适的语言。