一:服務(wù)端 ServerSocket
- ServerSocket包含一個(gè)監(jiān)聽來自客戶端連接請(qǐng)求的方法:
accept();
如果服務(wù)端接收到一個(gè)客戶端的Socket連接請(qǐng)求虚汛,會(huì)返回一個(gè)與客戶端Socket對(duì)應(yīng)的服務(wù)端Socket匾浪,否則該方法一直處于等待狀態(tài),線程阻塞卷哩。
ServerSocket類提供如下構(gòu)造器:
ServerSocket(int port);
使用指定端口來創(chuàng)建蛋辈,port范圍:0-65535。注意将谊,在選擇端口時(shí)冷溶,必須小心。每一個(gè)端口提供一種特定的服務(wù)尊浓,只有給出正確的端口逞频,才能獲得相應(yīng)的服務(wù)。0~1023的端口號(hào)為系統(tǒng)所保留
栋齿,例如http服務(wù)的端口號(hào)為80,telnet服務(wù)的端口號(hào)為21,ftp服務(wù)的端口號(hào)為23, 所以我們?cè)谶x擇端口號(hào)時(shí)苗胀,最好選擇一個(gè)大于1023的數(shù)以防止發(fā)生沖突。ServerSocket(int port, int backlog);
增加一個(gè)用來改變連接隊(duì)列長(zhǎng)度的參數(shù)backlog瓦堵。ServerSocket(int port, int backlog, InetAddress bindAddr);
在機(jī)器存在多個(gè)IP地址的情況下基协,bindAddr參數(shù)指定將ServerSocket綁定到指定IP。
當(dāng)ServerSocket使用完畢菇用,應(yīng)使用close()
方法來關(guān)閉此ServerSocket澜驮。通常情況下,服務(wù)器不應(yīng)該只接收一個(gè)客戶端請(qǐng)求惋鸥,而應(yīng)該不斷接收來自客戶端的請(qǐng)求泉唁,所以程序可以通過循環(huán)鹅龄,不斷調(diào)用ServerSocket的accept方法:
while (true) {
Socket socket = serverSocket.accept();//阻塞
....
}
二:客戶端 Socket
Socket 常用構(gòu)造器
Socket(InetAddress/String remoteAddress, int port);
創(chuàng)建連接到指定遠(yuǎn)程主機(jī)、遠(yuǎn)程端口的Socket亭畜,本地IP地址和端口使用默認(rèn)值。Socket(InetAddress/String remoteAddress, int port, InetAddress localAddr, int localPort);
綁定本地IP地址和端口迎卤,適用于本地主機(jī)有多個(gè)IP地址的情形拴鸵。
注:上面兩個(gè)構(gòu)造器指定遠(yuǎn)程主機(jī)時(shí)既可以使用InetAddress來指定,也可以直接使用String對(duì)象來指定遠(yuǎn)程IP蜗搔。本地主機(jī)只有一個(gè)IP地址時(shí)劲藐,使用第一個(gè)方法更簡(jiǎn)單。
三樟凄、心跳機(jī)制
在與服務(wù)器進(jìn)行通訊的時(shí)候聘芜,無法判斷遠(yuǎn)程的服務(wù)器是否斷開連接。如果使用OutputStream
發(fā)送數(shù)據(jù)則會(huì)影響正常的數(shù)據(jù)發(fā)送(無法區(qū)分)缝龄。所以就引入了一個(gè)心跳機(jī)制汰现。
心跳機(jī)制實(shí)現(xiàn),使用Socket.sendUrgentData()方法發(fā)送一個(gè)字節(jié)流數(shù)據(jù)(緊急數(shù)據(jù))叔壤∠顾牵可以通過判斷服務(wù)端的OOBINLINE屬性是否打開,來確定是否斷開連接炼绘;
當(dāng)設(shè)置OOBINLINE選項(xiàng)時(shí)嗅战,套接字上接收到的任何TCP緊急數(shù)據(jù)將通過套接字輸入流接收。當(dāng)該選項(xiàng)被禁用時(shí)(這是默認(rèn)設(shè)置)俺亮,緊急數(shù)據(jù)將被靜默丟棄驮捍。
setSoTimeout()理解:設(shè)置超時(shí)時(shí)間;例如:設(shè)置為2s脚曾,如果阻塞的時(shí)間>2s 东且,那么就會(huì)報(bào)錯(cuò)。
[SO_TIMEOUT] 使用指定的超時(shí)啟用/禁用斟珊,以毫秒為單位苇倡。如果將此選項(xiàng)設(shè)置為非零超時(shí),則與此Socket關(guān)聯(lián)的InputStream上的read()調(diào)用將僅阻塞這段時(shí)間囤踩。如果超時(shí)過期旨椒,則會(huì)引發(fā)java.net.SocketTimeoutException,但Socket仍然有效堵漱。該選項(xiàng)必須在進(jìn)入阻止操作生效之前啟用综慎。超時(shí)必須是
> 0
。超時(shí)為零被解釋為無限超時(shí)勤庐。