1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.core.nio.tcp;
21
22 import java.io.IOException;
23 import java.net.InetSocketAddress;
24 import java.nio.ByteBuffer;
25
26 import org.apache.mina.api.IdleStatus;
27 import org.apache.mina.api.IoHandler;
28 import org.apache.mina.api.IoService;
29 import org.apache.mina.api.IoSession;
30 import org.apache.mina.core.BenchmarkServer;
31 import org.apache.mina.session.AttributeKey;
32 import org.apache.mina.transport.nio.NioTcpServer;
33
34
35
36
37
38 public class Mina3TcpBenchmarkServer implements BenchmarkServer {
39
40 private static enum State {
41 WAIT_FOR_FIRST_BYTE_LENGTH, WAIT_FOR_SECOND_BYTE_LENGTH, WAIT_FOR_THIRD_BYTE_LENGTH, WAIT_FOR_FOURTH_BYTE_LENGTH, READING
42 }
43
44 private static final ByteBuffer ACK = ByteBuffer.allocate(1);
45
46 static {
47 ACK.put((byte) 0);
48 ACK.rewind();
49 }
50
51 private static final AttributeKey<State> STATE_ATTRIBUTE = new AttributeKey<State>(State.class,
52 Mina3TcpBenchmarkServer.class.getName() + ".state");
53
54 private static final AttributeKey<Integer> LENGTH_ATTRIBUTE = new AttributeKey<Integer>(Integer.class,
55 Mina3TcpBenchmarkServer.class.getName() + ".length");
56
57 private NioTcpServer tcpServer;
58
59
60
61
62 public void start(int port) throws IOException {
63 tcpServer = new NioTcpServer();
64 tcpServer.getSessionConfig().setReadBufferSize(128 * 1024);
65 tcpServer.getSessionConfig().setTcpNoDelay(true);
66 tcpServer.setIoHandler(new IoHandler() {
67 public void sessionOpened(IoSession session) {
68 session.setAttribute(STATE_ATTRIBUTE, State.WAIT_FOR_FIRST_BYTE_LENGTH);
69 }
70
71 public void messageReceived(IoSession session, Object message) {
72 if (message instanceof ByteBuffer) {
73 ByteBuffer buffer = (ByteBuffer) message;
74
75 State state = session.getAttribute(STATE_ATTRIBUTE);
76 int length = 0;
77
78 if (session.getAttribute(LENGTH_ATTRIBUTE) != null) {
79 length = session.getAttribute(LENGTH_ATTRIBUTE);
80 }
81
82 while (buffer.remaining() > 0) {
83 switch (state) {
84 case WAIT_FOR_FIRST_BYTE_LENGTH:
85 length = (buffer.get() & 255) << 24;
86 state = State.WAIT_FOR_SECOND_BYTE_LENGTH;
87 break;
88 case WAIT_FOR_SECOND_BYTE_LENGTH:
89 length += (buffer.get() & 255) << 16;
90 state = State.WAIT_FOR_THIRD_BYTE_LENGTH;
91 break;
92 case WAIT_FOR_THIRD_BYTE_LENGTH:
93 length += (buffer.get() & 255) << 8;
94 state = State.WAIT_FOR_FOURTH_BYTE_LENGTH;
95 break;
96 case WAIT_FOR_FOURTH_BYTE_LENGTH:
97 length += (buffer.get() & 255);
98 state = State.READING;
99 if ((length == 0) && (buffer.remaining() == 0)) {
100 session.write(ACK.slice());
101 state = State.WAIT_FOR_FIRST_BYTE_LENGTH;
102 }
103 break;
104 case READING:
105 int remaining = buffer.remaining();
106 if (length > remaining) {
107 length -= remaining;
108 buffer.position(buffer.position() + remaining);
109 } else {
110 buffer.position(buffer.position() + length);
111 session.write(ACK.slice());
112 state = State.WAIT_FOR_FIRST_BYTE_LENGTH;
113 length = 0;
114 }
115 }
116 }
117 session.setAttribute(LENGTH_ATTRIBUTE, length);
118 session.setAttribute(STATE_ATTRIBUTE, state);
119 }
120 }
121
122 public void exceptionCaught(IoSession session, Exception cause) {
123 cause.printStackTrace();
124 }
125
126 @Override
127 public void sessionClosed(IoSession session) {
128 }
129
130 @Override
131 public void sessionIdle(IoSession session, IdleStatus status) {
132 }
133
134 @Override
135 public void messageSent(IoSession session, Object message) {
136 }
137
138 @Override
139 public void serviceActivated(IoService service) {
140 }
141
142 @Override
143 public void serviceInactivated(IoService service) {
144 }
145 });
146
147 tcpServer.bind(new InetSocketAddress(port));
148 }
149
150
151
152
153 public void stop() throws IOException {
154 tcpServer.unbind();
155 }
156 }