亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

java必知必會之ServerSocket

chinafgj / 1587人閱讀

摘要:單個請求范圍之外的異??赡軙P(guān)閉服務(wù)器??蛻舳丝赡艹瑫r或崩潰,用戶可能取消事務(wù),網(wǎng)絡(luò)可能在流量高峰期間癱瘓,黑客可能發(fā)動拒絕服務(wù)攻擊。如果默認長度不夠大,一些的構(gòu)造函數(shù)還允許改變這個隊列的長度,不能不能超過操作系統(tǒng)支持的最大值。

ServerSocket的生命周期

一個ServerSocket的基本生命周期:
1)使用一個ServerSocket構(gòu)造函數(shù)在一個特定端口創(chuàng)建一個新的ServerSocket
2)ServerSocket使用accept方法監(jiān)聽這個端口的入站連接,accept方法會一直阻塞,直到一個客戶端嘗試建立連接,此時accept將返回一個連接客戶端和服務(wù)器的Socket對象
3)根據(jù)服務(wù)器類型,會調(diào)用Socket的getInputSteam或getOutputStream方法,或者兩個方法都調(diào)用,以獲取與客戶端通信的輸入和輸出流
4)服務(wù)器和客戶端根據(jù)已協(xié)商的協(xié)議交互,直到要關(guān)閉連接
5)服務(wù)器或客戶端(或二者)關(guān)閉連接
6)服務(wù)器返回到步驟2,等待下一次連接

異常

有兩類異常,一類異??赡荜P(guān)閉服務(wù)器并記錄一個錯誤信息,另一類異常只關(guān)閉活動連接,區(qū)分這兩類異常非常重要。某個特性連接范圍內(nèi)的異常會關(guān)閉這個連接,但是不會影響其他異?;蛘哧P(guān)閉服務(wù)器。

單個請求范圍之外的異??赡軙P(guān)閉服務(wù)器。

結(jié)束處理時,一定要關(guān)閉Socket,客戶端不能依賴連接的另一端關(guān)閉Socket,對于服務(wù)器尤其如此??蛻舳丝赡艹瑫r或崩潰,用戶可能取消事務(wù),網(wǎng)絡(luò)可能在流量高峰期間癱瘓,黑客可能發(fā)動拒絕服務(wù)攻擊。出于諸如此類的眾多原因,你不能依賴于客戶端關(guān)閉Socket,即使協(xié)議有這個要求也不能完全相信客戶端一定會關(guān)閉Socket。

請求隊列

操作系統(tǒng)把指向某個特定端口的入站連接請求存儲在一個先進先出的隊列中,默認地,Java將這個隊列的長度設(shè)置為50,但不同的操作系統(tǒng)會有所不同。FreeBSD默認最大隊列長度為128。在這些系統(tǒng)中,Java服務(wù)器socket的隊列長度將是操作系統(tǒng)所允許的最大值(小于等于50)。隊列中填入的未處理連接達到最大容量時,主機會拒絕這個端口上額外的連接,直到隊列騰出新的位置出來為止。很多客戶端在首次連接被拒絕后還會多次嘗試建立連接。

如果默認長度不夠大,一些ServerSocket的構(gòu)造函數(shù)還允許改變這個隊列的長度,不能不能超過操作系統(tǒng)支持的最大值。

package network.serversocket;
import java.net.*;
import java.io.*;
import java.util.Date;
 
public class DaytimeServer {
 
  public final static int PORT = 13;
  public static void main(String[] args) {  
   try (ServerSocket server = new ServerSocket(PORT)) {
     while (true) {  
       try (Socket connection = server.accept()) {
         Writer out = new OutputStreamWriter(connection.getOutputStream());
         Date now = new Date();
         out.write(now.toString() +"
");
         out.flush();      
         connection.close();
       } catch (IOException ex) {}       
     }
   } catch (IOException ex) {
     System.err.println(ex);
   } 
  }
}

不管怎樣,我們都希望能夠比新連接到來的速度更快地清空隊列。

每個連接對應(yīng)一個線程

解決方法是為每個連接提供它自己的一個線程,與接入站連接放入隊列的那個線程分開。生成一個線程來處理每個入站的連接,這樣可以防止一個慢客戶端阻塞所有其他客戶端,這種是“每個連接對應(yīng)一個線程”的設(shè)計。

package network.serversocket;
import java.net.*;
import java.io.*;
import java.util.Date;
 
public class ThreadPerConnectionDemo {
 
  public final static int PORT = 13;
  public static void main(String[] args) {   
   try (ServerSocket server = new ServerSocket(PORT)) {
     while (true) {  
       try {
         Socket connection = server.accept();
         Thread task = new DaytimeThread(connection);
         task.start();
       } catch (IOException ex) {}
     } 
    } catch (IOException ex) {
      System.err.println("Couldn"t start server");
    }
  }
  
  private static class DaytimeThread extends Thread {
    
    private Socket connection;
    
    DaytimeThread(Socket connection) {
      this.connection = connection;
    }
    
    @Override
    public void run() {
      try {
        Writer out = new OutputStreamWriter(connection.getOutputStream());
        Date now = new Date();
        out.write(now.toString() +"
");
        out.flush(); 
      } catch (IOException ex) {
        System.err.println(ex);
      } finally {
        try {
          connection.close();
        } catch (IOException e) {
          // ignore;
        }
      }
    }
  }
}
連接池的版本:
package network.serversocket;
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.*;
 
public class PooledDaytimeServer {
 
  public final static int PORT = 13;
  public static void main(String[] args) {  
   
   ExecutorService pool = Executors.newFixedThreadPool(50);
   try (ServerSocket server = new ServerSocket(PORT)) {
     while (true) {  
       try {
         Socket connection = server.accept();
         Callable task = new DaytimeTask(connection);
         pool.submit(task);
       } catch (IOException ex) {}
     } 
    } catch (IOException ex) {
      System.err.println("Couldn"t start server");
    }
  }
  
  private static class DaytimeTask implements Callable {
    
    private Socket connection;
    
    DaytimeTask(Socket connection) {
      this.connection = connection;
    }
    
    @Override
    public Void call() {
      try {
        Writer out = new OutputStreamWriter(connection.getOutputStream());
        Date now = new Date();
        out.write(now.toString() +"
");
        out.flush(); 
      } catch (IOException ex) {
        System.err.println(ex);
      } finally {
        try {
          connection.close();
        } catch (IOException e) {
          // ignore;
        }
      }
      return null;
    }
  }
}
優(yōu)雅地關(guān)閉socket

程序員通常會在一個try-finally塊中采用close-if-not-null模式了來關(guān)閉Socket,可以使用無參構(gòu)造器來稍加改進,無參構(gòu)造器不會拋出任何異常,也不綁定到一個端口,因此構(gòu)造放在try外邊,finally里頭直接close。

ServerSocket server = new ServerSocket();
try {
  SocketAddress address = new InetSocketAddress(port);
  server.bind(address);
  // ... work with the server socket
} finally {
  try {
    server.close();
  } catch (IOException ex) {
    // ignore
  }
}

或者直接采用Java7的AutoCloseable模式:

try (ServerSocket server = new ServerSocket(port)) {
  // ... work with the server socket
}catch (IOException ex) {
      logger.log(Level.SEVERE, "Could not start server", ex);
    }

如果要記錄異常信息,可以catch下異常,否則可以不用catch。

要測試ServerSocket是否打開:

public static boolean isOpen(ServerSocket ss) {
  return ss.isBound() && !ss.isClosed();
}

isBound方法有歧義,它是表示是否曾經(jīng)綁定到某個端口,即使它目前已經(jīng)關(guān)閉,isBound仍然會返回true,因此還需要判斷是否是close。

構(gòu)建ServerSocket
ServerSocket httpd = new ServerSocket(80, 50);

這里指定了綁定80端口,同時隊列一次最多可保存50個入站連接,如果試圖設(shè)置超過操作系統(tǒng)的最大隊列長度,則會使用最大隊列長度。

ServerSocket server = new ServerSocket(0);

0表示監(jiān)聽未指定的端口,操作系統(tǒng)會為你選擇可用的端口,稱之為匿名端口。

如果沒有綁定任何端口,則getLocalPort返回-1。

ServerSocket選項 1)SO_TIMEOUT

為0的話,表示永不超時,一般服務(wù)端都設(shè)置為永不超時??蛻舳藙t要指定。
設(shè)置該值必須在調(diào)用accppt之前。

2)SO_REUSEADDR

確定是否允許一個新的Socket綁定到之前使用過的一個端口,而此時可能還有一些發(fā)送到原來Socket的數(shù)據(jù)正在網(wǎng)絡(luò)上傳輸。

3)SO_RCVBUF

設(shè)置了服務(wù)器Socket接受的客戶端Socket默認接收緩沖區(qū)的大小。
setReceiveBufferSize來設(shè)置,必須在accept之前設(shè)置。

4)服務(wù)類型

為TCP定義了4個通用的業(yè)務(wù)流模型:
A、低成本
B、高可靠性
C、最大吞吐量
D、最小延遲

可以使用setPerformancePreferences方法描述

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/65945.html

相關(guān)文章

  • java必知會之SecureSocket

    SSL,Secure Sockets Layer,安全Socket層TLS,Transport Layer Security,傳輸層安全協(xié)議 package network.secure; import java.io.*; import javax.net.ssl.*; public class HTTPSClient { public static void main(Strin...

    kidsamong 評論0 收藏0
  • Java必知會之socket

    摘要:上,數(shù)據(jù)按有限大小的包傳輸,這些包成為數(shù)據(jù)報,每個數(shù)據(jù)報包含一個首部和一個有效載荷。不過,由于數(shù)據(jù)報長度有限,通常必須將數(shù)據(jù)分解為多個包,再在目的地重新組合。這兩個構(gòu)造函數(shù),在返回之前會與遠程主機建立一個活動的網(wǎng)絡(luò)連接。 Internet上,數(shù)據(jù)按有限大小的包傳輸,這些包成為數(shù)據(jù)報(datagram),每個數(shù)據(jù)報包含一個首部(header)和一個有效載荷(payload)。首部包含包發(fā)...

    jackzou 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<