Rumah >Java >javaTutorial >Java网络编程由浅入深二 Socket的构造和连接服务端的相关异常 的详细介绍

Java网络编程由浅入深二 Socket的构造和连接服务端的相关异常 的详细介绍

黄舟
黄舟asal
2017-03-04 10:07:331682semak imbas

Socket构造方法和Socket的设置与异常

本文将介绍Socket的构造方法和Socket的相关属性设置与异常处理

  • 构造Socket

  • 设置等待超时时间

  • 设置服务器地址

  • 设置客户端地址

  • 客户端连接服务器可能出现的异常


构造Socket

Socket的构造方法有如下几种重载方式:

Socket();Socket(InetAddress address, int port)Socket(InetAddress address, int port, 
InetAddress localAddr, int localPort)Socket(Proxy proxy)Socket(SocketImpl impl)Socket(String host, int port)
Socket(String host, int port, InetAddress localAddr, int localPort)

除了第一个构造器外,其他构造器都会尝试与服务器建立连接,如果连接成功返回Socket对象;如果因为某些原因连接失败,就抛出IOException。
如下代码扫描主机上从1到1024之间的端口,判断这些端口是否已经被服务器程序监听。

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 i=0;i<1024;i++){            try {
                socket = new Socket(host, i);
                System.out.println("There is a server on port "+i);
            }  catch (IOException e) {
                System.out.println("Can&#39;t connect to port "+i);
            }finally{                if(socket!=null){                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

设置等待建立连接的超时时间

使用不带参数的构造方法,设置socket连接超时时间:

Socket socket = new Socket();
SocketAddress endPoint = new InetSocketAddress("localhost", 8000);socket.connect(endPoint, 60000);

以上代码表示用于连接本机上监听的8000端口,等待连接的最长时间为1分钟。如果在1分钟内连接成功,则connect()方法顺利返回;如果在1分钟之内出现异常,则抛出异常;如果超过1分钟,既没有连接成功,也没有抛出异常,那么会抛出SocketTimeoutExceptionsocket. connect(SocketAddress endpoint, int timeout);负责连接服务器,参数endpoint指定服务器地址,参数timeout设定超时时间,以毫秒为单位。如果参数timeout为0,表示永远不超时。

设置服务器地址

Socket的构造方法中,除了第一个不带参数的构造方法,其他构造方法都需要指定服务器地址,包括服务器的IP或主机名,以及端口:
Socket(InetAddress address, int port)
Socket(String host, int port)
InetAddress类表示服务器的IP地址,InetAddress提供了很多静态方法:

    // 返回本地主机的IP地址
    InetAddress.getLocalHost();    // 返回代表10.202.164.65的IP地址
    InetAddress.getByName("10.202.164.65");    // 返回域名为&#39;www.csdn.net&#39;的ip地址
    InetAddress.getByName("www.csdn.net");

设置客户端的地址:

默认情况下,客户端的IP地址来自于客户端程序所在的主机,客户端的端口则由操作系统随机分配。但是Socket类还是提供了构造方法允许显式地设置客户端的IP和端口:

//参数localAddr和localPort用来设置客户端的IP和端口。
Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
Socket(String host, int port, InetAddress localAddr, int localPort)

客户端连接服务器可能抛出的异常

当Socket构造方法请求连接服务器时,可能会抛出下面的异常:
•   UnknownHostException:如果无法识别主机的名字或IP地址,就会抛出这种异常

•   ConnectException:如果没有服务器进程监听指定的端口,或者服务器拒绝连接,就会抛出这种异常。

•   SocketTimeoutException:如果等待连接超时,就会抛出这种异常。

•   BindException:如果无法把Socket对象与指定的本地IP地址或端口绑定,就会抛出这种异常。

通过下面测试类为例,演示抛出异常的原因。

public class ConnectTester {    public static void main(String[] args) {
        String host = "www.csdn.net";        
        int port = 12312;        
        new ConnectTester().connect(host, port);
    }    public void connect(String host,int port){
        SocketAddress remoteAddress = new InetSocketAddress(host, port);
        Socket socket = null;
        String result = null;        
        try{
            socket = new Socket();            
            long start = System.currentTimeMillis();
            socket.connect(remoteAddress,1000);            
            long end = System.currentTimeMillis();
            result = (end-start)+"ms";
        }catch(BindException bindException){
            result = "BindException,Socket对象与指定的本地IP地址或端口绑定,异常";
        }catch (UnknownHostException unknownHostException) {
            result = "UnknownHostException,无法识别的主机";
        }catch (ConnectException connectException) {
            result = "ConnectException,连接被拒绝";
        }catch (SocketTimeoutException socketTimeoutException) {
            result = "SocketTimeoutException,连接超时";
        }catch(IOException e){
            result = "IOException,连接失败";
        }finally{            if(socket!=null){                
        try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println(remoteAddress+" : "+result);
    }
}

•   抛出UnknownHostException情况:
如果无法识别主机的名字或IP地址,就会抛出这种异常。例如:host为:’ somehost11’。Socket的connect方法就会抛出UnknownHostException异常。
•   抛出ConnectException的情况:
在以下两种情况会抛出ConnectException。
1)  没有服务器进程监听指定的端口。例如:host为 ‘localhost’ port为 12321 。如果本机的12321端口没有被任何进程监听,则Socket连接方法会抛出ConnectException。
2)  服务器进程拒绝连接。介绍服务器进程拒绝客户的连接请求的情形。如下示例代码,一个简单的服务程序ServerSocket构造方法中的第二个参数表示请求队列的长度。如果队列的请求已满,服务器就会拒绝其余的请求。抛出ConnectException

public class SimplServer {    public static void main(String[] args) throws Exception{
        ServerSocket serverSocket = new ServerSocket(8888, 2);
        Thread.sleep(3600000);
    }
}
public class SimpleClient {    
public static void main(String[] args) throws Exception{
        String host = "localhost";        int port = 8888;
        Socket s1 = new Socket(host, port);
        System.out.println("第一次连接成功");
        Socket s2 = new Socket(host, port);
        System.out.println("第二次连接成功");
        Socket s3 = new Socket(host, port);
        System.out.println("第三次连接成功");
    }
}

•   抛出SocketTimeoutException的情形
如果客户端连接超时,就会抛出这种异常。修改           socket.connect(remoteAddress, 1);由原来的1000毫秒修改为1毫秒,这样增加了超时的可能性。

•   抛出BindException的情形:
将代码

socket = new Socket();socket.connect(remoteAddress, 1000);

修改为:

socket = new Socket();
socket.bind(new InetSocketAddress(InetAddress.getByName("222.34.5.6"), 5678));
socket.connect(remoteAddress, 1000);

修改后的代码试图把Socket的本地IP地址设为222.34.5.6,把本地端口设置为5678。如果本机不具有该IP,或者端口被占用,那么就会出现BindException。

 以上就是Java网络编程由浅入深二 Socket的构造和连接服务端的相关异常 的详细介绍的内容,更多相关内容请关注PHP中文网(www.php.cn)!


Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn