2.1 构造Socket
Socket构造方法如下:
1 Socket() 2 //Creates an unconnected socket, with the system-default type of SocketImpl. 3 4 Socket(InetAddress address, int port) 5 //Creates a stream socket and connects it to the specified port number at the 6 //specified IP address. 7 8 Socket(InetAddress host, int port, boolean stream) 9 //Deprecated. 10 //Use DatagramSocket instead for UDP transport. 11 12 Socket(InetAddress address, int port, InetAddress localAddr, int localPort) 13 //Creates a socket and connects it to the specified remote address on the 14 //specified remote port. 15 16 Socket(Proxy proxy) 17 //Creates an unconnected socket, specifying the type of proxy, if any, that 18 //should be used regardless of any other settings. 19 20 Socket(SocketImpl impl) 21 //Creates an unconnected Socket with a user-specified SocketImpl. 22 23 Socket(String host, int port) 24 //Creates a stream socket and connects it to the specified port number on the 25 named host. 26 27 Socket(String host, int port, boolean stream) 28 //Deprecated. 29 //Use DatagramSocket instead for UDP transport. 30 31 Socket(String host, int port, InetAddress localAddr, int localPort) 32 //Creates a socket and connects it to the specified remote host on the specified 33 //remote port.
除了第一个无参,其余构造方法都试图建立与服务器的连接,如果成功则返回Socket对象,否在抛出异常。
根据以上构造方法来创建一个类,用于扫描主机上1-1024之间的端口是否被服务器程序监听(如果被监听,就可以返回Socket对象)。代码如下:
import java.io.IOException; import java.net.Socket; public class PortScanner { public static void main(String[] args) { String host="localhost"; new PortScanner().scan(host); } public void scan(String host){ Socket socket=null; for(int port=1;port<=1024;port++){ try{ socket=new Socket(host,port); System.out.println("There is a server on port "+port); }catch(IOException e){ System.out.println("Can‘t connect to port "+port); }finally{ if(socket!=null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } } }
2.1.1 设定等待建立连接的超时时间
当需要设定连接超时时间时,则需要调用Socket的无参构造函数。
Socket socket = new Socket(); //SocketAddress 提供不可变对象,供套接字用于绑定、连接或用作返回值。 SocketAddress remoteAddr = new InetSocketAddress("localhost",8000); //超时未连接时,会抛出超时异常。 socket.connect(remoteAddr,60000);//毫秒为单位,0表示用于不超时
2.1.2 设定服务器地址
除了第一个无参构造函数,其余都需要提供服务器IP或主机名,以及端口号。
1 Socket(InetAddress address,int port) //第一个参数表示主机IP地址 2 Socket(String host,int port) //第一个表示主机名
InetAddress类表示服务器的IP地址,详情查看这里。
2.1.3 设定客户端地址
一个socket对象应该包含远程服务器的IP和端口信息,也包含本地客户机的IP地址和端口信息。默认情况下,客户机的IP来自于本地主机,端口有操作系统自动分配。也可以显式的设置客户端的IP和端口。
Socket(InetAddress address,int port,InetAddress localAddress,int localPort) Socket(String host,int port,int port,InetAddress localAddress,int localPort)
2.1.4 客户机连接服务器可能出现的异常
UnKnownHostException | 无法识别主机的名字或IP地址 |
ConnectException | 服务器没有对应的端口或服务器拒绝连接 |
SocketTimeoutException | 等待连接超时 |
BindException | 无法与指定的本地IP或端口绑定 |
2.2 获取Socket信息
以下方法可获得Socket相关信息:
1 InetAddress getInetAddress() 2 //Returns the address to which the socket is connected. 3 4 InputStream getInputStream() 5 //Returns an input stream for this socket. 6 7 OutputStream getOutputStream() 8 //Returns an output stream for this socket. 9 10 int getPort() 11 //Returns the remote port number to which this socket is connected. 12 13 InetAddress getLocalAddress() 14 //Gets the local address to which the socket is bound. 15 16 int getLocalPort() 17 //Returns the local port number to which this socket is bound.
2.3关闭Socket
部分代码如下:
if(socket!=null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } }}
Socket提供了3个状态测试方法:
boolean isBound() //Returns the binding state of the socket. boolean isClosed() //Returns the closed state of the socket. boolean isConnected() //Returns the connection state of the socket.
2.4 半关闭Socket
进程A与进程B通信时,A传输数据到B,如何告知B所有数据已经传输完毕呢?以下几个方法:
(1) 发送一行特殊的字符串,如前一章使用的“bye”,告知输出完毕。
(2) A先告诉B字符串的长度,在向B传输数据。
(3) A发送完成后,关闭Socket。此时B读完数据后,在此执行read()时,该方法返回-1,如果执行BufferedReader的readLine()方法,则返回null。以此表示到达输入流末尾。
(4) 关闭Socket的输入输出流
shutdownInput():关闭输入流
shutdownOutput():关闭输出流
对应两个状态测试方法:
isInputShutdown()
isOutputShutdown()