『壹』 java Socket 底層是怎樣基於TCP/IP 實現的
首先必須明確:TCP/IP模型中有四層結構:
應用層(Application Layer)、傳輸層(Transport Layer)、網路層(Internet Layer )、鏈路層(LinkLayer)
其中Ip協議(Internet Protocol)是位於網路層的,TCP協議時位於傳輸層的。通過Ip協議可以使可以使兩台計算機使用同一種語言,從而允許Internet上連接不同類型的計算機和不同操作系統的網路。Ip協議只保證計算機能夠接收和發送分組數據。 當計算機要和遠程的計算機建立連接時,TCP協議會讓他們建立連接:用於發送和接收數據的虛擬電路。
在JAVA中,我們用 ServerSocket、Socket類創建一個套接字連接,從套接字得到的結果是一個InputStream以及OutputStream對象,以便將連接作為一個IO流對象對待。通過IO流可以從流中讀取數據或者寫數據到流中,讀寫IO流會有異常IOException產生。
套接字或插座(socket)是一種軟體形 式的抽象,用於表達兩台機器間一個連接的「終端」。針對一個特定的連接,每台機器上都有一個「套接字」,可以想像它們之間有一條虛擬的「線纜」。JAVA 有兩個基於數據流的套接字類:ServerSocket,伺服器用它「偵聽」進入的連接;Socket,客戶端用它初始一次連接。偵聽套接字只能接收新的 連接請求,不能接收實際的數據包,即ServerSocket不能接收實際的數據包。
套接字是基於TCP/IP實現的,它是用來提供一個訪問TCP的服務介面,或者說套接字socket是TCP的應用編程介面API,通過它應用層就可以訪問TCP提供的服務。
在JAVA中,我們用 ServerSocket、Socket類創建一個套接字連接,從套接字得到的結果是一個InputStream以及OutputStream對象,以便 將連接作為一個IO流對象對待。通過IO流可以從流中讀取數據或者寫數據到流中,讀寫IO流會有異常IOException產生。
『貳』 請教大神,java socket介面,TCP長連接,怎麼解析和發送一種協議格式數據包
建議你下載我的java版本至尊聊天程序源碼下去參考。在CSDN或網路上找吧。
協議完全回自己來定製,答數據以位元組發送,以什麼開始,什麼結束,中間分幾段,都可由你自己來定,接收時,就按你定的規則來解析並還原。比如:我要的協議格式為
:>10:3:5:content:<
:>表示一條消息的開始。
10表示總消息長度(只是個代數,有可能不是10,需要你在發送前計算)
:為分隔符
3為頭消息長度,也可能不是3
5表示後面的消息內容長度,甚至還可以定製,是否有圖片,從多少位置開始是圖片的數據。
:<表示結束標志
沒有人限制你的協議。
關鍵一點:你在收取的時候,一定要注意數據可能會粘包,這個問題很頭疼的。因為一般都是多線程模式。這需要你自己來處理它。一言難清。可以參考我的聊天程序。
『叄』 java socket區域網傳輸文件丟包嚴重
這方面的 我也做過,建議用DataInputStream 做底層,然後用其他高級流,做裝飾,這樣穿不會丟失,我以前也做了一個如果要源代碼,給我留言,不會丟失文件的
『肆』 如何使用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 tcp socket 通信問題
這兩個問題都可以通過消息機制來解決,
消息機制就是雙方約定的通信語言。
首先:你需要自定義一份雙方約定的通信機制,
其次: 對每個連進來的客戶按用戶ID或IP進行編號存入哈希表,以方便索引用戶的Socket通道。 每進來一個客戶就 hashtable.put(user.name, socket);
最後:雙方都還要有兩個緩沖數組(可以是數組Object[],也可以是Vector,Arraylist,Hashtable都可以);
一個叫發送緩沖區,一個叫接收緩沖區。每一個都附帶一個管理線程。
向客戶端發送消息時,並不是馬上就發送,而是將消息推入到發送緩沖區排隊,
發送緩沖區的線程會每隔一小片時間後就掃描並 pop出一個可發送的消息。
分析這個消息的源發送者和目的發送者,然後hashtable的索引找到目的發送者的socket通道。並發送.
另一個叫接收緩沖區。 Socket的網路線程不斷接收到客戶的消息,但不是馬上就處理,也不會自己親自處理,而是壓入接收緩沖隊列等待緩沖隊列來處理,自己休息片段又立馬再去接收別的客戶發過來的消息。 接收緩沖區有自己的線程,它每sleep一小片刻時間後就掃描隊列中有無消息到達,如果有(網路線程剛壓進一的),則可以採用監聽器模式讓監聽器處理,如果不想那麼復雜也可以自己處理, 會分析消息來源和去向,從去向中分析出將要發送給某人,但自己並不發送,而是直接壓入到發送緩沖區(這里就接到前面的發送緩沖區介紹中去了)
最後是消息機制的設計。
我公司的游戲都是由我來設計通信機制,實現三網合一,即手機,PC,電視機頂盒三種客戶端同玩一桌麻將游戲
一般java設計的游戲中設計如下:
一. 消息頭 二.消息體
消息頭設計格式如下: 1. 本消息包長度,以方便解析位元組;2. 本消息類型TYPE:如一般消息,游戲消息,大廳消息,聊天消息;3.本消息命令類型COMMAND: 如登陸、個人資料修改、登出、聊天。。。。
消息體設計格式一般根據Type和command不同而有不同。 如聊天消息包含四個欄位,String 聊天內容、 User 發送者、 User 接收者、Text文字排版信息
服務端SeverSocket收到這個消息後,壓入接收緩沖區, 接收緩沖線程分析其中結構,根據Type和Command的類型實例化出相應消息類, 該消息類能自動將後面的位元組流實例化自身的欄位。從而得到接收方和發送方, 得到接收方後再將消息封裝好壓入到發送隊列
這個結構除完全適合聊天系統以外,以後要加入新內容將會非常容易!
如果有什麼疑問歡迎call我, 我不負責寫代碼,但可以指點你。 另外,我的回答記錄中有用nio設計的聊天室BBS代碼。也是幫一個學生做的。你可以看看
『陸』 java編程中,Socket通信是怎麼實現的
java編程對於Socket之間的通信過程如下:
服務端往Socket的輸出流裡面寫東西,客戶端就可以通過Socket的輸入流讀取對應的內容。Socket與Socket之間是雙向連通的,所以客戶端也可以往對應的Socket輸出流裡面寫東西,然後服務端對應的Socket的輸入流就可以讀出對應的內容。下面來看一些服務端與客戶端通信的例子:
publicclassServer{
publicstaticvoidmain(Stringargs[])throwsIOException{
//為了簡單起見,所有的異常信息都往外拋
intport=8899;
//定義一個ServerSocket監聽在埠8899上
ServerSocketserver=newServerSocket(port);
//server嘗試接收其他Socket的連接請求,server的accept方法是阻塞式的
Socketsocket=server.accept();
//跟客戶端建立好連接之後,我們就可以獲取socket的InputStream,並從中讀取客戶端發過來的信息了。
Readerreader=newInputStreamReader(socket.getInputStream());
charchars[]=newchar[64];
intlen;
StringBuildersb=newStringBuilder();
while((len=reader.read(chars))!=-1){
sb.append(newString(chars,0,len));
}
System.out.println("fromclient:"+sb);
reader.close();
socket.close();
server.close();
}
}
客戶端代碼
Java代碼publicclassClient{
publicstaticvoidmain(Stringargs[])throwsException{
//為了簡單起見,所有的異常都直接往外拋
Stringhost="127.0.0.1";//要連接的服務端IP地址
intport=8899;//要連接的服務端對應的監聽埠
//與服務端建立連接
Socketclient=newSocket(host,port);
//建立連接後就可以往服務端寫數據了
Writerwriter=newOutputStreamWriter(client.getOutputStream());
writer.write("HelloServer.");
writer.flush();//寫完後要記得flush
writer.close();
client.close();
}
}