❶ java Socket重要參數講解
Java Socket的api可能很多人會用 但是Java Socket的參數可能很多人都不知道用來幹嘛的 甚至都不知道有這些參數
backlog
用於ServerSocket 配置ServerSocket的最大客戶端等待隊列 等待隊列的意思 先看下面代碼
public class Main { public static void main(String[] args) throws Exception { int port = int backlog = ServerSocket serverSocket = new ServerSocket(port backlog) Socket clientSock = serverSocket accept() System out println( revcive from + clientSock getPort()) while (true) { byte buf[] = new byte[ ] int len = clientSock getInputStream() read(buf) System out println(new String(buf len)) }這段測試代碼在第一次處理一個客戶端時 就不會處理第二個客戶端 所以除了第一個客戶端 其他客戶端就是等待隊殲罩列了 所以這個伺服器最多可以同時連接 個客戶端 其中 個等待隊列 大家可以telnet localhost 測試下
這個參數設置為 表示無限制 默認是 個最大等待隊列 如果設置無限制 那麼你要小心了 如果你伺服器無法處理那麼多連接 那麼當很多客戶端連到你的伺服器時 每一個TCP連接都會佔用伺服器的內存 最後會讓伺服器崩潰的
另外 就算你設置了backlog為 如果你的代碼中是一直Socket clientSock = serverSocket accept() 假設我們的族唯機器最多可以同時處理 個請求 總共有 個線程在運行 然後你把在 個線程的線程池處理clientSock 不能處理的clientSock就排隊 最後clientSock越來越多 也意味著TCP連接越來越多 也意味著我們的伺服器的內存使用越來越高(客戶端連接進程 肯定會發送數據過來 數據會保存到伺服器端的TCP接收緩存區) 最後伺服器就宕機了 所以如果你不能處理那麼多請求 請不要循環無限制地調用serverSocket accept() 否則backlog也無法生效 如果真的請求過多 只會讓你的伺服器宕機(相信很多人都是這么寫 要注意點)
TcpNoDelay
禁用納格演算法 將數據立即發送出去 納格演算法是以減少封包傳送量來增進TCP/IP網路的效能 當我們調用下面代碼 如
Socket socket = new Socket() nnect(new InetSocketAddress(host )) InputStream in = socket getInputStream() OutputStream out = socket getOutputStream() String head = hello String body = world out write(head getBytes()) out write(body getBytes()) 我們發送了hello 當hello沒有收到ack確認(TCP是可靠連接 發送的每一個數據都要收到對方的一個ack確認 否則就要重發)的時候 根據納格演算法 world不會立馬發送 會等待 要麼等到ack確認(最多等 ms對方會氏穗鬧發過來的) 要麼等到TCP緩沖區內容>=MSS 很明顯這里沒有機會 我們寫了world後再也沒有寫數據了 所以只能等到hello的ack我們才會發送world 除非我們禁用納格演算法 數據就會立即發送了
SoLinger
當我們調用socket close()返回時 socket已經write的數據未必已經發送到對方了 例如
Socket socket = new Socket() nnect(new InetSocketAddress(host )) InputStream in = socket getInputStream() OutputStream out = socket getOutputStream() String head = hello String body = world out write(head getBytes()) out write(body getBytes()) socket close()
這里調用了socket close()返回時 hello和world未必已經成功發送到對方了 如果我們設置了linger而不小於 如
bool on = true int linger = ……
socket setSoLinger(boolean on int linger)
……
socket close() 那麼close會等到發送的數據已經確認了才返回 但是如果對方宕機 超時 那麼會根據linger設定的時間返回
UrgentData和OOBInline
TCP的緊急指針 一般都不建議使用 而且不同的TCP/IP實現 也不同 一般說如果你有緊急數據寧願再建立一個新的TCP/IP連接發送數據 讓對方緊急處理
所以這兩個參數 你們可以忽略吧 想知道更多的 自己查下資料
SoTimeout
設置socket調用InputStream讀數據的超時時間 以毫秒為單位 如果超過這個時候 會拋出 SocketTimeoutException
KeepAlive
keepalive不是說TCP的常連接 當我們作為服務端 一個客戶端連接上來 如果設置了keeplive為true 當對方沒有發送任何數據過來 超過一個時間(看系統內核參數配置) 那麼我們這邊會發送一個ack探測包發到對方 探測雙方的TCP/IP連接是否有效(對方可能斷點 斷網) 在Linux好像這個時間是 秒 如果不設置 那麼客戶端宕機時 伺服器永遠也不知道客戶端宕機了 仍然保存這個失效的連接
SendBufferSize和ReceiveBufferSize
TCP發送緩存區和接收緩存區 默認是 一般情況下足夠了 而且就算你增加了發送緩存區 對方沒有增加它對應的接收緩沖 那麼在TCP三握手時 最後確定的最大發送窗口還是雙方最小的那個緩沖區 就算你無視 發了更多的數據 那麼多出來的數據也會被丟棄 除非雙方都協商好
lishixin/Article/program/Java/hx/201311/26575
❷ 如何使用java socket來傳輸自定義的數據包
以下分四點進行描述:
1,什麼是Socket
網路上的兩個程序通過一個雙向的通訊連接實現數據的交換,這個雙向鏈路的一端稱為一個Socket。Socket通常用來實現客戶方和服務方的連接。Socket是TCP/IP協議的一個十分流行的編程界面,一個Socket由一個IP地址和一個埠號唯一確定。
但是,Socket所支持的協議種類也不光TCP/IP一種,因此兩者之間是沒有必然聯系的。在Java環境下,Socket編程主要是指基於TCP/IP協議的網路編程。
2,Socket通訊的過程
Server端Listen(監聽)某個埠是否有連接請求,Client端向Server 端發出Connect(連接)請求,Server端向Client端發回Accept(接受)消息。一個連接就建立起來了。Server端和Client 端都可以通過Send,Write等方法與對方通信。
對於一個功能齊全的Socket,都要包含以下基本結構,其工作過程包含以下四個基本的步驟:
(1) 創建Socket;
(2) 打開連接到Socket的輸入/出流;
(3) 按照一定的協議對Socket進行讀/寫操作;
(4) 關閉Socket.(在實際應用中,並未使用到顯示的close,雖然很多文章都推薦如此,不過在我的程序中,可能因為程序本身比較簡單,要求不高,所以並未造成什麼影響。)
3,創建Socket
創建Socket
java在包java.net中提供了兩個類Socket和ServerSocket,分別用來表示雙向連接的客戶端和服務端。這是兩個封裝得非常好的類,使用很方便。其構造方法如下:
Socket(InetAddress address, int port);
Socket(InetAddress address, int port, boolean stream);
Socket(String host, int prot);
Socket(String host, int prot, boolean stream);
Socket(SocketImpl impl)
Socket(String host, int port, InetAddress localAddr, int localPort)
Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
ServerSocket(int port);
ServerSocket(int port, int backlog);
ServerSocket(int port, int backlog, InetAddress bindAddr)
其中address、host和port分別是雙向連接中另一方的IP地址、主機名和端 口號,stream指明socket是流socket還是數據報socket,localPort表示本地主機的埠號,localAddr和 bindAddr是本地機器的地址(ServerSocket的主機地址),impl是socket的父類,既可以用來創建serverSocket又可 以用來創建Socket。count則表示服務端所能支持的最大連接數。例如:學習視頻網 http://www.xxspw.com
Socket client = new Socket("127.0.01.", 80);
ServerSocket server = new ServerSocket(80);
注意,在選擇埠時,必須小心。每一個埠提供一種特定的服務,只有給出正確的埠,才 能獲得相應的服務。0~1023的埠號為系統所保留,例如http服務的埠號為80,telnet服務的埠號為21,ftp服務的埠號為23, 所以我們在選擇埠號時,最好選擇一個大於1023的數以防止發生沖突。
在創建socket時如果發生錯誤,將產生IOException,在程序中必須對之作出處理。所以在創建Socket或ServerSocket是必須捕獲或拋出例外。
4,簡單的Client/Server程序
1. 客戶端程序
import java.io.*;
import java.net.*;
public class TalkClient {
public static void main(String args[]) {
try{
Socket socket=new Socket("127.0.0.1",4700);
//向本機的4700埠發出客戶請求
BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));
//由系統標准輸入設備構造BufferedReader對象
PrintWriter os=new PrintWriter(socket.getOutputStream());
//由Socket對象得到輸出流,並構造PrintWriter對象
BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//由Socket對象得到輸入流,並構造相應的BufferedReader對象
String readline;
readline=sin.readLine(); //從系統標准輸入讀入一字元串
while(!readline.equals("bye")){
//若從標准輸入讀入的字元串為 "bye"則停止循環
os.println(readline);
//將從系統標准輸入讀入的字元串輸出到Server
os.flush();
//刷新輸出流,使Server馬上收到該字元串
System.out.println("Client:"+readline);
//在系統標准輸出上列印讀入的字元串
System.out.println("Server:"+is.readLine());
//從Server讀入一字元串,並列印到標准輸出上
readline=sin.readLine(); //從系統標准輸入讀入一字元串
} //繼續循環
os.close(); //關閉Socket輸出流
is.close(); //關閉Socket輸入流
socket.close(); //關閉Socket
}catch(Exception e) {
System.out.println("Error"+e); //出錯,則列印出錯信息
}
}
}
2. 伺服器端程序
import java.io.*;
import java.net.*;
import java.applet.Applet;
public class TalkServer{
public static void main(String args[]) {
try{
ServerSocket server=null;
try{
server=new ServerSocket(4700);
//創建一個ServerSocket在埠4700監聽客戶請求
}catch(Exception e) {
System.out.println("can not listen to:"+e);
//出錯,列印出錯信息
}
Socket socket=null;
try{
socket=server.accept();
//使用accept()阻塞等待客戶請求,有客戶
//請求到來則產生一個Socket對象,並繼續執行
}catch(Exception e) {
System.out.println("Error."+e);
//出錯,列印出錯信息
}
String line;
BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//由Socket對象得到輸入流,並構造相應的BufferedReader對象
PrintWriter os=newPrintWriter(socket.getOutputStream());
//由Socket對象得到輸出流,並構造PrintWriter對象
BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));
//由系統標准輸入設備構造BufferedReader對象
System.out.println("Client:"+is.readLine());
//在標准輸出上列印從客戶端讀入的字元串
line=sin.readLine();
//從標准輸入讀入一字元串
while(!line.equals("bye")){
//如果該字元串為 "bye",則停止循環
os.println(line);
//向客戶端輸出該字元串
os.flush();
//刷新輸出流,使Client馬上收到該字元串
System.out.println("Server:"+line);
//在系統標准輸出上列印讀入的字元串
System.out.println("Client:"+is.readLine());
//從Client讀入一字元串,並列印到標准輸出上
line=sin.readLine();
//從系統標准輸入讀入一字元串
} //繼續循環
os.close(); //關閉Socket輸出流
is.close(); //關閉Socket輸入流
socket.close(); //關閉Socket
server.close(); //關閉ServerSocket
}catch(Exception e){
System.out.println("Error:"+e);
//出錯,列印出錯信息
}
}
}
❸ 請問java socket 裡面的bind做什麼用
socket.bind(SocketAddress bindpoint)
英文:Binds the socket to a local address;If the address is null, then the system will pick up
an ephemeral port and a valid local address to bind the socket
翻譯抄:將socket綁定襲到本地地址;如果地址為空,系統會指定一個暫時的埠和合法的本地地址去綁定socket