stock協議

Socket概念

Socket是什麼呢?

       Socket是應用層與TCP/IP協議族通信的中間軟件抽象層,它是一組接口。在設計模式中,Socket其實就是一個門面模式,它把複雜的TCP/IP協議族隱藏在Socket接口後面,對用戶來說,一組簡單的接口就是全部,讓Socket去組織數據,以符合指定的協議。

    網絡上的兩個程序通過一個雙向的通訊連接實現數據的交換,這個雙向鏈路的一端稱爲一個Socket。Socket通常用來實現客戶方和服務方的連接。Socket是TCP/IP協議的一個十分流行的編程界面,一個Socket由一個IP地址和一個端口號唯一確定。但是,Socket所支持的協議種類也不光TCP/IP一種,因此兩者之間是沒有必然聯繫的。在Java環境下,Socket編程主要是指基於TCP/IP協議的網絡編程。

你會使用它們嗎?
       
前人已經給我們做了好多的事了,網絡間的通信也就簡單了許多,但畢竟還是有挺多工作要做的。以前聽到Socket編程,覺得它是比較高深的編程知識,但是隻要弄清Socket編程的工作原理,神祕的面紗也就揭開了。
       一個生活中的場景。你要打電話給一個朋友,先撥號,朋友聽到電話鈴聲後提起電話,這時你和你的朋友就建立起了連接,就可以講話了。等交流結束,掛斷電話結束此次交談。    生活中的場景就解釋了這工作原理,也許TCP/IP協議族就是誕生於生活中,這也不一定。

一個是如何準確的定位網絡上一臺或多臺主機,另一個就是找到主機後如何可靠高效的進行數據傳輸。

基於Socket的java網絡單線程編程

   Server端Listen(監聽)某個端口是否有連接請求,Client端向Server 端發出Connect(連接)請求,Server端向Client端發回Accept(接受)消息。一個連接就建立起來了。Server端和Client 端都可以通過Send,Write等方法與對方通信。

   創建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則表示服務端所能支持的最大連接數。例如:

  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是必須捕獲或拋出例外。

示例如下:

    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多客戶的client/server多線程sotck程序 

   前面的Client/Server程序只能實現Server和一個客戶的對話。在實際應用 中,往往是在服務器上運行一個永久的程序,它可以接收來自其他多個客戶端的請求,提供相應的服務。爲了實現在服務器方給多個客戶提供服務的功能,需要對上 面的程序進行改造,利用多線程實現多客戶機制。服務器總是在指定的端口上監聽是否有客戶請求,一旦監聽到客戶請求,服務器就會啓動一個專門的服務線程來響 應該客戶的請求,而服務器本身在啓動完線程之後馬上又進入監聽狀態,等待下一個客戶的到來。

   採用Java 5的ExecutorService來進行線程池的方式實現多線程,模擬客戶端多用戶向同一服務器端發送請求.

       1.服務端
package sterning;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.*;
import java.util.concurrent.*;


public class MultiThreadServer {
    private int port=8821;
    private ServerSocket serverSocket;
    private ExecutorService executorService;//線程池
    private final int POOL_SIZE=10;//單個CPU線程池大小
    
    public MultiThreadServer() throws IOException{
        serverSocket=new ServerSocket(port);
        //Runtime的availableProcessor()方法返回當前系統的CPU數目.
        executorService=Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*POOL_SIZE);
        System.out.println("服務器啓動");
    }
    
    public void service(){
        while(true){
            Socket socket=null;
            try {
                //接收客戶連接,只要客戶進行了連接,就會觸發accept();從而建立連接
                socket=serverSocket.accept();
                executorService.execute(new Handler(socket));
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    public static void main(String[] args) throws IOException {
        new MultiThreadServer().service();
    }


}


class Handler implements Runnable{
    private Socket socket;
    public Handler(Socket socket){
        this.socket=socket;
    }
    private PrintWriter getWriter(Socket socket) throws IOException{
        OutputStream socketOut=socket.getOutputStream();
        return new PrintWriter(socketOut,true);
    }
    private BufferedReader getReader(Socket socket) throws IOException{
        InputStream socketIn=socket.getInputStream();
        return new BufferedReader(new InputStreamReader(socketIn));
    }
    public String echo(String msg){
        return "echo:"+msg;
    }
    public void run(){
        try {
            System.out.println("New connection accepted "+socket.getInetAddress()+":"+socket.getPort());
            BufferedReader br=getReader(socket);
            PrintWriter pw=getWriter(socket);
            String msg=null;
            while((msg=br.readLine())!=null){
                System.out.println(msg);
                pw.println(echo(msg));
                if(msg.equals("bye"))
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if(socket!=null)
                    socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}


2.客戶端
package sterning;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class MultiThreadClient {
    
    public static void main(String[] args) {
        int numTasks = 10;
        
        ExecutorService exec = Executors.newCachedThreadPool();


        for (int i = 0; i < numTasks; i++) {
            exec.execute(createTask(i));
        }


    }


    // 定義一個簡單的任務
    private static Runnable createTask(final int taskID) {
        return new Runnable() {
            private Socket socket = null;
            private int port=8821;


            public void run() {
                System.out.println("Task " + taskID + ":start");
                try {                    
                    socket = new Socket("localhost", port);
                    // 發送關閉命令
                    OutputStream socketOut = socket.getOutputStream();
                    socketOut.write("shutdown\r\n".getBytes());


                    // 接收服務器的反饋
                    BufferedReader br = new BufferedReader(
                            new InputStreamReader(socket.getInputStream()));
                    String msg = null;
                    while ((msg = br.readLine()) != null)
                        System.out.println(msg);
                } catch (IOException e) {                    
                    e.printStackTrace();
                }
            }


        };
    }
}

詳細stock講解:

   訪問地址-->http://www.blogjava.net/Reg/archive/2010/07/17/326392.html

webstock實現方式

   訪問此地址-->http://blog.fens.me/java-websocket-intro/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章