1. 程式人生 > >【Java TCP/IP Socket】TCP Socket(含代碼)

【Java TCP/IP Socket】TCP Socket(含代碼)

webkit -c round app code stat -m ride adl

TCP的Java支持

協議相當於相互通信的程序間達成的一種約定,它規定了分組報文的結構、交換方式、包含的意義以及怎樣對報文所包含的信息進行解析,TCP/IP協議族有IP協議、TCP協議和UDP協議現在TCP/IP協議族中的主要socket類型為流套接字(使用TCP協議)和數據報套接字(使用UDP協議)。

TCP協議提供面向連接的服務,通過它建立的是可靠地連接。Java為TCP協議提供了兩個類:Socket類和ServerSocket類。一個Socket實例代表了TCP連接的一個客戶端,而一個ServerSocket實例代表了TCP連接的一個服務器端,一般在TCP Socket編程中,客戶端有多個,而服務器端只有一個,客戶端TCP向服務器端TCP發送連接請求,服務器端的ServerSocket實例則監聽來自客戶端的TCP連接請求,並為每個請求創建新的Socket實例,由於服務端在調用accept()等待客戶端的連接請求時會阻塞,直到收到客戶端發送的連接請求才會繼續往下執行代碼,因此要為每個Socket連接開啟一個線程。服務器端要同時處理ServerSocket實例和Socket實例,而客戶端只需要使用Socket實例。另外,每個Socket實例會關聯一個InputStream和OutputStream對象,我們通過將字節寫入套接字的OutputStream來發送數據,並通過從InputStream來接收數據。

TCP連接的建立步驟

客戶端向服務器端發送連接請求後,就被動地等待服務器的響應。典型的TCP客戶端要經過下面三步操作:

1、創建一個Socket實例:構造函數向指定的遠程主機和端口建立一個TCP連接;

2.通過套接字的I/O流與服務端通信;

3、使用Socket類的close方法關閉連接。

服務端的工作是建立一個通信終端,並被動地等待客戶端的連接。典型的TCP服務端執行如下兩步操作:

1、創建一個ServerSocket實例並指定本地端口,用來監聽客戶端在該端口發送的TCP連接請求;

2、重復執行:

1)調用ServerSocket的accept()方法以獲取客戶端連接,並通過其返回值創建一個Socket實例;

2)為返回的Socket實例開啟新的線程,並使用返回的Socket實例的I/O流與客戶端通信;

3)通信完成後,使用Socket類的close()方法關閉該客戶端的套接字連接。

TCP Socket Demo

下面給出一個客戶端服務端TCP通信的Demo,該客戶端在20006端口請求與服務端建立TCP連接,客戶端不斷接收鍵盤輸入,並將其發送到服務端,服務端在接收到的數據前面加上“echo”字符串,並將組合後的字符串發回給客戶端,如此循環,直到客戶端接收到鍵盤輸入“bye”為止。

客戶端代碼如下:

package zyb.org.client;  
  
import java.io.BufferedReader;  
import java.io.IOException;  
import java.io.InputStreamReader;  
import java.io.PrintStream;  
import java.net.Socket;  
import java.net.SocketTimeoutException;  
  
public class Client1 {  
    public static void main(String[] args) throws IOException {  
        //客戶端請求與本機在20006端口建立TCP連接   
        Socket client = new Socket("127.0.0.1", 20006);  
        client.setSoTimeout(10000);  
        //獲取鍵盤輸入   
        BufferedReader input = new BufferedReader(new InputStreamReader(System.in));  
        //獲取Socket的輸出流,用來發送數據到服務端    
        PrintStream out = new PrintStream(client.getOutputStream());  
        //獲取Socket的輸入流,用來接收從服務端發送過來的數據    
        BufferedReader buf =  new BufferedReader(new InputStreamReader(client.getInputStream()));  
        boolean flag = true;  
        while(flag){  
            System.out.print("輸入信息:");  
            String str = input.readLine();  
            //發送數據到服務端    
            out.println(str);  
            if("bye".equals(str)){  
                flag = false;  
            }else{  
                try{  
                    //從服務器端接收數據有個時間限制(系統自設,也可以自己設置),超過了這個時間,便會拋出該異常  
                    String echo = buf.readLine();  
                    System.out.println(echo);  
                }catch(SocketTimeoutException e){  
                    System.out.println("Time out, No response");  
                }  
            }  
        }  
        input.close();  
        if(client != null){  
            //如果構造函數建立起了連接,則關閉套接字,如果沒有建立起連接,自然不用關閉  
            client.close(); //只關閉socket,其關聯的輸入輸出流也會被關閉  
        }  
    }  
}  

服務端需要用到多線程,這裏單獨寫了一個多線程類,代碼如下:

package zyb.org.server;  
  
import java.io.BufferedReader;  
import java.io.InputStreamReader;  
import java.io.PrintStream;  
import java.net.Socket;  
  
/** 
 * 該類為多線程類,用於服務端 
 */  
public class ServerThread implements Runnable {  
  
    private Socket client = null;  
    public ServerThread(Socket client){  
        this.client = client;  
    }  
      
    @Override  
    public void run() {  
        try{  
            //獲取Socket的輸出流,用來向客戶端發送數據  
            PrintStream out = new PrintStream(client.getOutputStream());  
            //獲取Socket的輸入流,用來接收從客戶端發送過來的數據  
            BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream()));  
            boolean flag =true;  
            while(flag){  
                //接收從客戶端發送過來的數據  
                String str =  buf.readLine();  
                if(str == null || "".equals(str)){  
                    flag = false;  
                }else{  
                    if("bye".equals(str)){  
                        flag = false;  
                    }else{  
                        //將接收到的字符串前面加上echo,發送到對應的客戶端  
                        out.println("echo:" + str);  
                    }  
                }  
            }  
            out.close();  
            client.close();  
        }catch(Exception e){  
            e.printStackTrace();  
        }  
    } 
}  

服務端處理TCP連接請求的代碼如下:

package zyb.org.server;  
  
import java.net.ServerSocket;  
import java.net.Socket;  
  
public class Server1 {  
    public static void main(String[] args) throws Exception{  
        //服務端在20006端口監聽客戶端請求的TCP連接  
        ServerSocket server = new ServerSocket(20006);  
        Socket client = null;  
        boolean f = true;  
        while(f){  
            //等待客戶端的連接,如果沒有獲取連接  
            client = server.accept();  
            System.out.println("與客戶端連接成功!");  
            //為每個客戶端連接開啟一個線程  
            new Thread(new ServerThread(client)).start();  
        }  
        server.close();  
    }  
}  

執行結果截圖如下:

技術分享圖片技術分享圖片

轉自:http://blog.csdn.net/ns_code/article/details/14105457

【Java TCP/IP Socket】TCP Socket(含代碼)