package org.rx.socks;

import lombok.extern.slf4j.Slf4j;
import org.rx.core.LogWriter;
import org.rx.core.NQuery;
import org.rx.beans.DateTime; import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket; import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque; import static org.rx.core.Contract.require; @Slf4j
public final class SocketPool extends Traceable implements AutoCloseable {
public static final class PooledSocket implements AutoCloseable {
private final SocketPool owner;
private DateTime lastActive;
public final Socket socket; public boolean isConnected() {
return !owner.isClosed() && !socket.isClosed() && socket.isConnected();
} public DateTime getLastActive() {
return lastActive;
} public void setLastActive(DateTime lastActive) {
this.lastActive = lastActive;
} private PooledSocket(SocketPool owner, Socket socket) {
this.owner = owner;
this.socket = socket;
lastActive = DateTime.utcNow();
} @Override
public void close() {
owner.returnSocket(this);
}
} public static final SocketPool Pool = new SocketPool();
private static final int DefaultConnectTimeout = 30000;
private static final int DefaultMaxIdleMillis = 120000;
private static final int DefaultMaxSocketsCount = 64;
private final ConcurrentHashMap<InetSocketAddress, ConcurrentLinkedDeque<PooledSocket>> pool;
private volatile int connectTimeout;
private volatile int maxIdleMillis;
private volatile int maxSocketsCount;
private final Timer timer;
private volatile boolean isTimerRun; public int getConnectTimeout() {
return connectTimeout;
} public void setConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
} public int getMaxIdleMillis() {
return maxIdleMillis;
} public void setMaxIdleMillis(int maxIdleMillis) {
if (maxIdleMillis <= 0) {
maxIdleMillis = DefaultMaxIdleMillis;
}
this.maxIdleMillis = maxIdleMillis;
} public int getMaxSocketsCount() {
return maxSocketsCount;
} public void setMaxSocketsCount(int maxSocketsCount) {
if (maxSocketsCount < 0) {
maxSocketsCount = 0;
}
this.maxSocketsCount = maxSocketsCount;
} private SocketPool() {
pool = new ConcurrentHashMap<>();
connectTimeout = DefaultConnectTimeout;
maxIdleMillis = DefaultMaxIdleMillis;
maxSocketsCount = DefaultMaxSocketsCount;
String n = "SocketPool";
timer = new Timer(n, true);
LogWriter tracer = new LogWriter();
tracer.setPrefix(n + " ");
tracer.info("started..");
setTracer(tracer);
} @Override
protected void freeObjects() {
clear();
} private void runTimer() {
if (isTimerRun) {
return;
}
synchronized (timer) {
if (isTimerRun) {
return;
} long period = 90000;
timer.schedule(new TimerTask() {
@Override
public void run() {
clearIdleSockets();
}
}, period, period);
isTimerRun = true;
}
getTracer().info("runTimer..");
} private void clearIdleSockets() {
for (Map.Entry<InetSocketAddress, ConcurrentLinkedDeque<PooledSocket>> entry : NQuery.of(pool.entrySet())) {
ConcurrentLinkedDeque<PooledSocket> sockets = entry.getValue();
if (sockets == null) {
continue;
} for (PooledSocket socket : NQuery.of(sockets)) {
if (!socket.isConnected()
|| DateTime.utcNow().subtract(socket.getLastActive()).getTotalMilliseconds() >= maxIdleMillis) {
sockets.remove(socket);
getTracer().info("clear idle socket[local=%s, remote=%s]..",
Sockets.getId(socket.socket, false), Sockets.getId(socket.socket, true));
}
}
if (sockets.isEmpty()) {
pool.remove(entry.getKey());
}
}
if (pool.size() == 0) {
stopTimer();
}
} private void stopTimer() {
synchronized (timer) {
timer.cancel();
timer.purge();
isTimerRun = false;
}
getTracer().info("stopTimer..");
} private ConcurrentLinkedDeque<PooledSocket> getSockets(InetSocketAddress remoteAddr) {
ConcurrentLinkedDeque<PooledSocket> sockets = pool.get(remoteAddr);
if (sockets == null) {
pool.put(remoteAddr, sockets = new ConcurrentLinkedDeque<>());
runTimer();
}
return sockets;
} public PooledSocket borrowSocket(InetSocketAddress remoteAddr) {
checkNotClosed();
require(remoteAddr); boolean isExisted = true;
ConcurrentLinkedDeque<PooledSocket> sockets = getSockets(remoteAddr);
PooledSocket pooledSocket;
if ((pooledSocket = sockets.pollFirst()) == null) {
Socket sock = new Socket();
try {
sock.connect(remoteAddr, connectTimeout);
} catch (IOException ex) {
throw new SocketException(remoteAddr, ex);
}
pooledSocket = new PooledSocket(this, sock);
isExisted = false;
}
if (!pooledSocket.isConnected()) {
if (isExisted) {
sockets.remove(pooledSocket);
}
return borrowSocket(remoteAddr);
}
Socket sock = pooledSocket.socket;
getTracer().info("borrow %s socket[local=%s, remote=%s]..", isExisted ? "existed" : "new",
Sockets.getId(sock, false), Sockets.getId(sock, true));
return pooledSocket;
} public void returnSocket(PooledSocket pooledSocket) {
checkNotClosed();
require(pooledSocket); String action = "return";
try {
if (!pooledSocket.isConnected()) {
action = "discard closed";
return;
}
pooledSocket.setLastActive(DateTime.utcNow());
ConcurrentLinkedDeque<PooledSocket> sockets = getSockets(
(InetSocketAddress) pooledSocket.socket.getRemoteSocketAddress());
if (sockets.size() >= maxSocketsCount || sockets.contains(pooledSocket)) {
action = "discard contains";
return;
} sockets.addFirst(pooledSocket);
} finally {
Socket sock = pooledSocket.socket;
getTracer().info("%s socket[local=%s, remote=%s]..", action, Sockets.getId(sock, false),
Sockets.getId(sock, true));
}
} public void clear() {
checkNotClosed(); for (Socket socket : NQuery.of(pool.values()).selectMany(p -> p).select(p -> p.socket)) {
try {
getTracer().info("clear socket[local=%s, remote=%s]..", Sockets.getId(socket, false),
Sockets.getId(socket, true));
Sockets.close(socket);
} catch (Exception ex) {
log.error("SocketPool clear", ex);
}
}
pool.clear();
}
}
package org.rx.socks;

import org.rx.core.Disposable;
import org.rx.core.LogWriter; import static org.rx.core.Contract.isNull; public abstract class Traceable extends Disposable {
private LogWriter tracer; public LogWriter getTracer() {
return tracer;
} public synchronized void setTracer(LogWriter tracer) {
this.tracer = isNull(tracer, new LogWriter());
}
}
package org.rx.socks;

import lombok.extern.slf4j.Slf4j;
import org.rx.beans.$;
import org.rx.beans.Tuple;
import org.rx.util.BufferSegment;
import org.rx.util.BytesSegment;
import org.rx.core.*;
import org.rx.core.AsyncTask;
import org.rx.io.MemoryStream; import java.io.IOException;
import java.net.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import static org.rx.beans.$.$;
import static org.rx.core.Contract.isNull;
import static org.rx.core.Contract.require; @Slf4j
public class DirectSocket extends Traceable implements AutoCloseable {
@FunctionalInterface
public interface SocketSupplier {
Tuple<AutoCloseable, Socket> get(MemoryStream pack);
} private static class ClientItem {
private final DirectSocket owner;
private final BufferSegment segment;
public final NetworkStream stream;
public final AutoCloseable toSock;
public final NetworkStream toStream; public ClientItem(Socket client, DirectSocket owner) {
this.owner = owner;
segment = new BufferSegment(Contract.config.getDefaultBufferSize(), 2);
try {
stream = new NetworkStream(client, segment.alloc());
if (owner.directAddress != null) {
SocketPool.PooledSocket pooledSocket = App.retry(owner.connectRetryCount,
p -> SocketPool.Pool.borrowSocket(p.directAddress), owner);
toSock = pooledSocket;
toStream = new NetworkStream(pooledSocket.socket, segment.alloc(), false);
return;
}
if (owner.directSupplier != null) {
MemoryStream firstPack = new MemoryStream(32, true);
BytesSegment buffer = stream.getSegment();
int read;
while ((read = stream.readSegment()) > 0) {
System.out.println("----:" + Bytes.toString(buffer.array, buffer.offset, read));
firstPack.write(buffer.array, buffer.offset, read);
Tuple<AutoCloseable, Socket> toSocks;
if ((toSocks = owner.directSupplier.get(firstPack)) != null) {
toSock = toSocks.left;
firstPack.writeTo(toStream = new NetworkStream(toSocks.right, segment.alloc(), false));
return;
}
}
log.info("DirectSocket ClientState directSupplier read: {}\ncontent: {}", read,
Bytes.toString(firstPack.toArray(), 0, firstPack.getLength()));
}
} catch (IOException ex) {
throw new SocketException((InetSocketAddress) client.getLocalSocketAddress(), ex);
}
throw new SocketException((InetSocketAddress) client.getLocalSocketAddress(),
"DirectSocket directSupplier error");
} public void closeSocket() {
owner.getTracer().info("client close socket[%s->%s]..", Sockets.getId(stream.getSocket(), false),
Sockets.getId(stream.getSocket(), true));
owner.clients.remove(this);
stream.close();
} public void closeToSocket(boolean pooling) {
owner.getTracer().info("client %s socket[%s->%s]..", pooling ? "pooling" : "close",
Sockets.getId(toStream.getSocket(), false), Sockets.getId(toStream.getSocket(), true));
if (pooling) {
try {
toSock.close();
} catch (Exception ex) {
ex.printStackTrace();
}
} else {
Sockets.close(toStream.getSocket());
}
}
} public static final SocketSupplier HttpSupplier = pack -> {
String line = Bytes.readLine(pack.getBuffer());
if (line == null) {
return null;
}
InetSocketAddress authority;
try {
authority = Sockets.parseEndpoint(
new URL(line.split(" ")[1])
.getAuthority());
} catch (MalformedURLException ex) {
throw SystemException.wrap(ex);
}
SocketPool.PooledSocket pooledSocket = App.retry(2,
p -> SocketPool.Pool.borrowSocket(p),
authority);
return Tuple.of(pooledSocket, pooledSocket.socket);
};
private static final int DefaultBacklog = 128;
private static final int DefaultConnectRetryCount = 4;
private final ServerSocket server;
private final List<ClientItem> clients;
private volatile int connectRetryCount;
private InetSocketAddress directAddress;
private SocketSupplier directSupplier; @Override
public boolean isClosed() {
return !(!super.isClosed() && !server.isClosed());
} public InetSocketAddress getLocalAddress() {
return (InetSocketAddress) server.getLocalSocketAddress();
} public NQuery<Tuple<Socket, Socket>> getClients() {
return NQuery.of(clients).select(p -> Tuple.of(p.stream.getSocket(), p.toStream.getSocket()));
} public int getConnectRetryCount() {
return connectRetryCount;
} public void setConnectRetryCount(int connectRetryCount) {
if (connectRetryCount <= 0) {
connectRetryCount = 1;
}
this.connectRetryCount = connectRetryCount;
} public DirectSocket(int listenPort, InetSocketAddress directAddr) {
this(new InetSocketAddress(Sockets.AnyAddress, listenPort), directAddr, null);
} public DirectSocket(InetSocketAddress listenAddr, InetSocketAddress directAddr, SocketSupplier directSupplier) {
require(listenAddr);
require(this, directAddr != null || directSupplier != null); try {
server = new ServerSocket();
server.setReuseAddress(true);
server.bind(listenAddr, DefaultBacklog);
} catch (IOException ex) {
throw new SocketException(listenAddr, ex);
}
directAddress = directAddr;
this.directSupplier = directSupplier;
clients = Collections.synchronizedList(new ArrayList<>());
connectRetryCount = DefaultConnectRetryCount;
String taskName = String.format("DirectSocket[%s->%s]", listenAddr, isNull(directAddress, "autoAddress"));
LogWriter tracer = new LogWriter();
tracer.setPrefix(taskName + " ");
setTracer(tracer);
AsyncTask.TaskFactory.run(() -> {
getTracer().info("start..");
while (!isClosed()) {
try {
ClientItem client = new ClientItem(server.accept(), this);
clients.add(client);
onReceive(client, taskName);
} catch (IOException ex) {
log.error(taskName, ex);
}
}
close();
}, taskName);
} @Override
protected void freeObjects() {
try {
for (ClientItem client : NQuery.of(clients)) {
client.closeSocket();
}
clients.clear();
server.close();
} catch (IOException ex) {
log.error("DirectSocket close", ex);
}
getTracer().info("stop..");
} private void onReceive(ClientItem client, String taskName) {
AsyncTask.TaskFactory.run(() -> {
try {
int recv = client.stream.directTo(client.toStream, (p1, p2) -> {
getTracer().info("sent %s bytes from %s to %s..", p2,
Sockets.getId(client.stream.getSocket(), true),
Sockets.getId(client.toStream.getSocket(), false));
return true;
});
getTracer().info("socket[%s->%s] closing with %s", Sockets.getId(client.stream.getSocket(), false),
Sockets.getId(client.stream.getSocket(), true), recv);
} catch (SystemException ex) {
$<java.net.SocketException> out = $();
if (ex.tryGet(out, java.net.SocketException.class)) {
if (out.v.getMessage().contains("Socket closed")) {
//ignore
log.debug("DirectTo ignore socket closed");
return;
}
}
throw ex;
} finally {
client.closeSocket();
}
}, String.format("%s[networkStream]", taskName));
AsyncTask.TaskFactory.run(() -> {
int recv = NetworkStream.StreamEOF;
try {
recv = client.toStream.directTo(client.stream, (p1, p2) -> {
getTracer().info("recv %s bytes from %s to %s..", p2,
Sockets.getId(client.toStream.getSocket(), false),
Sockets.getId(client.stream.getSocket(), true));
return true;
});
getTracer().info("socket[%s->%s] closing with %s", Sockets.getId(client.toStream.getSocket(), false),
Sockets.getId(client.toStream.getSocket(), true), recv);
} catch (SystemException ex) {
$<java.net.SocketException> out = $();
if (ex.tryGet(out, java.net.SocketException.class)) {
if (out.v.getMessage().contains("Socket closed")) {
//ignore
log.debug("DirectTo ignore socket closed");
return;
}
}
throw ex;
} finally {
client.closeToSocket(recv == NetworkStream.CannotWrite);
}
}, String.format("%s[toNetworkStream]", taskName));
}
}
package org.rx.socks;

import lombok.extern.slf4j.Slf4j;
import org.rx.util.BytesSegment;
import org.rx.io.IOStream; import java.io.IOException;
import java.net.Socket; import static org.rx.core.Contract.require;
import static org.rx.socks.Sockets.shutdown; @Slf4j
public final class NetworkStream extends IOStream {
@FunctionalInterface
public interface DirectPredicate {
boolean test(BytesSegment buffer, int count);
} public static final int SocketEOF = 0;
public static final int StreamEOF = -1;
public static final int CannotWrite = -2;
private final boolean ownsSocket;
private final Socket socket;
private final BytesSegment segment; public boolean isConnected() {
return !isClosed() && !socket.isClosed() && socket.isConnected();
} @Override
public boolean canRead() {
return super.canRead() && checkSocket(socket, false);
} @Override
public boolean canWrite() {
return super.canWrite() && checkSocket(socket, true);
} private static boolean checkSocket(Socket sock, boolean isWrite) {
return !sock.isClosed() && sock.isConnected() && !(isWrite ? sock.isOutputShutdown() : sock.isInputShutdown());
} public Socket getSocket() {
return socket;
} public BytesSegment getSegment() {
return segment;
} public NetworkStream(Socket socket, BytesSegment segment) throws IOException {
this(socket, segment, true);
} public NetworkStream(Socket socket, BytesSegment segment, boolean ownsSocket) throws IOException {
super(socket.getInputStream(), socket.getOutputStream()); this.ownsSocket = ownsSocket;
this.socket = socket;
this.segment = segment;
} @Override
protected void freeObjects() {
try {
log.info("NetworkStream freeObjects ownsSocket={} socket[{}][closed={}]", ownsSocket,
Sockets.getId(socket, false), socket.isClosed());
if (ownsSocket) {
//super.freeObjects(); Ignore this!!
Sockets.close(socket, 1);
}
} finally {
segment.close();
}
} int readSegment() {
return read(segment.array, segment.offset, segment.count);
} void writeSegment(int count) {
write(segment.array, segment.offset, count);
} public int directTo(NetworkStream to, DirectPredicate onEach) {
checkNotClosed();
require(to); int recv = StreamEOF;
while (canRead() && (recv = read(segment.array, segment.offset, segment.count)) >= -1) {
if (recv <= 0) {
if (ownsSocket) {
log.debug("DirectTo read {} flag and shutdown send", recv);
shutdown(socket, 1);
}
break;
} if (!to.canWrite()) {
log.debug("DirectTo read {} bytes and can't write", recv);
recv = CannotWrite;
break;
}
to.write(segment.array, segment.offset, recv); if (onEach != null && !onEach.test(segment, recv)) {
recv = StreamEOF;
break;
}
}
if (to.canWrite()) {
to.flush();
}
return recv;
}
}
package org.rx.socks;

import org.rx.core.SystemException;

import java.net.InetSocketAddress;

public class SocketException extends SystemException {
private InetSocketAddress localAddress; public InetSocketAddress getLocalAddress() {
return localAddress;
} public SocketException(InetSocketAddress localAddress, Exception ex) {
super(ex);
this.localAddress = localAddress;
} public SocketException(InetSocketAddress localAddress, String msg) {
super(msg);
this.localAddress = localAddress;
}
}
package org.rx.socks;

import java.io.IOException;
import java.net.*; import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.ServerChannel;
import io.netty.channel.epoll.Epoll;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.epoll.EpollSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.rx.core.Strings;
import org.rx.core.SystemException;
import org.rx.core.WeakCache;
import org.springframework.util.CollectionUtils; import java.util.List;
import java.util.Properties;
import java.util.function.Function; import static org.rx.core.Contract.require;
import static org.rx.core.Contract.values; public final class Sockets {
public static final InetAddress LocalAddress, AnyAddress; static {
LocalAddress = InetAddress.getLoopbackAddress();
try {
AnyAddress = InetAddress.getByName("0.0.0.0");
} catch (Exception ex) {
throw SystemException.wrap(ex);
}
} public InetAddress[] getAddresses(String host) {
return (InetAddress[]) WeakCache.getOrStore("Sockets.getAddresses", values(host), p -> {
try {
return InetAddress.getAllByName(host);
} catch (UnknownHostException ex) {
throw SystemException.wrap(ex);
}
});
} public static InetSocketAddress getAnyEndpoint(int port) {
return new InetSocketAddress(AnyAddress, port);
} public static InetSocketAddress parseEndpoint(String endpoint) {
require(endpoint); String[] arr = Strings.split(endpoint, ":", 2);
return new InetSocketAddress(arr[0], Integer.parseInt(arr[1]));
} public static void writeAndFlush(Channel channel, Object... packs) {
require(channel); channel.eventLoop().execute(() -> {
for (Object pack : packs) {
channel.write(pack);
}
channel.flush();
});
} public static EventLoopGroup bossEventLoop() {
return eventLoopGroup(1);
} public static EventLoopGroup workEventLoop() {
return eventLoopGroup(0);
} public static EventLoopGroup eventLoopGroup(int threadAmount) {
return Epoll.isAvailable() ? new EpollEventLoopGroup(threadAmount) : new NioEventLoopGroup(threadAmount); //NioEventLoopGroup(0, TaskFactory.getExecutor());
} public static Bootstrap bootstrap() {
return bootstrap(getChannelClass());
} public static Bootstrap bootstrap(Class<? extends Channel> channelClass) {
require(channelClass); return new Bootstrap().group(channelClass.getName().startsWith("Epoll") ? new EpollEventLoopGroup() : new NioEventLoopGroup()).channel(channelClass);
} public static Bootstrap bootstrap(Channel channel) {
require(channel); return new Bootstrap().group(channel.eventLoop()).channel(channel.getClass());
} public static Class<? extends ServerChannel> getServerChannelClass() {
return Epoll.isAvailable() ? EpollServerSocketChannel.class : NioServerSocketChannel.class;
} public static Class<? extends Channel> getChannelClass() {
return Epoll.isAvailable() ? EpollSocketChannel.class : NioSocketChannel.class;
} public static void closeOnFlushed(Channel channel) {
require(channel); if (!channel.isActive()) {
return;
}
channel.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
} public static void close(Socket socket) {
close(socket, 1 | 2);
} public static void close(Socket socket, int flags) {
require(socket); if (!socket.isClosed()) {
shutdown(socket, flags);
try {
socket.setSoLinger(true, 2);
socket.close();
} catch (IOException ex) {
throw SystemException.wrap(ex);
}
}
} /**
* @param socket
* @param flags Send=1, Receive=2
*/
public static void shutdown(Socket socket, int flags) {
require(socket); if (!socket.isClosed() && socket.isConnected()) {
try {
if ((flags & 1) == 1 && !socket.isOutputShutdown()) {
socket.shutdownOutput();
}
if ((flags & 2) == 2 && !socket.isInputShutdown()) {
socket.shutdownInput();
}
} catch (IOException ex) {
throw SystemException.wrap(ex);
}
}
} public static String getId(Socket sock, boolean isRemote) {
require(sock); InetSocketAddress addr = (InetSocketAddress) (isRemote ? sock.getRemoteSocketAddress()
: sock.getLocalSocketAddress());
return addr.getHostString() + ":" + addr.getPort();
} public static <T> T httpProxyInvoke(String proxyAddr, Function<String, T> func) {
setHttpProxy(proxyAddr);
try {
return func.apply(proxyAddr);
} finally {
clearHttpProxy();
}
} public static void setHttpProxy(String proxyAddr) {
setHttpProxy(proxyAddr, null, null, null);
} public static void setHttpProxy(String proxyAddr, List<String> nonProxyHosts, String userName, String password) {
InetSocketAddress ipe = parseEndpoint(proxyAddr);
Properties prop = System.getProperties();
prop.setProperty("http.proxyHost", ipe.getAddress().getHostAddress());
prop.setProperty("http.proxyPort", String.valueOf(ipe.getPort()));
prop.setProperty("https.proxyHost", ipe.getAddress().getHostAddress());
prop.setProperty("https.proxyPort", String.valueOf(ipe.getPort()));
if (!CollectionUtils.isEmpty(nonProxyHosts)) {
//如"localhost|192.168.0.*"
prop.setProperty("http.nonProxyHosts", String.join("|", nonProxyHosts));
}
if (userName != null && password != null) {
Authenticator.setDefault(new UserAuthenticator(userName, password));
}
} public static void clearHttpProxy() {
System.clearProperty("http.proxyHost");
System.clearProperty("http.proxyPort");
System.clearProperty("https.proxyHost");
System.clearProperty("https.proxyPort");
System.clearProperty("http.nonProxyHosts");
} static class UserAuthenticator extends Authenticator {
private String userName;
private String password; public UserAuthenticator(String userName, String password) {
this.userName = userName;
this.password = password;
} protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(userName, password.toCharArray());
}
}
}

Java BIO socket的更多相关文章

  1. JAVA BIO与NIO、AIO的区别

    IO的方式通常分为几种,同步阻塞的BIO.同步非阻塞的NIO.异步非阻塞的AIO. 一.BIO 在JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个ServerSock ...

  2. java bio 之聊天室

    最近在复习java io相关知识 ,发现很多细节之前没学习到位,原理也没吃透,只能感叹本人愚钝. 复习到bio,顺手写了个简单的聊天室功能,并和大家分享下. 服务端: package io.QQ聊天室 ...

  3. Java BIO及实现

    发现日常学习过的知识不久就会遗忘,在此只是整理并记录一下学习笔记,做个回忆,并方便以后查阅,若有错误,欢迎指正 网络模型:TCP/IP网络模型是从OSI七层模型中演化来的,osi模型分为物理层,数据链 ...

  4. 3. 彤哥说netty系列之Java BIO NIO AIO进化史

    你好,我是彤哥,本篇是netty系列的第三篇. 欢迎来我的公从号彤哥读源码系统地学习源码&架构的知识. 简介 上一章我们介绍了IO的五种模型,实际上Java只支持其中的三种,即BIO/NIO/ ...

  5. [转帖]JAVA BIO与NIO、AIO的区别(这个容易理解)

    JAVA BIO与NIO.AIO的区别(这个容易理解) https://blog.csdn.net/ty497122758/article/details/78979302 2018-01-05 11 ...

  6. Java BIO NIO 与 AIO

    回顾 上一章我们介绍了操作系统层面的 IO 模型. 阻塞 IO 模型. 非阻塞 IO 模型. IO 复用模型. 信号驱动 IO 模型(用的不多,知道个概念就行). 异步 IO 模型. 并且介绍了 IO ...

  7. 【转】JAVA BIO与NIO、AIO的区别

    Java中IO的模型分为三种,同步阻塞的BIO.同步非阻塞的NIO.异步非阻塞的AIO. BIO[同步阻塞] 在JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个Ser ...

  8. Java BIO、NIO与AIO的介绍(学习过程)

    Java BIO.NIO与AIO的介绍 因为netty是一个NIO的框架,所以在学习netty的过程中,开始之前.针对于BIO,NIO,AIO进行一个完整的学习. 学习资源分享: Netty学习:ht ...

  9. Netty之JAVA BIO模型

    一.JAVA BIO模型 1.I/O模型 I/O 模型简单的理解:就是用什么样的通道进行数据的发送和接收,很大程度上决定了程序通信的性能 Java 共支持 3 种网络编程模型/IO 模式:BIO.NI ...

随机推荐

  1. (66) c# async await

    1.使用 async await 2.返回值 static void Main(string[] args) { Program p = new Program(); Console.WriteLin ...

  2. jmeter添加自定义扩展函数之Strng---base64解密

    1,打开eclipse,新建maven工程,在pom中引用jmeter核心jar包,具体请看---https://www.cnblogs.com/guanyf/p/10863033.html---,这 ...

  3. Linux ftp安装

    ftp安装部分,操作步骤如下: 可以使用yum命令直接安装ftp # yum install vsftpd ftp服务的开启与关闭命令: 开启:# /bin/systemctl start vsftp ...

  4. day 84 Xadmin组件之构建表单数据

    一 .先设置一些相关配置 1. 创建数据库模型. 在app01 下创建 from django.db import models # Create your models here. class Au ...

  5. Java导入

    导入(import)声明用于将任何类型导入编译单元.导入(import)声明出现在包声明之后,第一个类型声明之前. 有两种类型的导入声明: 单类型导入声明 按需导入声明 单类型导入声明 单类型导入声明 ...

  6. Eclipse插件pydev编辑.py文件时报错:unresolved import error.解决办法

    在同一个包中import还报unresolved import error.感觉很奇怪,原来需要把当前的包也要添加到System libs中  

  7. 详解 CSS 绝对定位

    基本定义和用法 在 CSS 中,position 属性指定一个元素(静态的,相对的,绝对或固定,以及粘性定位)的定位方法的类型. 当设置 position 属性的值为 absolute 时,生成绝对定 ...

  8. C#获取文件夹/文件的大小以及占用空间 转摘自:http://www.cnblogs.com/chenpeng-dota/articles/2176470.html

    C#获取文件夹/文件的大小以及占用空间 今天,头给了个任务:写个方法,我会给你个路径,计算这个路径所占用的磁盘空间 . 然后,找了很多资料.但大部分都是获取文件夹/文件的大小的.对于占用空间的没有成品 ...

  9. 波兰语 polish

    There are several systems for encoding the Polish alphabet for computers. All letters of the Polish ...

  10. day01 html介绍 文档声明头 head标签 body标签

    day01 html   初识html <!--文档的声明--> <!doctype html>   <html lang="en">    # ...