qileilove

          blog已經轉移至github,大家請訪問 http://qaseven.github.io/

          Java的Socket網絡編程以及多線程

           1.Socket是代表兩臺機器之間網絡連接的對象(java.net.Socket)。
            Socket的建立如下,參數分別是服務器端的IP地址和端口號: Socket socket  =  new Socket("167.5.75.1",5000);
            2.客戶端(Client)Socket的使用
            2.1 從Socket讀出數據步驟:
          // 1.創建Socket連接,告知Server的IP地址以及端口號
          Socket socket = new Socket("127.0.0.1", 4242);
          // 2.創建InputStreamReader,用于讀取socket輸入流
          InputStreamReader stream = new InputStreamReader(socket.getInputStream());
          // 3.使用BufferedReader鏈接輸入流
          BufferedReader br = new BufferedReader(stream);
          // 4.讀出數據
          String line = null;
          while ((line = br.readLine()) != null)
          {
          System.out.println("Today's advice is: " + line);
          }
          // 5. 關閉輸入流BufferedReader
          br.close();
            2.2 向Scoket寫入數據步驟:
          // 1.創建Socket連接,告知Server的IP地址以及端口號
          Socket socket = new Socket("127.0.0.1", 4242);
          // 2.創建PrintWriter對象,用以接收socket輸出流
          PrintWriter writer = new PrintWriter(socket.getOutputStream());
          // 3.使用PrintWriter對象寫出輸出數據
          String advice ="Today's advice";
          writer.println(advice);
          // 4. 關閉連接
          writer.close();
            3.  服務器端(Server)Socket的使用
          // 1.創建一個SercerSocket,使用4242端口監聽客戶端請求
          ServerSocket serverSocket = new ServerSocket(4242);
          System.out.println("The server is started, listening on port 4242");
          while (true)
          {
          // 2.ServerSocket的accept()在等待用戶連接的時候閑置;在用戶連接上來的時候,返回一個Socket來與客戶端通信
          Socket socket = serverSocket.accept();
          // 3.創建PrintWriter對象,用以接收socket輸出流
          PrintWriter writer = new PrintWriter(socket.getOutputStream());
          // 4.使用PrintWriter對象寫出輸出數據
          String advice = "notifier's blog";
          writer.println(advice);
          // 5. 關閉連接
          writer.close();
          }

           4.   線程的狀態
            線程總共有5種狀態:
            1. 新建 (Thread t = new Thread())
            2. 就緒 (t.start())
            3. 運行
            4. 堵塞
            線程被block的原因很多,比如: 等待IO操作, sleep(), 等待被占用對象釋放
            5.死亡
            5.解決線程同步化問題的方法是: 對使用到共享對象的方法使用synchronized
            需要注意的是:
            雖說是方法進行了synchronized,但鎖不是加在方法上的而是對象上的,也就是說,是synchronized方法獲取對象鎖。如果對象(類)有兩個或者多個synchronized方法,就表示兩個線程不能同時進入同一個方法,也不能同時進入不同的方法。 因為同一時間,只有一個方法在占有對象鎖。
            6.synchronized代碼塊
            有時候在一個方法中做了很多事情,但只有一部分邏輯是需要synchronized的,這時候我們可以使用synchronized代碼塊。如下,其中this表示當前對象:
          public void function()
          {
          doSomething();
          //以下方法需要同步化
          synchronized (this)
          {
          doCriticalStuff();
          moreCriticalStuff();
          }
          doSomeOtherThing();
          }
            7. 以下是一個Socket簡單的例子:
            客戶端代碼及詳細注釋:
          /**
          * @author notifier
          * @create 2010-9-25 上午10:12:10
          * @version 1.0
          */
          public class DailyAdviceClient
          {
          public static void main(String[] args)
          {
          DailyAdviceClient client = new DailyAdviceClient();
          client.receiveMsg();
          }
          public void receiveMsg()
          {
          try
          {
          // 1.創建Socket連接,告知Server的IP地址以及端口號
          Socket socket = new Socket("127.0.0.1", 4242);
          // 2.創建InputStreamReader,用于讀取socket輸入流
          InputStreamReader stream = new InputStreamReader(socket
          .getInputStream());
          // 3.使用BufferedReader鏈接輸入流
          BufferedReader br = new BufferedReader(stream);
          // 4.讀出數據
          String line = null;
          while ((line = br.readLine()) != null)
          {
          System.out.println("Today's advice is: " + line);
          }
          // 5. 關閉輸入流BufferedReader
          br.close();
          } catch (UnknownHostException e)
          {
          e.printStackTrace();
          } catch (IOException e)
          {
          e.printStackTrace();
          }
          }
          }
           服務器端代碼及詳細注釋:
          /**
          * @author notifier
          * @create 2010-9-25 下午07:06:54
          * @version 1.0
          */
          public class SimpleChatServer
          {
          // 保存客戶端列表
          private ArrayList clientList = new ArrayList();;
          public static void main(String[] args)
          {
          new SimpleChatServer().startUp();
          }
          /**
          * 負責服務器端的啟動
          *
          */
          public void startUp()
          {
          try
          {
          // 創建服務器端ServerSocket連接,監聽端口號5000
          ServerSocket serverSocket = new ServerSocket(5000);
          // 輪詢等待客戶端請求
          while(true)
          {
          // 等待客戶端請求,無請求則閑置;有請求到來時,返回一個對該請求的socket連接
          Socket clientSocket = serverSocket.accept();
          // 將該客戶端加入到列表中
          PrintWriter writer = new PrintWriter(clientSocket.getOutputStream());
          clientList.add(writer);
          // 創建ClientHandler對象,通過socket連接通信
          Thread t = new Thread(new ClientHandler(clientSocket));
          t.start();
          System.out.println("有Client連進來");
          }
          }catch(Exception e)
          {
          e.printStackTrace();
          }
          }
          /**
          * 客戶端處理類, 主要負責:
          * 1.接收客戶端發來的消息
          * 2.將消息轉發其他客戶端
          * @author sdniu
          * @create 2010-9-26 上午10:00:18
          * @version 1.0
          */
          public class ClientHandler implements Runnable
          {
          private BufferedReader reader;
          private Socket socket;
          /**
          * ClientHandler的構造函數
          * @param clientSocket
          */
          public ClientHandler(Socket clientSocket)
          {
          try
          {
          // 得到socket連接
          socket = clientSocket;
          // 得到客戶端發來的消息
          InputStreamReader isReader = new InputStreamReader(socket.getInputStream());
          reader = new BufferedReader(isReader);
          } catch (IOException e)
          {
          e.printStackTrace();
          }
          }
          public void run()
          {
          String message;
          try
          {
          while((message = reader.readLine()) != null)
          {
          System.out.println("客戶端消息: " + message);
          // 將客戶端發來的消息轉發所有客戶端
          notifyAllClients(message);
          }
          } catch (IOException e)
          {
          e.printStackTrace();
          }
          }
          }
          /**
          *
          * @param message
          */
          public void notifyAllClients(String message)
          {
          // 得到客戶端列表的迭代器,語法格式為 Iterator it = clientList.iterator();
          Iterator it = clientList.iterator();
          while(it.hasNext())
          {
          try
          {
          // 得到的Iterator別忘了強制轉換回PrintWriter
          PrintWriter writer = (PrintWriter) it.next();
          writer.println(message);
          writer.flush();
          } catch (Exception e)
          {
          e.printStackTrace();
          }
          }
          }
          }
            8. 多線程Socket編程的例子, 代碼比較長, 放在下載里了, 鏈接如下:
            http://files.cnblogs.com/notifier/SimpleChatroom.7z

          posted on 2013-09-27 10:38 順其自然EVO 閱讀(185) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          <2013年9月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          導航

          統計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 施秉县| 兴宁市| 河曲县| 平乡县| 鸡东县| 城市| 怀仁县| 隆昌县| 内江市| 大理市| 博野县| 光泽县| 施甸县| 肇东市| 栾城县| 平山县| 吉木乃县| 临城县| 云林县| 称多县| 陕西省| 远安县| 汾阳市| 临夏市| 潼南县| 牡丹江市| 建平县| 东乡族自治县| 铜梁县| 泰来县| 湖南省| 嘉义县| 浦江县| 临沧市| 泽州县| 海门市| 岗巴县| 札达县| 军事| 七台河市| 屯昌县|