1. 构造Socket
(1).Socket()
(2).Socket(InetAddress address, int port)
(3).Socket(InetAddress address, int port, InetAddress localAdd, int localPort)
(4).Socket(String host, int port)
(5).Socket(String host, int port, InetAddress localAdd, int localPort)
除了第一个不带参数的构造方法外,其他构造方法都会试图连接服务器,如果连接成功,返回Socket对象,否则抛出IOException。
1.1 设定等待连接的超时时间
当客户端与服务器连接时,可能会等待一段时间。默认情况下,Socket的构造方法会一直等待下去,直到连接成功或者抛出异常。那该如何限定等待时间呢?此时就应该利用第一个无参的构造方法
Socket socket = new Socket();
SocketAddress address = new InetSocketAddress("localhost",1700);
socket.connect(address, 60000); //单位是毫秒,等待时间为1min
Socket类的connect(SocketAddress endpoint, int timeout)负责连接服务器,参数endpoint指定服务器的地址,参数timeout指定超时的时间,以毫秒为单位,如果设为0,则永远不会超时。
1.2 设定服务器的地址
InetAddress类表示服务器的IP地址,提供了一系列的静态工厂方法,用于构造自身的实例。
//返回本地主机的IP地址
InetAddress address1 = InetAddress.getLocalHost();
//返回代表222.34.5.7的IP地址
InetAddress address2 = InetAddress.getByName("222.34.5.7");
//返回域名为"www.javathinker.org"的IP地址
InetAddress address3 = InetAddress.getByName("www.javathinker.org");
1.3 设定客户端的地址
如果一个主机同时拥有两个以上的网络,那么就有可能拥有两个以上的IP地址,如一个主机在Internet网络中的IP地址是“222.67.1.34”,而在一个局域网中的IP地址是“112.5.4.3”.假定这个主机的客户程序希望和同一个局域网上的一个服务器程序(假设地址为112.5.4.45 : 1700)通信,可以按照如下方式构造Socket对象:
InetAddress remoteAddr = InetAddress.getByName("112.5.4.45");
InetAddress localAddr = InetAddress.getByName("112.5.4.3");
Socket socket = new Socket(remoteAddr, 1700, localAddr, 1234); //假设客户端使用的端口是1234
1.4 连接服务器时可能抛出的异常
当Socket的构造方法请求连接服务器时,可能抛出如下的异常:
(1)、UnknownHostException:如果无法识别主机的名字或IP地址,就会抛出此异常
(2)、ConnectException:如果服务器进程监听指定的端口,或者服务器进程拒绝连接,就会抛出此异常
(3)、SocketTimeoutException:如果等待连接超时,就会抛出此异常
(4)、BindException:如果无法把Socket对象与 指定的本地IP地址或端口绑定,就会抛出此异常
以下通过例子来演示:
public class ConnectTester {
public void connect(String host,int port){
SocketAddress address = new InetSocketAddress(host, port);
Socket socket = null;
String result = null;
try{
long beginTime = System.currentTimeMillis(); //开始时间
socket = new Socket();
socket.connect(address, 1000); //超时1秒
long endTime = System.currentTimeMillis(); //结束时间
result = (endTime-beginTime) + "毫秒";
}catch(BindException b){
result = "socket无法与指定的本地IP地址或端口绑定";
}catch(UnknownHostException u){
result = "无法识别主机的名字或IP地址";
}catch(ConnectException c){
result = "服务器拒绝连接";
}catch(SocketTimeoutException s){
result = "连接超时";
}catch(IOException e){
result = "不知原因";
}
if(socket!=null)
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(result);
}
public static void main(String[] args){
String host;
int port;
Scanner in = new Scanner(System.in);
host = in.nextLine();
port = in.nextInt();
ConnectTester t = new ConnectTester();
t.connect(host, port);
}
}
运行程序然后输入:
www.javathinker.org
80
a. 抛出UnknownHostException的情况:
在控制台输入
somehost
80
如果不存在名为"somehost"的主机,Socket的构造方法就会抛出UnknownHostException。
b. 抛出ConnectException的情况
分两种情况
(1)、没有服务器进程指定的端口。
在控制台输入
localhost
1700
如果本地主机的1700端口没有被任何服务器进程监听,Socket构造方法就会抛出ConnectException
(2)、服务器进程拒绝连接
ServerSocket(int port, int backlog)构造方法的第二个参数backlog,设定服务器请求连接的队列长度,如果请求连接已满,服务器就会拒绝其余的连接请求
服务器类:
public class SimpleServer {
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
//连接请求的队列长度为2
ServerSocket server = new ServerSocket(1700, 2);
Thread.sleep(6000); //睡眠1分钟
}
}
客户端类
public class SimpleClient {
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
for(int i=1;i<5;i++){
Socket socket = new Socket("localhost", 1700);
System.out.println("第"+i+"次连接成功");
}
}
}
先运行服务器类,再启动客户端类,可以在控制台看到
由于1700端口在之前可能已经打开过,这里再启动服务器的话有可能出错,所以没有得到上述结果的小伙伴请自行换个端口尝试,例如1701
其他异常情形可自己尝试更改数据进行测试。