SocketImpl.java revision 2cd82d7111f68ff63145ef7c393bf1479ff06223
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package java.net; 19 20import java.io.FileDescriptor; 21import java.io.IOException; 22import java.io.InputStream; 23import java.io.OutputStream; 24import org.apache.harmony.luni.platform.INetworkSystem; 25import org.apache.harmony.luni.platform.Platform; 26 27/** 28 * This class is the base of all streaming socket implementation classes. 29 * Streaming sockets are wrapped by two classes, {@code ServerSocket} and 30 * {@code Socket} at the server and client end of a connection. At the server, 31 * there are two types of sockets engaged in communication, the {@code 32 * ServerSocket} on a well known port (referred to as listener) used to 33 * establish a connection and the resulting {@code Socket} (referred to as 34 * host). 35 */ 36public abstract class SocketImpl implements SocketOptions { 37 38 /** 39 * The remote address this socket is connected to. 40 */ 41 protected InetAddress address; 42 43 /** 44 * The remote port this socket is connected to. 45 */ 46 protected int port; 47 48 /** 49 * The file descriptor of this socket. 50 */ 51 protected FileDescriptor fd; 52 53 /** 54 * The local port this socket is connected to. 55 */ 56 protected int localport; 57 58 INetworkSystem netImpl = Platform.getNetworkSystem(); 59 60 boolean streaming = true; 61 62 /** 63 * Waits for an incoming request and blocks until the connection is opened 64 * on the given socket. 65 * 66 * @param newSocket 67 * the socket to accept connections on. 68 * @throws IOException 69 * if an error occurs while accepting a new connection. 70 */ 71 protected abstract void accept(SocketImpl newSocket) throws IOException; 72 73 /** 74 * Returns the available number of bytes which are readable from this socket 75 * without blocking. 76 * 77 * @return the number of bytes that may be read without blocking. 78 * @throws IOException 79 * if an error occurs while reading the number of bytes. 80 */ 81 protected abstract int available() throws IOException; 82 83 /** 84 * Binds this socket to the specified local host address and port number. 85 * 86 * @param address 87 * the local machine address to bind this socket to. 88 * @param port 89 * the port on the local machine to bind this socket to. 90 * @throws IOException 91 * if an error occurs while binding this socket. 92 */ 93 protected abstract void bind(InetAddress address, int port) 94 throws IOException; 95 96 /** 97 * Closes this socket. This makes later access invalid. 98 * 99 * @throws IOException 100 * if an error occurs while closing this socket. 101 */ 102 protected abstract void close() throws IOException; 103 104 /** 105 * Connects this socket to the specified remote host and port number. 106 * 107 * @param host 108 * the remote host this socket has to be connected to. 109 * @param port 110 * the remote port on which this socket has to be connected. 111 * @throws IOException 112 * if an error occurs while connecting to the remote host. 113 */ 114 protected abstract void connect(String host, int port) throws IOException; 115 116 /** 117 * Connects this socket to the specified remote host address and port 118 * number. 119 * 120 * @param address 121 * the remote host address this socket has to be connected to. 122 * @param port 123 * the remote port on which this socket has to be connected. 124 * @throws IOException 125 * if an error occurs while connecting to the remote host. 126 */ 127 protected abstract void connect(InetAddress address, int port) 128 throws IOException; 129 130 /** 131 * Creates a new unconnected socket. The argument {@code isStreaming} 132 * defines whether the new socket is a streaming or a datagram socket. 133 * 134 * @param isStreaming 135 * defines whether the type of the new socket is streaming or 136 * datagram. 137 * @throws IOException 138 * if an error occurs while creating the socket. 139 */ 140 protected abstract void create(boolean isStreaming) throws IOException; 141 142 /** 143 * Gets the file descriptor of this socket. 144 * 145 * @return the file descriptor of this socket. 146 */ 147 protected FileDescriptor getFileDescriptor() { 148 return fd; 149 } 150 151 /** 152 * Gets the remote address this socket is connected to. 153 * 154 * @return the remote address of this socket. 155 */ 156 protected InetAddress getInetAddress() { 157 return address; 158 } 159 160 /** 161 * Gets the input stream of this socket. 162 * 163 * @return the input stream of this socket. 164 * @throws IOException 165 * if an error occurs while accessing the input stream. 166 */ 167 protected abstract InputStream getInputStream() throws IOException; 168 169 /** 170 * Gets the local port number of this socket. The field is initialized to 171 * {@code -1} and upon demand will go to the IP stack to get the bound 172 * value. See the class comment for the context of the local port. 173 * 174 * @return the local port number this socket is bound to. 175 */ 176 protected int getLocalPort() { 177 return localport; 178 } 179 180 /** 181 * Gets the value of the given socket option. 182 * 183 * @param optID 184 * the socket option to retrieve. 185 * @return the option value. 186 * @throws SocketException 187 * if an error occurs while accessing the option. 188 */ 189 public abstract Object getOption(int optID) throws SocketException; 190 191 /** 192 * Gets the output stream of this socket. 193 * 194 * @return the output stream of this socket. 195 * @throws IOException 196 * if an error occurs while accessing the output stream. 197 */ 198 protected abstract OutputStream getOutputStream() throws IOException; 199 200 /** 201 * Gets the remote port number of this socket. This value is not meaningful 202 * when this instance is wrapped by a {@code ServerSocket}. 203 * 204 * @return the remote port this socket is connected to. 205 */ 206 protected int getPort() { 207 return port; 208 } 209 210 /** 211 * Listens for connection requests on this streaming socket. Incoming 212 * connection requests are queued up to the limit specified by {@code 213 * backlog}. Additional requests are rejected. The method {@code listen()} 214 * may only be invoked on streaming sockets. 215 * 216 * @param backlog 217 * the maximum number of outstanding connection requests. 218 * @throws IOException 219 * if an error occurs while listening. 220 */ 221 protected abstract void listen(int backlog) throws IOException; 222 223 /** 224 * Sets the value for the specified socket option. 225 * 226 * @param optID 227 * the socket option to be set. 228 * @param val 229 * the option value. 230 * @throws SocketException 231 * if an error occurs while setting the option. 232 */ 233 public abstract void setOption(int optID, Object val) 234 throws SocketException; 235 236 /** 237 * Returns a string containing a concise, human-readable description of the 238 * socket. 239 * 240 * @return the textual representation of this socket. 241 */ 242 @SuppressWarnings("nls") 243 @Override 244 public String toString() { 245 return new StringBuilder(100).append("Socket[addr=").append( 246 getInetAddress()).append(",port=").append(port).append( 247 ",localport=").append(getLocalPort()).append("]").toString(); 248 } 249 250 /** 251 * In the IP stack, write at most {@code count} bytes on the socket 252 * from the {@code buffer}, from the {@code offset}. 253 * 254 * @param buffer 255 * the buffer to read into 256 * @param offset 257 * the offset into the buffer 258 * @param count 259 * the number of bytes to write 260 * @return int the actual number of bytes written 261 * @throws IOException 262 * thrown if an error occurs while writing 263 */ 264 int write(byte[] buffer, int offset, int count) throws IOException { 265 if (streaming) { 266 return this.netImpl.write(fd, buffer, offset, count); 267 } else { 268 return this.netImpl.send(fd, buffer, offset, count, port, address); 269 } 270 } 271 272 /** 273 * Closes the input channel of this socket. 274 * <p> 275 * This default implementation always throws an {@link IOException} to 276 * indicate that the subclass should have overridden this method. 277 * 278 * @throws IOException 279 * always because this method should be overridden. 280 */ 281 protected void shutdownInput() throws IOException { 282 throw new IOException("Method has not been implemented"); 283 } 284 285 /** 286 * Closes the output channel of this socket. 287 * <p> 288 * This default implementation always throws an {@link IOException} to 289 * indicate that the subclass should have overridden this method. 290 * 291 * @throws IOException 292 * always because this method should be overridden. 293 */ 294 protected void shutdownOutput() throws IOException { 295 throw new IOException("Method has not been implemented"); 296 } 297 298 /** 299 * Connects this socket to the remote host address and port number specified 300 * by the {@code SocketAddress} object with the given timeout. This method 301 * will block indefinitely if the timeout is set to zero. 302 * 303 * @param remoteAddr 304 * the remote host address and port number to connect to. 305 * @param timeout 306 * the timeout value in milliseconds. 307 * @throws IOException 308 * if an error occurs while connecting. 309 */ 310 protected abstract void connect(SocketAddress remoteAddr, int timeout) 311 throws IOException; 312 313 /** 314 * Returns whether the socket supports urgent data or not. Subclasses should 315 * override this method. 316 * 317 * @return {@code false} because subclasses must override this method. 318 */ 319 protected boolean supportsUrgentData() { 320 return false; 321 } 322 323 /** 324 * Sends the single byte of urgent data on the socket. 325 * 326 * @param value 327 * the byte of urgent data. 328 * @throws IOException 329 * if an error occurs sending urgent data. 330 */ 331 protected abstract void sendUrgentData(int value) throws IOException; 332 333 /** 334 * Sets performance preference for connection time, latency and bandwidth. 335 * Does nothing by default. 336 * 337 * @param connectionTime 338 * the importance of connect time. 339 * @param latency 340 * the importance of latency. 341 * @param bandwidth 342 * the importance of bandwidth. 343 */ 344 protected void setPerformancePreferences(int connectionTime, int latency, 345 int bandwidth) { 346 // Our socket implementation only provide one protocol: TCP/IP, so 347 // we do nothing for this method 348 } 349} 350