Mina代码跟踪(1)
1 NioSocketAcceptor类关系图
1.1 NioSocketAcceptor acceptor = new NioSocketAcceptor(5);
NioSocketAcceptor 初始化顺序
AbstractIoService构造函数
protected AbstractIoService(IoSessionConfig sessionConfig, Executor executor) {
if (sessionConfig == null) {
throw new IllegalArgumentException("sessionConfig");
} if (getTransportMetadata() == null) {
throw new IllegalArgumentException("TransportMetadata");
} if (!getTransportMetadata().getSessionConfigType().isAssignableFrom(
sessionConfig.getClass())) {
throw new IllegalArgumentException("sessionConfig type: "
+ sessionConfig.getClass() + " (expected: "
+ getTransportMetadata().getSessionConfigType() + ")");
} // Create the listeners, and add a first listener : a activation listener
// for this service, which will give information on the service state.
listeners = new IoServiceListenerSupport(this);
listeners.add(serviceActivationListener); // Stores the given session configuration
this.sessionConfig = sessionConfig; // Make JVM load the exception monitor before some transports
// change the thread context class loader.
ExceptionMonitor.getInstance(); if (executor == null) {
this.executor = Executors.newCachedThreadPool();
createdExecutor = true;
} else {
this.executor = executor;
createdExecutor = false;
} threadName = getClass().getSimpleName() + '-' + id.incrementAndGet();
}
protected AbstractIoAcceptor(IoSessionConfig sessionConfig, Executor executor) {
super(sessionConfig, executor);
defaultLocalAddresses.add(null);
}
AbstractPollingIoAcceptor 构造函数
private AbstractPollingIoAcceptor(IoSessionConfig sessionConfig,
Executor executor, IoProcessor<S> processor,
boolean createdProcessor) {
super(sessionConfig, executor); if (processor == null) {
throw new IllegalArgumentException("processor");
} this.processor = processor;
this.createdProcessor = createdProcessor; try {
// Initialize the selector
init(); // The selector is now ready, we can switch the
// flag to true so that incoming connection can be accepted
selectable = true;
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeIoException("Failed to initialize.", e);
} finally {
if (!selectable) {
try {
destroy();
} catch (Exception e) {
ExceptionMonitor.getInstance().exceptionCaught(e);
}
}
}
}
NioSocketAcceptor 构造函数
public NioSocketAcceptor(int processorCount) {
super(new DefaultSocketSessionConfig(), NioProcessor.class, processorCount);
((DefaultSocketSessionConfig) getSessionConfig()).init(this);
}
1.2 IoFilterChain 过滤链
aaarticlea/png;base64,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" alt="" />
acceptor.getFilterChain().addLast("logger", new LoggingFilter());
/** AbstractIoService
* {@inheritDoc}
*/
public final DefaultIoFilterChainBuilder getFilterChain() {
if (filterChainBuilder instanceof DefaultIoFilterChainBuilder) {
return (DefaultIoFilterChainBuilder) filterChainBuilder;
} throw new IllegalStateException(
"Current filter chain builder is not a DefaultIoFilterChainBuilder.");
}
源代码:
public class DefaultIoFilterChainBuilder implements IoFilterChainBuilder { private final static Logger LOGGER =
LoggerFactory.getLogger(DefaultIoFilterChainBuilder.class);
private final List<Entry> entries; /**
* Creates a new instance with an empty filter list.
*/
public DefaultIoFilterChainBuilder() {
entries = new CopyOnWriteArrayList<Entry>();
} /**
* Creates a new copy of the specified {@link DefaultIoFilterChainBuilder}.
*/
public DefaultIoFilterChainBuilder(DefaultIoFilterChainBuilder filterChain) {
if (filterChain == null) {
throw new IllegalArgumentException("filterChain");
}
entries = new CopyOnWriteArrayList<Entry>(filterChain.entries);
}
addLast
/**
* @see IoFilterChain#addLast(String, IoFilter)
*/
public synchronized void addLast(String name, IoFilter filter) {
register(entries.size(), new EntryImpl(name, filter));
}
private void register(int index, Entry e) {
if (contains(e.getName())) {
throw new IllegalArgumentException(
"Other filter is using the same name: " + e.getName());
} entries.add(index, e);
}
1.3 IoFilter
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAg8AAAFmCAIAAABlVO76AAAVpklEQVR4nO3d25GiTBgGYOKZEAxhArEmjK0yASOYMKyauz8Pg/G/8IQINoj0gX6e4mL3G0fRPrw0wm5zAoCQJvUOAFAAaQFAmLQAIOySFv/991/vj9XV1dXV1U/WFgCMIS0ACJMWAIRJCwDCpAUAYdICgDBpAUCY+y3U1dXV1cN1awsAwqQFAGHSAoAwaQFAmLQAIExaABAmLQAIc7+Furq6unq4bm0BQJi0ACBMWgAQJi0ACJMWAIRJCwDCpAUAYe63UFdXV1cP160tAAiTFgCESQsAwqQFAGHSAoAwaQFAmLQAIMz9Furq6urq4bq1BQBh0gKAMGkBQJi0ACBMWgAQJi0ACJMWAIS530JdXV1dPVy3tgAgTFoAECYtAAiTFlX41zS2SVvqFoPsGBVV+Nc0p9OfbeQmLeCZUVEFaSEtYCajogrSQlrATO63qKIuLd5Li9zaUV09Yd0xVBWkxXtpAdwYFVWQFtICZjIqqpB7Whx/Nk3TNM1m/5t+Z6QF9DEqqvDptNhtm6/98b2fPm+/+02zPaQPCWkBLxgVVZiQFofvZrub/KNZaTH18YPbYTuYOi9+JC1gDKOiCqPS4nw6qDcPuj+6ze+7bfO133839/NIv/vzSaWmaZrvw+XBF9f5erdtvvaH89mnr83D4+8Pbj3+4Umuu/H8tJdU6FTG/EhaQJBRUYVAWpzDYPNzHPujdlpcp+/jz+YeD7e1wu9+c/024uEB7eccWFvcH/+739xC4ne//Tn2P+3HMkNawDPXlVdRf5EWh+1ATrz60ePa4jhcfJjKb99PdOLh+a83X/vj+Uke46T/aT/y1h7SIrd2VFdPWHcMVYXA2uLw3TrDM+ZHo9Pi8N08CqXFbnu/MupaP3w3ndVD/9NaW8CCjIoqjPreYkJmTEqL7mmiV2nx8Phr/flcU//TfiAnpAUMMSqq8OlrooJpcZuUW18wnP6O+++n3/p7OnPVTo7zn19+b3F/WtdEwYKMiiosdr9Fb1r8HfdfvddEXb8qePW9xfV3m2b73TlDNXRN1ItvIN7bpAU8Myqq8Om0WPkmLeCZUVEFaSEtYCajogrSQlrATK4rr6IuLd5Li9zaUV09Yd0xVBWkxXtpAdwYFVWQFtICZjIqqpBbWpxvlGu2u+td2f232kkLyIdRUYVl0qL9z82+uk36fgvF9faIfU9aXJ4th/8QSVrAM6OiCguuLUYsDh5v1hv6dWkBWTMqqhAvLa7/Z2rTNE3/rd2Pv3X9w76z/ni+D/zhv8e4/PWwXeQslrSAZ0ZFFSKlxSUq2hP91/44Ki361hbnZ2j9Fxf3f8K2aZpmsxleskgL+DTXlVdRj5MW9++uT3+n6183+9/O9xab/e+YtLj81vXZWn+9psVi56z+ud9CXd39FnVKmBbNdvfe2uLQPgl1Pxu1a5+JWjotgBujogpx0qKzGnhaW0xLi86ztTZpAQkYFVWIkxbzvrfoLk2uz9b6t80P35v9r7SAJIyKKiyTFn33W7x7TdTTFVAPX27fSAtIxaiowoJrizVu0gKeGRVVkBbSAmYyKqogLaQFzOS68irq0uK9tMitHdXVE9YdQ1VBWryXFsCNUVEFaSEtYCajogrSQlrATEZFFaSFtICZjIoq/Gsa26QtdYtBdoyKKlhbWFvATEZFFaSFtICZXFdeRV1avJcWubWjunrCumOoKkiL99ICuDEqqiAtpAXMZFRUQVpIC5jJqKiCtJAWMJNRUQVpIS1gJqOiCslvdituS91ikB2jogrWFtYWMJPryquoS4v30iK3dlRXT1h3DFUFafFeWgA3RkUVpIW0gJmMiipIC2kBMxkVVZAW0gJmMiqqIC2kBcxkVFRBWkgLmMmoqIK0kBYwk+vKq6gnvzW6uC3PdlRXT1h3DEUajt+hLEYsaUgLKIsRSwLnqBAYUBDDlQSkBRTHcCW2W0hICyiI4Ups7ZAQGFAKY5WoOvEgLaAUritXj1p/nRb57Ke6urr7LUimdyVheQFFMFCJR1pAuQxUIhlKBWkBRTBQieRFKggMyJ9RSgyv80BaQP6MUmII5oHAgMwZoixuTBJIC8ic+y3UF6+PT4s8919dXf1kbcHSxi8aLC8gZ8Yny5IWsA7GJwuaFADSAnJmfLKg4H98/fz4yHsIjGRwksDUFAGSMzhJQCpAcQxaAMLcb6GeoD4kt/1UV1e/sbYAIExakIDvLaA4Bi0JSAsojkFLAtICimPQAhAmLQAIkxYAhLnfQj12/V/TZLU/6urqY+rWFsTmK24okXFLbNICSmTcAhAmLQAIkxYAhEkLYvO9BZTIuCU2aQElcr9F8fUX/2upbeaWQ/uqq2dSd5RXvH9Nczr92T6+WQNBm/FQPGkhLSAC46F40kJaQATGQ/GkhbSACIyH4kkLaQERGA/FkxbSAiIwHoq3RFoctk3TNM12dzp8N03TNN+HSHP0bts0TfO1P0oLyIv7LYqvD6fF737TtG0P/dPicf/18LjNz74nLS7Pttn/zg2h8zN/Pi0+sIedtMihfdXVM6k7eipeYG0xYnFwTYu+x3wyLXa3sBjOg7zSInXbQkaMh+JNS4vjz+Zpyu5Ji9tvXf+w76w/Lg9uB8Bt7XIpbg/nxcTlaS+vsv3pmdMvr9LZsYcnv0fI5S18bx9XKt0V0vQ9lBbwgvFQvAlpcZ1nW9Po1/44Ki361hbnZzj/1uWn28N9Lt5s2k97n6AHAqy7V6fTbrv5OQ6+i4fX2h561xaT9lBawCvGQ/HGp8X9u+vT3+n6183+t3NUvtn/jkmL61ph9/TX61zcs3p4So7uXg2diWrVH9Kl/evz9lBawEvGQ/FmpkWz3b23tjg8nie6aM3FrS/Vu9+3X3Pp59gKrZ606D1DNTotpuyhtIAA46F449Oic6z9tLaYlhadZ3taB7Tm4sv83loxXJ72a38cTIvL819ORgXWFpv9b3Bt8WoPpQWEGA/FG58W87636C5NejNgs/99nosvv3j7EqK92rhdpHv+aes5H16u/Vrtd/G4D2/vobSAIPdbFF8fTou++y3evSbq6fqih6+Ob/rm4v4vCdovej9ltPlqze+tl2vXH95CZ9J/bw8H0yKH9lVXz6Tu6Kl4w2mx0u3xTNRym7UFtBkPxZMW0gIiMB6KJy2kBURgPBSvurSItUkLaDMeiictpAVEYDwUT1pIC4jAeCietJAWEIH7LYqvS4vl0iKH9lVXz6Tu6Kl4/5rGttCWum0hI8ZD8awtlltbpG5byIjxUDxpIS0gAuOheNJCWkAExkPxpIW0gAiMh+JJC2kBERgPxZMW0gIicL9F8XVpsVxa5NC+6uqZ1B09FU9aLJcWqdsWMmI8FC/5LWwr3lK3LWTEeCietYW1BURgPBRPWkgLiMB4KJ60kBYQgfFQPGkhLSAC46F40kJaQATutyi+Li2WS4sc2lddPZO6o6fiSYvl0iJ120JGjIfiSQtpAREYD8WTFtICIjAeipf8hucVb6nbFjJiPDBo6Rkz2nQsBmA+w4YHMWfVmBN354UsKWAqA4PTqTV7dooRXnTRl+i83PhHyg/ocL9F1fUXs2Fv8YP7c3v+9gst+n7fm/SX/hzU1UupO2iqzshD5ggLizgv1Puii/4KrJKRUItJJ1UiTJHtl8g2MEQF3BgM6/fGmffIaRHnFd94LWkBNwZDFTI8oM4/LUQFtBkPtcjqgHr89+oxd+CNx0A9jIdaZHVAnTwtgi8nKqDDkKhIPgfUQ6+ST2BIC+hwv0Vd9ZEH1BHu8wjuwxKv26m/HVrJ21FdPX7dAVR1cjigzmEfXrxcwm/gIVuGQV1eXE2bz5fMaQNjKD9kBpUzACry+vbpHBYWkx7zQaluFYSCGBi1eH0Enc/CYvxjPijJP0MCZTE2qhBcTOSWFuMf9innlxu/b3KF2ujx6xf8oiKHL5bfftgHZfjvo0A+dPc1G/kPzWaYFv5jCciN+y1WWx/5/0ZE/v8bXix0XvxT6jl8nq/r533OZ3/U1T9ed+y2TtkelbdPf438nzZKsZo3Ar107hXKec4aioec9xk4SYv1Me0CSzCzrIczIVnRHKyM3rwSJqY8aRdWQ1degxVMSSt4C7BuhmjxVjPPruaNDFn9G2Td3G9Rdr0zASXfnzn1f02T1f4sUe98mZF8f9TVx9cd7JTKl6hATKabIskJIDKTTnlExWpYIFIQPbUwK55cVvzWXqv2jVMW3bQkq59WVv8GoVwGZxkqOWVRw3t8zSdAtnTNAphBqlLJkQHFcb9F7vXI//9E2vqQ3PZTXb3CukOYrDnGBDJhMspXhVFR4VsOcmKKTOiFmap2gqj2jb/mYyE5XTA7lR9L1vzeIWdGZl7MlQTpJCSh22XELMBIlS9ASUKHy4XBD+TM/RZZ1IeiIrf9jFN//jTy3E919arqjmcTc0rhmQ9kKr2ICPSwlIzwXj6W9/jcWJTulYyxDRTEhJWGqGBROhgfp0slYCQTgS8z+CydKSoDeCSfEuTGmIzHDDiezwpy436LSPXz9JfP/mRe76RF8v1ZQb29rs1hf9SLqzuCi8GRMpnQFXmbrrM44xNYARPZgnynTc50TibRXZZiKM7kA4zAAQ3j6SiLMALn8xlCVgzIzzPNfYSPEbJiQH6YOY5yOTHFC66//ljd9ezq8fubLZ8tz37ywbrjiM/o7SuwnH9Nczr92TLZapgB1v8OI6ihoyThg31BWmS11dBX1/8Ol1ZDL0nFZ/uCtMhqq6Gvrv8dLmqtXST5KeAituRtlHyKtN225P0hgvW/w4XkMF8sx0yU/+ygjbLakveHCNb/Dpew+p5hJsp/dtBGWW3J+0ME63+HH1dDtzAT5T87FNNGh++maZrm+zDreXbbpmmar/1x7v4ctk3TNM1296Edy6U/RLDg/QHJTyvnti30OS9RL2YmSrf1zg6R77d42KXjz6Z5tN1NfFO/+03TNM1m//vJz+pxUj7uv1q7OH72fzMtHl+uaTY/+560+MAbT94fItQXzEMzTrAzZUvb5d+gA2lxnk/Pc+vU6W/ptLg8f7P5Od5ebmykzUyLvgXE8mmxMtIi0lZWZ9J2+Tfoy7S4nm/Z/ByvybE9nIvfh1NnIXL5le5h+PAjT6e/WyDdjtmPQw++TcqXP7Sf5He/351evMrlV55/9PDq28PgXh2e06K7P9/73jfe/xJ9H2Ye/SECaVHL5DLJmtpureepu23Umxbb3X2dsbnOm5dHtufE8289HWIPPvI+aZ7OP9r8HIcefP3Yt/cA++vb86dfDLz6uX7Z5+2hf6/GpEXf2iLwEvcPM5v+EIG0iLSV1Zm6bdc9xGsfzS2xvX9mIO156pRt1Hcm6mGCu77ZVpDc/7rZ/z5/7EOPvHzIj/P+4NOG0mLoFx/r97S4vPr18be/9u5Vpz+09+dFWgy9xItTfMn7QwTSItJWVmcaSIsPXJEybpufFus/Tz2QFs+J3jni7p+dm+1uZFo0212nHnjat9Li9irXnbmnxeHhZNPt3fbvVU9/GJEWQy/x/GHm0x8ikBaRtrI604i0uJ7VPQ/O8wMuE8HYc8rHh1ND93E45QR69zzyvprz1N02ejwT1dq6E1znwPnF2mLoka+O4ofXFoeeM4G/+/1u6BeH0qLz+O4O9K8tpqXF0EtIi6V0e/OSW+9hxdynWtdp7km6bde7trhPT+2TvBPOKQ+lxRsn0G/nkcekxTrOU7+dFsMf5tM4CnyjMO17i6drov4O26bZ7gZfpX0I0n53z+/08L3Z//bu1bjvLYbe+NNLSItT3OvBlzjl/XZaRD7Nncl108F6t+2631tcx16rfm7WSeeUT6PTYvhUe/c8ctrz1BncbzEiLU4jr3T69DVR7absdKSBV7k/ePP1+O6uwdNu6L69GpkWPW+8/yWmpUVu47qc+y2WTIu3t3pOc0/Sbbvh7y36Tzp3DJxTnpkWveeR6zlP3W0jW9IteX+IIIO0mHqpdW/9NhFcV7Xb6/i/T/F9vzhmclnHae5Jum03kBbtA/netUX3ke+uLYZPtX8mLUo8T91tI1vSLXl/iCB1WoTPdU6st1+lvTYf+MX3JpcST3NPMiot7m3X+jSmnFM+9pyMvjxg7An0N9NiDeeppUVWW/L+EEHitJh6qfVQ/XltcRj3iy7H7jWQFnfbw8M1UY9Lh7HnlI/t1cnlxHR3lXab34PXRD20RaLz1CnbyJZ0S94fIsgxLYKXWj/XX6bF7bzQ8NV4FZzmnsRMlP/soI2y2pL3hwgSp8XUS60zSYsST3NPYibKf3bQRlltyftDBHl/b/F8qfXr+nBaDP1iPae5JzET5T87aKOstuT9IYIE91vcvbhGu+eM9tO/lNmuB9Ni4Bcjn+bO5LrpYN1M9N7skPJ+C1vSLXl/iFAv4V7uoduOBm9HevcJo3embJmJ8m/Qf6n/dy9bZ0vbHyLINi122+u1+Y/X2wzV337CWiaXSea1XRVb8gbVRlltyftDBBmnRdNyn9mH6m8/oc7Uw0yUf4Nqo6y25P0hgmzTYm1bWZ1J2+XfoNooqy15f4hAWuhMPZKfAi5iS95GyXu17bYl7w8RSAudqYe2y79BtVFWW/L+EIG00Jl6aLv8G1QbZbUl7w8RRLzfou7tn/st1rX1zg7ut6h2S94fItSXXVvY8jnNPYmZ6L3ZQRtVuyXvDxE4E6Uz9dB2+Tdo8qMfW2dL2x8ikBa1TC6TaLv8G1QbZbUl7w8RSAudqYe2y79BtVFWW/L+EIG00Jl6aLv8G1QbZbUl7w8RSAudqUfyU8BFbMnbKHmvtt225P0hAmmhM/XQdvk3qDbKakveHyJwv0XUzpTJddPBurYb2aAJ20sbZbUl7w8R6tYWKTtTtrRd/g2qjbLakveHCNydV8tp7knMRPnPDtooqy15f4jA2kJn6qHt8m9QbZTVlrw/RCAtdKYe2i7/Bk2+VrZ1trT9IQJpUcvkMom2W1mDwnzSwuTSQ9utrEFhPmlhcumh7VbWoDCf+y2iTi6ZXDcdrCc/BVzElk97qatHqFtbRE0LgEJJC2kBECYtpAVAmHu5U57mBiiFKQyAMGkBQJi0ACBswfst1NXV1dVXU7e2ACBMWgAQJi0ACJMWAIRJCwDCpAUAYdICgDD3W6irq6urh+vWFgCESQsAwqQFAGHSAoAwaQFAmLQAIExaABDmfgt1dXV19XDd2gKAMGkBQJi0ACBMWgAQJi0ACJMWAIRJCwDC3G+hrq6urh6uW1sAECYtAAiTFgCESQsAwqQFAGHSAoAwaQFAmPst1NXV1dXDdWsLAMKkBQBh0gKAMGkBQJi0ACBMWgAQJi0ACHO/hbq6urp6uG5tAUCYtAAgTFoAECYtAAiTFgCESQsAwqQFAGHut1BXV1dXD9etLQAI+x9/pPPUvfBzwwAAAABJRU5ErkJggg==" alt="" />
1.4 IoSessionConfig
1.4 IoProcess
aaarticlea/png;base64,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" alt="" />
1.5 acceptor.bind(new InetSocketAddress(this.serverAddr, this.serverPort));
最终会运行AbstractPollingIoAcceptor.bindInternal
AbstractPollingIoAcceptor
protected final Set<SocketAddress> bindInternal(
List<? extends SocketAddress> localAddresses) throws Exception {
// Create a bind request as a Future operation. When the selector
// have handled the registration, it will signal this future.
AcceptorOperationFuture request = new AcceptorOperationFuture(
localAddresses); // adds the Registration request to the queue for the Workers
// to handle
registerQueue.add(request); // creates the Acceptor instance and has the local
// executor kick it off.
startupAcceptor(); // As we just started the acceptor, we have to unblock the select()
// in order to process the bind request we just have added to the
// registerQueue.
wakeup(); // Now, we wait until this request is completed.
request.awaitUninterruptibly(); if (request.getException() != null) {
throw request.getException();
} // Update the local addresses.
// setLocalAddresses() shouldn't be called from the worker thread
// because of deadlock.
Set<SocketAddress> newLocalAddresses = new HashSet<SocketAddress>(); for (H handle:boundHandles.values()) {
newLocalAddresses.add(localAddress(handle));
} return newLocalAddresses;
}
1.5.1 startupAcceptor() 使用线程池执行Acceptor
/**
* This method is called by the doBind() and doUnbind()
* methods. If the acceptor is null, the acceptor object will
* be created and kicked off by the executor. If the acceptor
* object is null, probably already created and this class
* is now working, then nothing will happen and the method
* will just return.
*/
private void startupAcceptor() {
// If the acceptor is not ready, clear the queues
// TODO : they should already be clean : do we have to do that ?
if (!selectable) {
registerQueue.clear();
cancelQueue.clear();
} // start the acceptor if not already started
Acceptor acceptor = acceptorRef.get(); if (acceptor == null) {
acceptor = new Acceptor(); if (acceptorRef.compareAndSet(null, acceptor)) {
executeWorker(acceptor);
}
}
}
Acceptor() 实现了Runnable接口 不停的执行
/**
* This class is called by the startupAcceptor() method and is
* placed into a NamePreservingRunnable class.
* It's a thread accepting incoming connections from clients.
* The loop is stopped when all the bound handlers are unbound.
*/
private class Acceptor implements Runnable {
public void run() {
assert (acceptorRef.get() == this); int nHandles = 0; while (selectable) {
try {
// Detect if we have some keys ready to be processed
// The select() will be woke up if some new connection
// have occurred, or if the selector has been explicitly
// woke up
int selected = select(); // this actually sets the selector to OP_ACCEPT,
// and binds to the port on which this class will
// listen on
nHandles += registerHandles(); // Now, if the number of registred handles is 0, we can
// quit the loop: we don't have any socket listening
// for incoming connection.
if (nHandles == 0) {
acceptorRef.set(null); if (registerQueue.isEmpty() && cancelQueue.isEmpty()) {
assert (acceptorRef.get() != this);
break;
} if (!acceptorRef.compareAndSet(null, this)) {
assert (acceptorRef.get() != this);
break;
} assert (acceptorRef.get() == this);
} if (selected > 0) {
// We have some connection request, let's process
// them here.
processHandles(selectedHandles());
} // check to see if any cancellation request has been made.
nHandles -= unregisterHandles();
} catch (ClosedSelectorException cse) {
// If the selector has been closed, we can exit the loop
break;
} catch (Throwable e) {
ExceptionMonitor.getInstance().exceptionCaught(e); try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
ExceptionMonitor.getInstance().exceptionCaught(e1);
}
}
} // Cleanup all the processors, and shutdown the acceptor.
if (selectable && isDisposing()) {
selectable = false;
try {
if (createdProcessor) {
processor.dispose();
}
} finally {
try {
synchronized (disposalLock) {
if (isDisposing()) {
destroy();
}
}
} catch (Exception e) {
ExceptionMonitor.getInstance().exceptionCaught(e);
} finally {
disposalFuture.setDone();
}
}
}
}
NioSocketAcceptor
/**
* Check if we have at least one key whose corresponding channels is
* ready for I/O operations.
*
* This method performs a blocking selection operation.
* It returns only after at least one channel is selected,
* this selector's wakeup method is invoked, or the current thread
* is interrupted, whichever comes first.
*
* @return The number of keys having their ready-operation set updated
* @throws IOException If an I/O error occurs
* @throws ClosedSelectorException If this selector is closed
*/
@Override
protected int select() throws Exception {
return selector.select();
}
请问
/**
* Sets up the socket communications. Sets items such as:
* <p/>
* Blocking
* Reuse address
* Receive buffer size
* Bind to listen port
* Registers OP_ACCEPT for selector
*/
private int registerHandles() {
for (;;) {
// The register queue contains the list of services to manage
// in this acceptor.
AcceptorOperationFuture future = registerQueue.poll(); if (future == null) {
return 0;
} // We create a temporary map to store the bound handles,
// as we may have to remove them all if there is an exception
// during the sockets opening.
Map<SocketAddress, H> newHandles = new ConcurrentHashMap<SocketAddress, H>();
List<SocketAddress> localAddresses = future.getLocalAddresses(); try {
// Process all the addresses
for (SocketAddress a : localAddresses) {
H handle = open(a);
newHandles.put(localAddress(handle), handle);
} // Everything went ok, we can now update the map storing
// all the bound sockets.
boundHandles.putAll(newHandles); // and notify.
future.setDone();
return newHandles.size();
} catch (Exception e) {
// We store the exception in the future
future.setException(e);
} finally {
// Roll back if failed to bind all addresses.
if (future.getException() != null) {
for (H handle : newHandles.values()) {
try {
close(handle);
} catch (Exception e) {
ExceptionMonitor.getInstance().exceptionCaught(e);
}
} // TODO : add some comment : what is the wakeup() waking up ?
wakeup();
}
}
}
}
接上图open方法 jdk自带的NIO
/**
* {@inheritDoc}
*/
@Override
protected ServerSocketChannel open(SocketAddress localAddress)
throws Exception {
// Creates the listening ServerSocket
ServerSocketChannel channel = ServerSocketChannel.open(); boolean success = false; try {
// This is a non blocking socket channel
channel.configureBlocking(false); // Configure the server socket,
ServerSocket socket = channel.socket(); // Set the reuseAddress flag accordingly with the setting
socket.setReuseAddress(isReuseAddress()); // and bind.
socket.bind(localAddress, getBacklog()); // Register the channel within the selector for ACCEPT event
channel.register(selector, SelectionKey.OP_ACCEPT);
success = true;
} finally {
if (!success) {
close(channel);
}
}
return channel;
}
Acceptor接收数据
if (selected > 0) {
// We have some connection request, let's process
// them here.
processHandles(selectedHandles());
}
/**
* This method will process new sessions for the Worker class. All
* keys that have had their status updates as per the Selector.selectedKeys()
* method will be processed here. Only keys that are ready to accept
* connections are handled here.
* <p/>
* Session objects are created by making new instances of SocketSessionImpl
* and passing the session object to the SocketIoProcessor class.
*/
@SuppressWarnings("unchecked")
private void processHandles(Iterator<H> handles) throws Exception {
while (handles.hasNext()) {
H handle = handles.next();
handles.remove(); // Associates a new created connection to a processor,
// and get back a session
S session = accept(processor, handle); if (session == null) {
break;
}
//初始化session
initSession(session, null, null); // add the session to the SocketIoProcessor 过滤链处理数据入口
session.getProcessor().add(session);
}
}
processHandles 的accept 获取SocketChannel 封装成NioSocketSession
protected NioSession accept(IoProcessor<NioSession> processor,
ServerSocketChannel handle) throws Exception { SelectionKey key = handle.keyFor(selector); if ((key == null) || (!key.isValid()) || (!key.isAcceptable()) ) {
return null;
} // accept the connection from the client
SocketChannel ch = handle.accept(); if (ch == null) {
return null;
} return new NioSocketSession(this, processor, ch);
}
processor
/**
* {@inheritDoc}
*/
public final void add(S session) {
if (disposed || disposing) {
throw new IllegalStateException("Already disposed.");
} // Adds the session to the newSession queue and starts the worker
newSessions.add(session);
startupProcessor();
}
/**
* Starts the inner Processor, asking the executor to pick a thread in its
* pool. The Runnable will be renamed
*/
private void startupProcessor() {
Processor processor = processorRef.get(); if (processor == null) {
processor = new Processor(); if (processorRef.compareAndSet(null, processor)) {
executor.execute(new NamePreservingRunnable(processor, threadName));
}
} // Just stop the select() and start it again, so that the processor
// can be activated immediately.
wakeup();
}
主要接收数据处理代码逻辑
/**
* The main loop. This is the place in charge to poll the Selector, and to
* process the active sessions. It's done in
* - handle the newly created sessions
* -
*/
private class Processor implements Runnable {
public void run() {
assert (processorRef.get() == this); int nSessions = 0;
lastIdleCheckTime = System.currentTimeMillis(); for (;;) {
try {
// This select has a timeout so that we can manage
// idle session when we get out of the select every
// second. (note : this is a hack to avoid creating
// a dedicated thread).
long t0 = System.currentTimeMillis();
int selected = select(SELECT_TIMEOUT);
long t1 = System.currentTimeMillis();
long delta = (t1 - t0); if ((selected == 0) && !wakeupCalled.get() && (delta < 100)) {
// Last chance : the select() may have been
// interrupted because we have had an closed channel.
if (isBrokenConnection()) {
LOG.warn("Broken connection"); // we can reselect immediately
// set back the flag to false
wakeupCalled.getAndSet(false); continue;
} else {
LOG.warn("Create a new selector. Selected is 0, delta = "
+ (t1 - t0));
// Ok, we are hit by the nasty epoll
// spinning.
// Basically, there is a race condition
// which causes a closing file descriptor not to be
// considered as available as a selected channel, but
// it stopped the select. The next time we will
// call select(), it will exit immediately for the same
// reason, and do so forever, consuming 100%
// CPU.
// We have to destroy the selector, and
// register all the socket on a new one.
registerNewSelector();
} // Set back the flag to false
wakeupCalled.getAndSet(false); // and continue the loop
continue;
} // Manage newly created session first
nSessions += handleNewSessions(); updateTrafficMask(); // Now, if we have had some incoming or outgoing events,
// deal with them
if (selected > 0) {
//LOG.debug("Processing ..."); // This log hurts one of the MDCFilter test...
process();
} // Write the pending requests
long currentTime = System.currentTimeMillis();
flush(currentTime); // And manage removed sessions
nSessions -= removeSessions(); // Last, not least, send Idle events to the idle sessions
notifyIdleSessions(currentTime); // Get a chance to exit the infinite loop if there are no
// more sessions on this Processor
if (nSessions == 0) {
processorRef.set(null); if (newSessions.isEmpty() && isSelectorEmpty()) {
// newSessions.add() precedes startupProcessor
assert (processorRef.get() != this);
break;
} assert (processorRef.get() != this); if (!processorRef.compareAndSet(null, this)) {
// startupProcessor won race, so must exit processor
assert (processorRef.get() != this);
break;
} assert (processorRef.get() == this);
} // Disconnect all sessions immediately if disposal has been
// requested so that we exit this loop eventually.
if (isDisposing()) {
for (Iterator<S> i = allSessions(); i.hasNext();) {
scheduleRemove(i.next());
} wakeup();
}
} catch (ClosedSelectorException cse) {
// If the selector has been closed, we can exit the loop
break;
} catch (Throwable t) {
ExceptionMonitor.getInstance().exceptionCaught(t); try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
ExceptionMonitor.getInstance().exceptionCaught(e1);
}
}
} try {
synchronized (disposalLock) {
if (disposing) {
doDispose();
}
}
} catch (Throwable t) {
ExceptionMonitor.getInstance().exceptionCaught(t);
} finally {
disposalFuture.setValue(true);
}
}
}
过滤链:
private void process() throws Exception {
for (Iterator<S> i = selectedSessions(); i.hasNext();) {
S session = i.next();
process(session);
i.remove();
}
} /**
* Deal with session ready for the read or write operations, or both.
*/
private void process(S session) {
// Process Reads
if (isReadable(session) && !session.isReadSuspended()) {
read(session);
} // Process writes
if (isWritable(session) && !session.isWriteSuspended()) {
// add the session to the queue, if it's not already there
if (session.setScheduledForFlush(true)) {
flushingSessions.add(session);
}
}
} private void read(S session) {
IoSessionConfig config = session.getConfig();
int bufferSize = config.getReadBufferSize();
IoBuffer buf = IoBuffer.allocate(bufferSize); final boolean hasFragmentation = session.getTransportMetadata()
.hasFragmentation(); try {
int readBytes = 0;
int ret; try {
if (hasFragmentation) { while ((ret = read(session, buf)) > 0) {
readBytes += ret; if (!buf.hasRemaining()) {
break;
}
}
} else {
ret = read(session, buf); if (ret > 0) {
readBytes = ret;
}
}
} finally {
buf.flip();
} if (readBytes > 0) {
//处理逻辑
IoFilterChain filterChain = session.getFilterChain();
filterChain.fireMessageReceived(buf);
buf = null; if (hasFragmentation) {
if (readBytes << 1 < config.getReadBufferSize()) {
session.decreaseReadBufferSize();
} else if (readBytes == config.getReadBufferSize()) {
session.increaseReadBufferSize();
}
}
} if (ret < 0) {
scheduleRemove(session);
}
} catch (Throwable e) {
if (e instanceof IOException) {
if (!(e instanceof PortUnreachableException)
|| !AbstractDatagramSessionConfig.class.isAssignableFrom(config.getClass())
|| ((AbstractDatagramSessionConfig) config).isCloseOnPortUnreachable()) {
scheduleRemove(session);
}
} IoFilterChain filterChain = session.getFilterChain();
filterChain.fireExceptionCaught(e);
}
}
调用过滤连: DefaultIoFilterChain
public void fireMessageReceived(Object message) {
if (message instanceof IoBuffer) {
session.increaseReadBytes(((IoBuffer) message).remaining(), System
.currentTimeMillis());
} Entry head = this.head;
callNextMessageReceived(head, session, message);
} private void callNextMessageReceived(Entry entry, IoSession session,
Object message) {
try {
IoFilter filter = entry.getFilter();
NextFilter nextFilter = entry.getNextFilter();
filter.messageReceived(nextFilter, session,
message);
} catch (Throwable e) {
fireExceptionCaught(e);
}
}
业务处理handler总是最后处理
Mina代码跟踪(1)的更多相关文章
- AM335x tscadc platform driver 相关代码跟踪
TI AM335x ti am335x_tsc.c 代码跟踪 在kernel 首层目录: 先运行make ARCH=arm tags 这个作用是建立tags文件,只含有arm架构的,利用ctag即可进 ...
- openstack学习笔记一 虚拟机启动过程代码跟踪
openstack学习笔记一 虚拟机启动过程代码跟踪 本文主要通过对虚拟机创建过程的代码跟踪.观察虚拟机启动任务状态的变化,来透彻理解openstack各组件之间的作用过程. 当从horizon界面发 ...
- 简单 php 代码跟踪调试实现
简单 php 代码跟踪调试实现 debug_backtrace:生成回溯 debug_print_backtrace:打印回溯 1. debug_backtrace ($options = DEBUG ...
- trace与代码跟踪服务
首先开篇引用<MVC2 2 in action>里面一段关于这个跟踪服务的话 When you called Trace.Write() in Web Forms, you were in ...
- Linux 内核高-低端内存设置代码跟踪(ARM构架)
对于ARM中内核如何在启动的时候设置高低端内存的分界线(也是逻辑地址与虚拟地址分界线(虚拟地址)减去那个固定的偏移),这里我稍微引导下(内核分析使用Linux-3.0): 首先定位设置内核虚拟地址起始 ...
- saiku执行过程代码跟踪
使用了很久的saiku,决定跟踪一下代码,看看它的执行核心过程: 一.入口controller代码 1.1.页面打开之后,会发送一个ajax请求 Request URL: http://l-tdata ...
- 【实习记】2014-08-10(上)代码跟踪git的想法+归并排序的debug过程
(冒泡,选择,插入,希尔,快速,归并,堆排)周末加班学习C++,打算用C++写七大经典排序代码.发现3个月前自己写的七大经典排序代码(C Language)突然运行出错. Makefile内容 ...
- __FILE__,__LINE__,FUNCTION__实现代码跟踪调试(linux下c语言编程 )
root@xuanfei-desktop:~/cpropram/2# cat global.h //头文件#ifndef CLOBAL_H #define GLOBAL_H ...
- __FILE__,__LINE__,FUNCTION__实现代码跟踪调试
转:http://www.cnitblog.com/zouzheng/archive/2007/08/31/32691.aspx 先看下简单的初始代码:注意其编译运行后的结果. root@xuanfe ...
随机推荐
- linux下批量更改一个目下的目录和文件的权限
对于网站目录我们一般设置目录的权限是755, 而文件的权限是644 ,上传目录另设 比如我们要设置web目录下的所有目录的权限是755,文件的目录是644,那么我们可以批量修改吗?答案是肯定的, 就 ...
- linux命令详解:basename命令
转:http://www.cnblogs.com/lwgdream/archive/2013/11/05/3407768.html 前言 bashname命令用于获取路径中的文件名或路径名(获取的时候 ...
- JAVA常见算法题(十六)
package com.xiaowu.demo; //猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个: //第二天早上又将剩下的桃子吃掉一半,而且又多吃了一个. //以后 ...
- lodop 控件实现web打印功能
WEB套打可选方案不多,理想的更少,利用免费控件Lodop+JavaScript实现精确套打,算是较为经典的选择.这种方案其实比较简单,利用一个htm文件就可以实现模板设计过程,几乎是“空手套”式的开 ...
- php设计模式之建造者模式
建造者模式 建造者设计模式的目的是消除其他对象的复杂创建过程.使用建造者设计模式不仅是最佳的做法,而且在摸个对象的构造和配置方法改变时候,可以尽可能的减少重复更改代码. <?php /** *p ...
- 在Centos7.x中安装psutil模块
一.window10操作系统(Python 3.6开发环境)安装psutil 1.安装psutil模块 wget https://pypi.python.org/packages/source/p/p ...
- 2017.7.10 Redis报错:DENIED Redis is running in protected mode
参考来自: java 客户端链接不上redis解决方案 DENIED Redis is running in protected mode 完整错误信息: Caused by: redis.clien ...
- call、aply、bind的常用方法总结
类函数变为数组 function aaa (){ Array.prototype.slice(arguments); } 进一步操作它的每个元素 function bbb() { Array.prot ...
- Angular 学习笔记——ng-animate
<!DOCTYPE HTML> <html ng-app="myApp"> <head> <meta http-equiv="C ...
- iOS开发:Framework的创建
转载自:http://jonzzs.cn/2017/06/01/iOS%20开发笔记/[iOS%20开发]将自己的框架打包成%20Framework%20的方法/ 环境:Xcode 8 创建 Fram ...