java 中的socket_Java中Socket用法详解
一、構(gòu)造Socket
Socket的構(gòu)造方法有以下幾種重載形式:
(1)Socket()
(2)Socket(InetAddress address, int port)throws UnknownHostException,IOException
(3)Socket(InetAddress address, int port, InetAddress localAddr, int localPort)throws IOException
(4)Socket(String host, int port) throws UnknownHostException,IOException
(5)Socket(String host, int port, InetAddress localAddr, int localPort) throws IOException
各構(gòu)造方法的用法如下:
1. 設(shè)定等待建立連接的超時(shí)時(shí)間:
Socket socket=new Socket();SocketAddress remoteAddr=new InetSocketAddress(“l(fā)ocalhost”,8000);//等待建立連接的超時(shí)時(shí)間為1分鐘
socket.connect(remoteAddr, 60000);
2. 設(shè)定服務(wù)器的地址:
Socket(InetAddress address, int port)
Socket(String host, int port)
InetAddress類表示IP地址,其用法如下://返回本地主機(jī)的IP地址InetAddress addr1=InetAddress.getLocalHost();
//返回代表”222.34.5.7″的IP地址
InetAddress addr2=InetAddress.getByName(“222.34.5.7″);
//返回域名為”www.javathinker.org”的IP地址
InetAddress addr3=InetAddress.getByName(“www.javathinker.org”);
3. 設(shè)定客戶端的地址:
在一個(gè)Socket對(duì)象中,既包含遠(yuǎn)程服務(wù)器的IP地址和端口信息,也包含本地客戶端的IP地址和端口信息。默認(rèn)情況下,客戶端的IP地址來(lái)自于客戶程序所在的主機(jī),客戶端的端口則由操作系統(tǒng)隨機(jī)分配。Socket類還有兩個(gè)構(gòu)造方法允許顯式的設(shè)置客戶端的IP地址和端口:
Socket(InetAddress address, int port, InetAddress localAddr, int localPort)throws IOExceptionSocket(String host, int port, InetAddress localAddr, int localPort) throws IOException
4. 客戶連接服務(wù)器時(shí)可能拋出的異常:
當(dāng)Socket的構(gòu)造方法請(qǐng)求連接服務(wù)器時(shí),可能會(huì)拋出以下異常:
l UnknownHostException:如果無(wú)法識(shí)別主機(jī)的名字或IP地址,就會(huì)拋出這種異常。
l ConnectException:如果沒(méi)有服務(wù)器進(jìn)程監(jiān)聽(tīng)指定的端口,或者服務(wù)器進(jìn)程拒絕連接,就會(huì)拋出這種異常。
l SocketTimeoutException:如果等待連接超時(shí),就會(huì)拋出這種異常。
l BindException:如果無(wú)法把Socket對(duì)象與指定的本地IP地址或端口綁定,就會(huì)拋出這種異常。
二、獲取Socket的信息
以下方法用于獲取Socket的有關(guān)信息:
l getInetAddress():獲得遠(yuǎn)程服務(wù)器的IP地址。
l getPort():獲得遠(yuǎn)程服務(wù)器的端口。
l getLocalAddress():獲得客戶本地的IP地址。
l getLocalPort():獲得客戶本地的端口。
l getInputStream():獲得輸入流。如果Socket還沒(méi)有連接,或者已經(jīng)關(guān)閉,或者已經(jīng)通過(guò)shutdownInput()方法關(guān)閉輸入流,那么此方法會(huì)拋出IOException。
l getOutputStream():獲得輸出流。如果Socket還沒(méi)有連接,或者已經(jīng)關(guān)閉,或者已經(jīng)通過(guò)shutdownOutput()方法關(guān)閉輸出流,那么此方法會(huì)拋出IOException。
三、關(guān)閉Socket
1. 當(dāng)客戶與服務(wù)器的通信結(jié)束,應(yīng)該及時(shí)關(guān)閉Socket,以釋放Socket占用的包括端口在內(nèi)的各種資源。Socket的close()方法負(fù)責(zé)關(guān)閉Socket。推薦代碼如下:
Socket socket=null;try{socket=newSocket(“www.javathinker.org”,80);
//執(zhí)行接收和發(fā)送數(shù)據(jù)的操作
…
}catch(IOException e){
e.printStackTrace();
}finally{
try{
if(socket!=null)socket.close();
}catch(IOException e){e.printStackTrace();}
}
2. Socket類提供了三個(gè)狀態(tài)測(cè)試方法:
l isClosed()
l isConnected()
l isBound()
3. 如果要判斷一個(gè)Socket對(duì)象當(dāng)前是否處于連接狀態(tài),可采用以下方式:
boolean isConnected=socket.isConnected() && !socket.isClosed();
四、半關(guān)閉Socket
1. 有的時(shí)候,可能僅僅希望關(guān)閉輸出流或輸入流之一。此時(shí)可以采用Socket類提供的半關(guān)閉方法:
l shutdownInput():關(guān)閉輸入流。
l shutdownOutput(): 關(guān)閉輸出流。
2. 先后調(diào)用Socket的shutdownInput()和shutdownOutput()方法,僅僅關(guān)閉了輸入流和輸出流,并不等價(jià)于調(diào)用Socket的close()方法。在通信結(jié)束后,仍然要調(diào)用Socket的close()方法,因?yàn)橹挥性摲椒ú艜?huì)釋放Socket占用的資源,比如占用的本地端口等。
3. Socket類還提供了兩個(gè)狀態(tài)測(cè)試方法,用來(lái)判斷輸入流和輸出流是否關(guān)閉:
l public boolean isInputShutdown()
l public boolean isOutputShutdown()
五、設(shè)置Socket的選項(xiàng)
Socket有以下幾個(gè)選項(xiàng):
n TCP_NODELAY:表示立即發(fā)送數(shù)據(jù)。
n SO_RESUSEADDR:表示是否允許重用Socket所綁定的本地地址。
n SO_TIMEOUT:表示接收數(shù)據(jù)時(shí)的等待超時(shí)時(shí)間。
n SO_LINGER:表示當(dāng)執(zhí)行Socket的close()方法時(shí),是否立即關(guān)閉底層的Socket。
n SO_SNFBUF:表示發(fā)送數(shù)據(jù)的緩沖區(qū)的大小。
n SO_RCVBUF:表示接收數(shù)據(jù)的緩沖區(qū)的大小。
n SO_KEEPALIVE:表示對(duì)于長(zhǎng)時(shí)間處于空閑狀態(tài)的Socket,是否要自動(dòng)把它關(guān)閉。
n OOBINLINE:表示是否支持發(fā)送一個(gè)字節(jié)的TCP緊急數(shù)據(jù)。
1. TCP_NODELAY選項(xiàng)
1) 設(shè)置該選項(xiàng):public void setTcpNoDelay(boolean on) throws SocketException
2) 讀取該選項(xiàng):public boolean getTcpNoDelay() throws SocketException
3) TCP_NODEALY的默認(rèn)值為false,表示采用Negale算法。如果調(diào)用setTcpNoDelay(true)方法,就會(huì)關(guān)閉Socket的緩沖,確保數(shù)據(jù)及時(shí)發(fā)送:
if(!socket.getTcpNoDelay()) socket.setTcpNoDelay(true);
4) 如果Socket的底層實(shí)現(xiàn)不支持TCP_NODELAY選項(xiàng),那么getTcpNoDelay()和setTcpNoDelay()方法會(huì)拋出SocketException。
2. SO_RESUSEADDR選項(xiàng)
1) 設(shè)置該選項(xiàng):public void setResuseAddress(boolean on) throws SocketException
2) 讀取該選項(xiàng):public boolean getResuseAddress() throws SocketException
3) 為了確保一個(gè)進(jìn)程關(guān)閉了Socket后,即使它還沒(méi)釋放端口,同一個(gè)主機(jī)上的其他進(jìn)程還可以立刻重用該端口,可以調(diào)用Socket的setResuseAddress(true)方法:
if(!socket.getResuseAddress()) socket.setResuseAddress(true);
4) 值得注意的是socket.setResuseAddress(true)方法必須在Socket還沒(méi)有綁定到一個(gè)本地端口之前調(diào)用,否則執(zhí)行socket.setResuseAddress(true)方法無(wú)效。因此必須按照以下方式創(chuàng)建Socket對(duì)象,然后再連接遠(yuǎn)程服務(wù)器:
Socket socket = newSocket(); //此時(shí)Socket對(duì)象未綁定到本地端口,并且未連接遠(yuǎn)程服務(wù)器socket.setResuseAddress(true);SocketAddress remoteAddr = newInetSocketAddress(“remotehost”,8000);
socket.connect(remoteAddr);//連接遠(yuǎn)程服務(wù)器,并且綁定匿名的本地端口
或者:
Socket socket = newSocket(); //此時(shí)Socket對(duì)象未綁定到本地端口,并且未連接遠(yuǎn)程服務(wù)器
socket.setResuseAddress(true);
SocketAddress localAddr = newInetSocketAddress(“l(fā)ocalhost”,9000);
SocketAddress remoteAddr = newInetSocketAddress(“remotehost”,8000);
socket.bind(localAddr); //與本地端口綁定
socket.connect(remoteAddr); //連接遠(yuǎn)程服務(wù)器,并且綁定匿名的本地端口
3. SO_TIMEOUT選項(xiàng)
1) 設(shè)置該選項(xiàng):public void setSoTimeout(int milliseconds) throws SocketException
2) 讀取該選項(xiàng):public int getSoTimeOut() throws SocketException
3) 當(dāng)通過(guò)Socket的輸入流讀數(shù)據(jù)時(shí),如果還沒(méi)有數(shù)據(jù),就會(huì)等待。Socket類的SO_TIMEOUT選項(xiàng)用于設(shè)定接收數(shù)據(jù)的等待超時(shí)時(shí)間,單位為毫秒,它的默認(rèn)值為0,表示會(huì)無(wú)限等待,永遠(yuǎn)不會(huì)超時(shí)。
4) Socket的setSoTimeout()方法必須在接收數(shù)據(jù)之前執(zhí)行才有效。此外,當(dāng)輸入流的read()方法拋出SocketTimeoutException后,Socket仍然是連接的,可以嘗試再次讀取數(shù)據(jù)。
4. SO_LINGER選項(xiàng)
1) 設(shè)置該選項(xiàng):public void setSoLinger(boolean on, int seconds) throws SocketException
2) 讀取該選項(xiàng):public int getSoLinger() throws SocketException
3) SO_LINGER選項(xiàng)用來(lái)控制Socket關(guān)閉時(shí)的行為。
l socket.setSoLinger(true,0):執(zhí)行Socket的close()方法時(shí),該方法也會(huì)立即返回,但底層的Socket也會(huì)立即關(guān)閉,所有未發(fā)送完的剩余數(shù)據(jù)被丟棄。
l socket.setSoLinger(true,3600):執(zhí)行Socket的close()方法時(shí),該方法不會(huì)立即返回,而進(jìn)入阻塞狀態(tài),同時(shí),底層的Socket會(huì)嘗試發(fā)送剩余的數(shù)據(jù)。只有滿足以下兩個(gè)條件之一,close()方法才返回:
n 底層的Socket已經(jīng)發(fā)送完所有的剩余數(shù)據(jù)。
n 盡管底層的Socket還沒(méi)有發(fā)送完所有的剩余數(shù)據(jù),但已經(jīng)阻塞了3600秒。close()方法的阻塞時(shí)間超過(guò)3600秒,也會(huì)返回,剩余未發(fā)送的數(shù)據(jù)被丟棄。
以上兩種情況內(nèi),當(dāng)close()方法返回后,底層的Socket會(huì)被關(guān)閉,斷開(kāi)連接。
4) setSoLinger(boolean on ,int second)方法中的seconds參數(shù)以秒為單位,而不是以毫秒為單位。
5. SO_RCVBUF選項(xiàng)
1) 設(shè)置該選項(xiàng):public void setReceiveBufferSize(int size) throws SocketException
2) 讀取該選項(xiàng):public int getReceiveBufferSize() throws SocketException
3) SO_RCVBUF表示Socket的用于輸入數(shù)據(jù)的緩沖區(qū)的大小。
4) 如果底層Socket不支持SO_RCVBUF選項(xiàng),那么setReceiveBufferSize()方法會(huì)拋出SocketException。
總結(jié)
以上是生活随笔為你收集整理的java 中的socket_Java中Socket用法详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 台达变频器485通讯接线图_台达变频器基
- 下一篇: 空心字母金字塔(Java)