充分理解Socket—簡單的聊天程式的代碼

來源:互聯網
上載者:User

充分理解Socket 

   1.什麼是socket 

  
所謂socket通常也稱作"通訊端",用於描述IP地址和連接埠,是一個通訊鏈的控制代碼。應用程式通常通過"通訊端"向網路發出請求或者應答網路請求。 

   以J2SDK-1.3為例,Socket和ServerSocket類庫位於java.net包中。ServerSocket用於伺服器端,Socket是建立網路連接時使用的。在串連成功時,應用程式兩端都會產生一個Socket執行個體,操作這個執行個體,完成所需的會話。對於一個網路連接來說,通訊端是平等的,並沒有差別,不因為在伺服器端或在用戶端而產生不同層級。不管是Socket還是ServerSocket它們的工作都是通過SocketImpl類及其子類完成的。 

   重要的Socket API: 

   java.net.Socket繼承於java.lang.Object,有八個構造器,其方法並不多,下面介紹使用最頻繁的三個方法,其它方法大家可以見JDK-1.3文檔。 

   . Accept方法用於產生"阻塞",直到接受到一個串連,並且返回一個用戶端的Socket對象執行個體。"阻塞"是一個術語,它使程式運行暫時"停留"在這個地方,直到一個會話產生,然後程式繼續;通常"阻塞"是由迴圈產生的。 

   .
getInputStream方法獲得網路連接輸入,同時返回一個IutputStream對象執行個體,。 

   . getOutputStream方法串連的另一端將得到輸入,同時返回一個OutputStream對象執行個體。 

   注意:其中getInputStream和getOutputStream方法均會產生一個IOException,它必須被捕獲,因為它們返回的流對象,通常都會被另一個流對象使用。 

   2.如何開發一個Server-Client模型的程式 

   開發原理: 

  
伺服器,使用ServerSocket監聽指定的連接埠,連接埠可以隨意指定(由於1024以下的連接埠通常屬於保留連接埠,在一些作業系統中不可以隨意使用,所以建議使用大於1024的連接埠),等待客戶串連請求,客戶串連後,會話產生;在完成會話後,關閉串連。 

   用戶端,使用Socket對網路上某一個伺服器的某一個連接埠發出串連請求,一旦串連成功,開啟會話;會話完成後,關閉Socket。用戶端不需要指定開啟的連接埠,通常臨時的、動態分配一個1024以上的連接埠


簡單的聊天程式樣本。用到多線程、流、socket編程,用到Frame。

server端程式如下:

import java.io.BufferedReader;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.EOFException;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintStream;import java.net.BindException;import java.net.ServerSocket;import java.net.Socket;import java.util.ArrayList;import java.util.List;public class ChatServer {    boolean started = false;    ServerSocket ss = null;Socket s = null;String ip;List<Client> clients = new ArrayList<Client>();//int count;//開啟伺服器    public void startServer(){    try{ss = new ServerSocket(8888);started = true;System.out.println("伺服器已啟動!");} catch (BindException e1){System.out.println("連接埠被佔用,請關閉後重試");} catch (IOException e) {e.printStackTrace();}try {    while(started){s = ss.accept();System.out.println("一個客戶已串連");Client c = new Client(s);new Thread(c).start();clients.add(c);}}catch (IOException e) {e.printStackTrace();}finally {try {ss.close();//關閉此通訊端。 在 accept() 中所有當前阻塞的線程都將會拋出 SocketException。 //如果此通訊端有一個與之關聯的通道,則關閉該通道。} catch (IOException e) {e.printStackTrace();}}    }public static void main(String[] args) {new ChatServer().startServer();}     class Client implements Runnable {       private Socket s;private DataInputStream dis = null;private DataOutputStream dos = null;private boolean flag = false;        public Client(Socket s){        this.s = s;        try {dis = new DataInputStream(s.getInputStream());dos = new DataOutputStream(s.getOutputStream());flag = true;} catch (IOException e) {e.printStackTrace();}        }                @Override      public void run() {                                                     //把目前使用者發來的資訊發送給所有使用者.              try {            while (flag) {    String str = dis.readUTF();for (int i = 0; i < clients.size();i++) {                       Client c = clients.get(i);                    //獲得目前使用者的IP               ip=s.getInetAddress().getHostAddress();                       c.send(str);                }}           }catch (EOFException e) {System.out.println("用戶端關閉了!");} catch (IOException e) {e.printStackTrace();}finally {try {if(dis != null) dis.close();if(dos != null) dos.close();if(s != null)  {s.close();}} catch (IOException e1) {e1.printStackTrace();}}                 }        public void send(String str){    try{    dos.writeUTF(ip+"說:");dos.writeUTF(str+'\n');} catch (IOException e) {clients.remove(this);}    }    }   }

  


client端代碼如下:

import java.awt.BorderLayout;import java.awt.Button;import java.awt.TextArea;import java.awt.TextField;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.EOFException;import java.io.IOException;import java.net.Socket;import java.net.SocketException;import java.net.UnknownHostException;import javax.swing.JFrame;public class ChatClient extends JFrame {TextArea textArea = new TextArea();// 建立一個文本域TextField textField = new TextField();// 建立一個文字框Button button_send = new Button("發送");Thread t = new Thread(new RecvThread());Socket s = null;DataInputStream dis = null;DataOutputStream dos = null;String str = null;boolean flag = false;    public void launchFrame(){this.setLocation(400, 400);//this.setSize(300, 300);//button_send.setSize(20, 20);this.add(textArea,BorderLayout.NORTH);this.add(textField,BorderLayout.SOUTH);this.add(button_send,BorderLayout.EAST);//this.setResizable(true);pack();this.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent arg0) {disConnect();System.exit(0);}});//this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//匿名內部類對發送按鈕進行響應,發送資訊button_send.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e){str = textField.getText().trim();//textArea.setText(str);textField.setText("");try {dos.writeUTF(str);dos.flush();} catch (IOException e1) {e1.printStackTrace();}}});setVisible(true);connect();t.start();}//從伺服器接收資訊class RecvThread implements Runnable{@Overridepublic void run() {try {while(flag){str = dis.readUTF();textArea.setText(textArea.getText() + str + '\n');}}catch (SocketException e) {System.out.println("退出了,bye!");} catch (EOFException e) {System.out.println("退出了,bye - bye!");} catch (IOException e) {e.printStackTrace();} }}//串連到伺服器public void connect(){try {s = new Socket("127.0.0.1",8888);flag = true;System.out.println("已經串連到伺服器");dis = new DataInputStream(s.getInputStream());dos = new DataOutputStream(s.getOutputStream());} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}//中斷連線public void disConnect(){try {dis.close();dos.close();s.close();} catch(SocketException e2){System.out.println("用戶端關閉了,bye");}catch (EOFException e1){System.out.println("用戶端關閉了,bye");//catch還有先後順序啊?}catch (IOException e) {System.out.println("串連已經斷開");e.printStackTrace();}}public static void main(String[] args) {new ChatClient().launchFrame();}}

打包成JAR檔案方式:

        在MyEclipse中,選中項目名,右擊--export--jar--打包成client和server兩個JAR檔案,啟動並執行時候,先運行server再運行client,IP設定為127.0.0.1,所以開啟兩個用戶端,自己和自己通訊。

假如我想和A通訊,那麼設定為A的IP,然後他開啟server和client,我也開啟一個server和client,就可以通訊了。


自己剛學這方面知識,所以程式只能簡單的通訊,有以下疑問:

      1、我我每次關掉視窗,通訊結束的時候,只能通過殺進程的方式關閉麼。要不然下一次好像起不來啊?

      2、QQ的原始碼哪裡可以下載到嗎?

      3、是不是我這樣的程式用到的是TCP ,因為程式中有建立串連這個環節啊

      4、不知道我打包JAR檔案的方式是否正確。不能把client和server打包在一起麼。。。。


第一個項目,所以各種迷惑。。。。。


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.