程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA編程入門知識 >> Java中的Socket編程

Java中的Socket編程

編輯:JAVA編程入門知識

        Socket是網絡上運行的兩個程序間雙向通訊的一端,它既可以接受請求,也可以發送請求,利用它可以較為方便的編寫網絡上數據的傳遞。在Java中,有專門的Socket類來處理用戶的請求和響應。利用Socket類的方法,就可以實現兩台計算機之間的通訊。這裡就介紹一下在Java中如何利用Socket進行網絡編程。
  
  在Java中Socket可以理解為客戶端或者服務器端的一個非凡的對象,這個對象有兩個要害的方法,一個是getInputStream方法,另一個是getOutputStream方法。getInputStream方法可以得到一個輸入流,客戶端的Socket對象上的getInputStream方法得到的輸入流其實就是從服務器端發回的數據流。GetOutputStream方法得到一個輸出流,客戶端Socket對象上的getOutputStream方法返回的輸出流就是將要發送到服務器端的數據流,(其實是一個緩沖區,暫時存儲將要發送過去的數據)。
  
  程序可以對這些數據流根據需要進行進一步的封裝。本文的例子就對這些數據流進行了一定的封裝(關於封裝可以參考Java中流的實現部分)。
  
  為了更好的說明問題,這裡舉了一個網上對話的例子,客戶端啟動以後,服務器會啟動一個線程來與客戶進行文字交流。
  
  要完成這個工作,需要完成三個部分的工作,以下依次說明:
  
  一、建立服務器類
  
  Java中有一個專門用來建立Socket服務器的類,名叫ServerSocket,可以用服務器需要使用的端口號作為參數來創建服務器對象。
  
  ServerSocket server = new ServerSocket(9998)
  
  這條語句創建了一個服務器對象,這個服務器使用9998號端口。當一個客戶端程序建立一個Socket連接,所連接的端口號為9998時,服務器對象server便響應這個連接,並且server.accept()方法會創建一個Socket對象。服務器端便可以利用這個Socket對象與客戶進行通訊。
  
  Socket incoming = server.accept()
  
  進而得到輸入流和輸出流,並進行封裝
  
  BufferedReader in = new BufferedReader(new
  InputStreamReader(incoming.getInputStream()));
  PrintWriter out = new PrintWriter(incoming.getOutputStream(),true);
  
  隨後,就可以使用in.readLine()方法得到客戶端的輸入,也可以使用out.println()方法向客戶端發送數據。從而可以根據程序的需要對客戶端的不同請求進行回應。
  
  在所有通訊結束以後應該關閉這兩個數據流,關閉的順序是先關閉輸出流,再關閉輸入流,即使用
  
  out.close();
  in.close();
  
  二、建立客戶端代碼
  
  相比服務器端,客戶端要簡單一些,客戶端只需用服務器所在機器的ip以及服務器的端口作為參數創建一個Socket對象。得到這個對象後,就可以用"建立服務器"部分介紹的方法實現數據的輸入和輸出。
  
  Socket socket = new Socket("168.160.12.42",9998);
  in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  out = new PrintWriter(socket.getOutputStream(),true);
  
  以上的程序代碼建立了一個Socket對象,這個對象連接到ip地址為168.160.12.42的主機上、端口為9998的服務器對象。並且建立了輸入流和輸出流,分別對應服務器的輸出和客戶端的寫入。
  
  三、建立用戶界面
  
  讀者可以根據自己的喜好建立自己的用戶界面,這不是本文的重點。
  
  經過以上三個步驟,就可以建立一個比較簡單的對話程序。但是,為了使這個程序更加完善,應進行以下幾個改進:
  
  一、現在服務器只能服務一個客戶,也就是單線程的。可以將它改進為多線程服務器。
  
  try
  { file://建立服務器
   ServerSocket server = new ServerSocket(9998);
   int i=1;
   for(;;)
   {
  Socket incoming = server.accept();
  new ServerThread(incoming,i).start();
  i++;
   }
  }catch (IOException ex){ ex.printStackTrace(); }
  
  循環檢測是否有客戶連接到服務器上,假如有,則創建一個線程來服務這個客戶,這個線程的名稱是ServerThread,這個類擴展了Thread類,它的編寫方法與前述的服務器的寫法相同。
  
  二、為了可以隨時得到對方傳送過來的消息,可以在服務器以及客戶端各建立一個獨立的線程來察看輸入流,假如輸入流中有輸入,則可以即時顯示出來。代碼如下:
  
  new Thread()
  {
   public void run()
   {
  try
  { 
   while(true)
   {
  checkInput();
  sleep(1000);//每1000毫秒檢測一次
   }
  }catch (InterruptedException ex)
   {
   }catch(IOException ex)
   {
  }
   }
  }.start();
  
  其中的checkInput()方法為
  private void checkInput() throws IOException
  {
   String line;
   if((line=in.readLine())!=null) file://檢測輸入流中是否有新的數據
  t.setPartner(line); file://將數據流中的消息顯示出來
  }
  
  通過以上改進,程序就可以比較好的運行了。
  
  附:服務器的實現代碼
  
  import java.net.*;
  import java.io.*;
  import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  
  public class talkServer
  { public static void main(String[] args)
   { try
  { file://建立服務器
   ServerSocket server = new ServerSocket(9998);
   int i=1;
   for(;;)
  { Socket incoming = server.accept();
   new ServerThread(incoming,i).start();
   i++;
  }
   }catch (IOException ex){
   ex.printStackTrace();
  }
   }
  }
  
  class ServerThread extends Thread implements ActionListener
  {
   private int threadNum;
   private Socket socket;
   talkServerFrm t;
   BufferedReader in;
   PrintWriter out;
   private boolean talking=true;
   public ServerThread(Socket s,int c)
   { threadNum = c;
  socket = s;
   }
  
  public void actionPerformed(ActionEvent e)
  { Object source = e.getSource();
   try{
  if(source==t.BTnSend)
   { out.println(t.getTalk());
  t.clearTalk();
  }else
  if(source==t.btnEnd)
   { out.println("談話過程被對方終止");
  out.close();
  in.close();
  talking = false;
   }
   }catch(IOException ex){
   }
  }
  
  public void run()
  { try{
  t=new talkServerFrm(new Integer(threadNum).toString(),this);
  t.setSize(500,500);
  t.show();
  in = new BufferedReader(new
    InputStreamReader(socket.getInputStream()));
  out = new PrintWriter(socket.getOutputStream(),true);

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved