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