Socket 会被client和server用到,它代表一个线上的联结,不属于client也不属于server。它的构造函数如下:1 public Socket(String host, int port) throws UnknownHostException, IOException; 会尝试建立一个对远程的connect,但在本机上的IP就是本机IP,port是本机操作系统随即分配的。
2 public Socket(InetAddress host, int port) throws IOException, 和上面那个差不多,不过不会扔出UnknownHostException,这个异常会在InetAddress建立过程中出现。
3 public Socket(String host, int port, InetAddress interface, int localPort) throws IOException, UnknownHostException 从指定的localPort上连接一个Host,会尝试建立连接。
4 public Socket(InetAddress host, int port, InetAddress interface, int localPort) throws IOException 和上面那个类似。
5 public Socket( )
制造一个还没有连接Host的socket,如果以后要连接,这个调用 connect(SocketAddress)来实现。
6 protected Socket(SocketImpl impl)
7 public Socket(Proxy proxy) // Java 1.5 这个构造函数的意思就是,从本机上发出的连接,经过一个Proxy,然后再到达指定的Host。 下面是一个用法: SocetAddress proxyAddress = new InetSocketAddress("myproxy.example.com", 1080);
Proxy proxy = new Proxy(Proxy.Type.SOCKS, proxyAddress)
Socket s = new Socket(proxy);
SocketAddress remote = new InetSocketAddress("login.ibiblio.org", 25);
s.connect(remote);//通过代理发起连接 如果不用这种方法,代理也可以设置。设置 socksProxyHost and socksProxyPort system properties, 不过这个设置会对所有的Socket起作用。
8 Socket 用一个SocketImpl 字段,其中SocketImpl 主要用来实现 native code.
9 public InetAddress getInetAddress( ) 用来得到Socket所连接的 remote host. (相似的方法有:int getPort())
10 public int getLocalPort( ) 一个Socket分为两端,remote host 端的host是已知的,而local host 是操作系统分配的。当local传输数据时,会把自己的port信息附带的发给remote host,这样 remote就知道如何回复local了。
11 public InetAddress getLocalAddress( ) 在有多个网卡时可能会用到。
12 public InputStream getInputStream( ) throws IOException 从remote host读数据
13 public OutputStream getOutputStream( ) throws IOException 向remote host写数据
14 Setting Socket Options Socket Options 包括好几个,他们是: TCP_NODELAY (Setting TCP_NODELAY to true ensures that packets are sent as quickly as possible regardless of their size,即可以不buffer)
SO_BINDADDR
SO_TIMEOUT (当socket在read的时候它可能会block, 如果设置timeout, 则过了这个时间就会抛出InterruptedIOException)
SO_LINGER (在socket关闭前,剩余数据的传输时间)
SO_SNDBUF (Java 1.2 and later)
SO_RCVBUF (Java 1.2 and later)
SO_KEEPALIVE (Java 1.3 and later)
OOBINLINE (Java 1.4 and later)
15 Class of Service public int getTrafficClass( ) throws SocketException public void setTrafficClass(int trafficClass) throws SocketException 只有以下四种Service 0x02: Low cost
0x04: High reliability
0x08: Maximum throughput
0x10: Minimum delay
16 Socket Exceptions Most methods of the Socket class are declared to throw IOException or its subclass. Such as public class SocketException extends IOException public class BindException extends SocketException public class ConnectException extends SocketException public class NoRouteToHostException extends SocketException
这些异常类的说明如下: A BindException is thrown if you try to construct a Socket or ServerSocket object on a local port that is in use or that you do not have sufficient privileges to use. A ConnectException is thrown when a connection is refused at the remote host, which usually happens because the host is busy or no process is listening on that port. Finally, a NoRouteToHostException indicates that the connection has timed out
17 Socket Addresses 代表远端的一个地址,包括InetAddress 和 port, 主要用在 Socket.connect(SocketAddress a) 中
18 Closing the socket
一个client是这样对待一个Socket的。当Socket的两个流都关闭了、程序结束、被垃圾收集器回收 时,Socket在本机上占用的资源就被释放了,但这样不是好方法,我们应该显示的关闭它。有下面几个方法可用。
public void close( ) throws IOException
我们应该这样用它
Socket connection = null; try { connection = new Socket("www.oreilly.com", 13); // interact with the socket... } // end try catch (UnknownHostException ex) { System.err.println(ex); } catch (IOException ex) { System.err.println(ex); } finally { if (connection != null) connection.close( ); }
但用close( )关闭Socket后,还是可以调用它的getInetAddress(), getPort(), getInputStream() 等方法的。
java1.4 中增加方法 isClosed( ) 用来测试Socket是否已经关闭,但当Socket没有被链接时,此方法也返回true
另一个方法是 isConnected() 用来测试是否Socket被联接,这个方法容易引起误解,只要Socket曾经被成功联接,无论它是否被关闭,此方法都返回true, 所以测试一个Socket是否可用应该这样 boolean coonnected = soocket.isConnected() && !socket.isClosed()
方法 isBound() 用来测试Socket是否已经成功的在本机上建立链接。
Half-closed sockets
close( )方法一下子把Socket的input 和 output 都关闲了,在用的情况下是不需要这种情况的。比如http, client只是在第一次请求时需要写东西给server,在接下来的过程中就不在写了,只是接收。 所以socket提供了以下两个方法:
public void shutdownInput() throws IOException
public void shutdownOutput() throws IOException
分别用来关闭输入和输出,下面是一个http的例子。
Socket connection = null; try { connection = new Socket("www.oreilly.com", 80); Writer out = new OutputStreamWriter( connection.getOutputStream( ), "8859_1"); out.write("GET / HTTP 1.0/r/n/r/n"); out.flush( ); connection.shutdownOutput( ); // read the response... } catch (IOException ex) { } finally { try { if (connection != null) connection.close( ); } catch (IOException ex) {} }
但是要注意,即使输入和输出流都关闭了,还是要调用Socket的close() 方法的, 不然只是流被关闭了,Socket占用的资源并没有被释放。
同时也提供了以下两个方法:
public boolean isInputShutdown()
public boolean isOutputShutdown()