使用java.NET.ServerSocket能夠方便的創(chuàng)建一個服務(wù)端套接字,這個類的構(gòu)造函數(shù)有一個參數(shù)backlog。下面這段代碼,在本機(jī)的8888端口上建立了一個套接字,backlog設(shè)置為5。
[java] view plain copy// port:8888,backlog:5 ServerSocket server = new ServerSocket(8888, 5); 下面的Client是我們的測試類,會創(chuàng)建30個socket連接。[java] view plain copyimport java.net.Socket; public class Client { PRivate static Socket[] clients = new Socket[30]; public static void main(String[] args) throws Exception { for (int i = 1; i <= 30; i++) { clients[i-1] = new Socket("127.0.0.1", 8888); System.out.println("client connection:" + i); } } } 如果沒有啟動服務(wù)端套接字,那么直接運(yùn)行Client會報錯誤:Connection refused: connect。[plain] view plain copyException in thread "main" java.net.ConnectException: Connection refused: connect at java.net.DualStackPlainSocketImpl.connect0(Native Method) at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182) at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:579) at java.net.Socket.connect(Socket.java:528) at java.net.Socket.<init>(Socket.java:425) at java.net.Socket.<init>(Socket.java:208) 接下來我們啟動Server端套接字,但是不調(diào)用accept()方法,也就是說不處理客戶端的socket連接。[java] view plain copyimport java.net.ServerSocket; public class Server { public static void main(String[] args) throws Exception{ // port:8888,backlog:5 ServerSocket server = new ServerSocket(8888, 5); while(true) { } } } 運(yùn)行Client測試類,運(yùn)行結(jié)果見下圖:
可以看到:測試類Client中,前面5個客戶端Socket創(chuàng)建是成功的,后面再創(chuàng)建Scoket就會報錯。能夠成功創(chuàng)建客戶端套接字的個數(shù),剛好就是創(chuàng)建ServerSocket時候指定的backlog。
下面這段代碼,ServerSocket正常處理客戶端socket的連接請求。
[java] view plain copyimport java.net.ServerSocket; import java.net.Socket; public class Server { public static void main(String[] args) throws Exception{ // port:8888,backlog:5 ServerSocket server = new ServerSocket(8888, 5); int acceptCount = 0; while(true) { Socket client = server.accept(); acceptCount++; System.out.println("new connection has connected, num=" + acceptCount); } } } 運(yùn)行測試類Client,服務(wù)端和客戶端的運(yùn)行結(jié)果如下:沒有任何異常產(chǎn)生。

下面我們再修改下服務(wù)端代碼,處理每個客戶端連接需要花費(fèi)2s,我們用線程睡眠來模擬。
[java] view plain copyimport java.net.ServerSocket; import java.net.Socket; public class Server { public static void main(String[] args) throws Exception{ // port:8888,backlog:5 ServerSocket server = new ServerSocket(8888, 5); int acceptCount = 0; while(true) { Socket client = server.accept(); acceptCount++; System.out.println("new connection has connected, num=" + acceptCount); Thread.sleep(2 * 1000); } } } 運(yùn)行測試類Client,服務(wù)端和客戶端運(yùn)行結(jié)果如下:

總結(jié)一下:
服務(wù)端socket處理客戶端socket連接是需要一定時間的。ServerSocket有一個隊(duì)列,存放還沒有來得及處理的客戶端Socket,這個隊(duì)列的容量就是backlog的含義。如果隊(duì)列已經(jīng)被客戶端socket占滿了,如果還有新的連接過來,那么ServerSocket會拒絕新的連接。也就是說backlog提供了容量限制功能,避免太多的客戶端socket占用太多服務(wù)器資源。
客戶端每次創(chuàng)建一個Socket對象,服務(wù)端的隊(duì)列長度就會增加1個。
[java] view plain copynew Socket("127.0.0.1", 8888); 服務(wù)端每次accept(),就會從隊(duì)列中取出一個元素。[java] view plain copySocket client = server.accept();新聞熱點(diǎn)
疑難解答