Java網絡編程從入門到精通(14):多種多樣的建立網絡連接的方式 – JAVA編程語言程序開發技術文章

在上一篇文章中我們討論瞭Socket類的基本用法,並給出的例子中使用Socket類連接服務器時使用瞭一種最簡單的連接方式,也就是通過IP和端口號來連接服務器。而為瞭使連接服務器的方式更靈活,Socket類不僅可以通過自身的構造方法連接服務器,而且也可以通過connect方法來連接數據庫。


一、通過構造方法連接服務器


    我們可以通過6個重載構造函數以不同的方式來連接服務器。這6個重載的構造函數可以分為兩類:


1. 自動選擇IP


    這種方式是最常用的。所謂自動選擇IP,是指當本機有多塊網卡或者在一個網卡上綁定瞭多個IP時,Socket類會自動為我們選擇一個可用的IP。在上述6個構造方法中有4個是使用這種方法來連接服務器的。



<!–[if !supportLists]–>(1)    <!–[endif]–>public Socket(String host, int port)


這是最常用的構造方法,在前面的例子中就是使用的這個構造方法。在使用時隻需要提供一個字符串類型的IP或域名以及一個整型的端口號即可。在這個構造方法中可能會拋出兩個錯誤:UnknownHostException和IOException。發生第一個錯誤的原因是我們提供的host並不存在或不合法,而其它的錯誤被歸為IO錯誤。因此,這個構造方法的完整定義是:


public Socket(String host, int port) throws UnknownHostException, IOException


(2) public Socket(InetAddress inetaddress, int port)


這個構造方法和第一種構造方法類似,隻是將字符串形式的host改為InetAddress對象類型瞭。在這個構造方法中之所以要使用InetAddress類主要是因為考慮到在程序中可能需要使用Socket類多次連接同一個IP或域名,這樣使用InetAddress類的效率比較高。另外,在使用字符串類型的host連接服務器時,可能會發生兩個錯誤,但使用InetAddress對象來描述host,隻會發生IOException錯誤,這是因為當你將IP或域名傳給InetAddress時,InetAddress會自動檢查這個IP或域名,如果這個IP或域名無效,那麼InetAddress就會拋出UnknownHostException錯誤,而不會由Socket類的構造方法拋出。因此,這個構造方法的完整定義是:



public Socket(InetAddress inetaddress, int port) throws IOException


(3) public Socket(String host, int port, boolean stream)


這個構造方法和第一種構造方法差不多,隻是多瞭一個boolean類型的stream參數。如果這個stream為true,那麼這個構造方法和第一種構造方法完全一樣。如果stream為false,則使用UDP協議建立一個UDP連接(UDP將在下面的章節詳細討論,在這裡隻要知道它和TCP最大的區別是UDP是面向無連接的,而TCP是面向有連接的),也許是當初Sun的開發人員在編寫Socket類時還未考慮編寫處理UDP連接的DatagramSocket類,所以才將建立UDP連接的功能加入到Socket類中,不過Sun在後來的JDK中加入瞭DatagramSocket類,所以,這個構造方法就沒什麼用瞭,因此,Sun將其設為瞭Deprecated標記,也就是說,這個構造方法在以後的JDK版本中可以會被刪除。其於以上原因,在使用Java編寫網絡程序時,盡量不要使用這個構造方法來建立UDP連接。


 


(4) public Socket(InetAddress inetaddress, int port, boolean flag)


這個構造方法和第三種構造方法的flag標記的含義一樣,也是不建議使用的。


    下面的代碼演示上述4種構造方法的使用:



package mysocket;


import java.net.*;
import java.io.*;


public class MoreConnection
{
    private static void closeSocket(Socket socket)
    {
        if (socket != null)
            try
            {
                socket.close();
            }
            catch (Exception e) { }
    }


    public static void main(String[] args)
    {
        Socket socket1 = null, socket2 = null, socket3 = null, socket4 = null;
        try
        {
            // 如果將www.ptpress.com.cn改成其它不存在的域名,將拋出UnknownHostException錯誤
            // 測試public Socket(String host, int port)
            socket1 = new Socket(“www.ptpress.com.cn”, 80);
            System.out.println(“socket1連接成功!”);
            // 測試public Socket(InetAddress inetaddress, int port)
            socket2 = new Socket(InetAddress.getByName(“www.ptpress.com.cn”), 80);
            System.out.println(“socket2連接成功!”);


            // 下面的兩種建立連接的方式並不建議使用
            // 測試public Socket(String host, int port, boolean stream)
            socket3 = new Socket(“www.ptpress.com.cn”, 80, false);
            System.out.println(“socket3連接成功!”);
            // 測試public Socket(InetAddress inetaddress, int i, boolean flag)
            socket4 = new Socket(InetAddress.getByName(“www.ptpress.com.cn”), 80, false);
            System.out.println(“socket4連接成功!”);
        }
        catch (UnknownHostException e)
        {
            System.out.println(“UnknownHostException 被拋出!”);
        }
        catch (IOException e)
        {
            System.out.println(“IOException 被拋出!”);
        }
        finally
        {
            closeSocket(socket1);
            closeSocket(socket2);
            closeSocket(socket3);
            closeSocket(socket4);
        }
    }
}



在上面代碼中的最後通過finally關閉瞭被打開的Socket連接,這是一個好習慣。因為隻有在將關閉Socket連接的代碼寫在finally裡,無論是否出錯,都會執行這些代碼。但要註意,在關閉Socket連接之前,必須檢查Socket對象是否為null,這是因為錯誤很可能在建立連接時發生,這樣Socket對象就沒有建立成功,也就用不著關閉瞭。



1.       手動綁定IP


當本機有多個IP時(這些IP可能是多塊網卡上的,也可能是一塊網卡上綁定的多個IP),在連接服務器時需要由客戶端確定需要使用哪個IP。這樣就必須使用Socket類的另外兩個構方法來處理。下面讓我們來看看這兩個構造方法是如何來使用特定的IP來連接服務器的。


public Socket(String host, int port, InetAddress inetaddress, int localPort)


這個構造方法的參數分為兩部分,第一部分為前兩個參數:host和port,它們分別表示要連接的服務器的IP和端口號。第二部分為後兩個參數:inetaddress和localPort。其中inetaddress則表示要使用的本地的IP,而localPort則表示要綁定的本地端口號。這個localPort這以設置為本機的任何未被綁定的端口號。如果將localPort的值設為0,jav

發佈留言