利用Socket進行Java網路編程

來源:互聯網
上載者:User
 利用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);
 }catch(Exception e){
}
 new Thread()
 { public void run()
  { try{
    while(true)
    { checkInput();
     sleep(1000);
  }
 }catch (InterruptedException ex){
 }catch(IOException ex){
 }
 }
 }.start();
 while(talking)
 { }
 t.dispose();
 }

private void checkInput() throws IOException
{ String line;
 if((line=in.readLine())!=null)
  t.setPartner(line); file://這是介面類裡的方法,
  file://用來將line的內容輸出到使用者介面
 }
}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.