java編程_socket_套接字_網絡編程


============================================================ 

                                          1.實現server和client模型程序

============================================================ 

實現原理:

============================================================ 

服務器,使用ServerSocket監聽指定的端口,端口可以隨意指定(由於1024以下的端口通常屬於保留端口,

在一些操作系統中不可以隨意使用,所以建議使用大於1024的端口),

等待客戶連接請求,客戶連接后,會話產生;在完成會話后,關閉連接。  

============================================================ 
客戶端,使用Socket對網絡上某一個服務器的某一個端口發出連接請求,一旦連接成功,打開會話;會話完成后,

關閉Socket。客戶端不需要指定打開的端口,通常臨時的、動態的分配一個1024以上的端口。

============================================================ 

服務器端代碼:

 1 package com.b510.socket1703;
 2 
 3 import java.io.*;
 4 import java.net.Socket;
 5 import java.net.ServerSocket;
 6 
 7 /**
 8  * 服務器斷的工作就是在指定的端口上監聽
 9  * <li>建立連接</li>
10  * <li>打開輸出流</li>
11  * <li>封裝輸出流</li>
12  * <li>向客戶端發送數據</li>
13  * <li>關閉打開的輸出流</li>
14  * <li>關閉打開的socket對象</li>
15  * 
16  * @author Hongten
17  * 
18  * @time 2012-4-29  2012
19  */
20 public class TestServer {
21     public static void main(String args[]) {
22         try {
23             // 指定服務器端的端口號為8888
24             ServerSocket s = new ServerSocket(8888);
25             while (true) {
26                 // 建立連接
27                 Socket socket = s.accept();
28                 // 打開輸出流
29                 OutputStream os = socket.getOutputStream();
30                 // 封裝輸出流
31                 DataOutputStream dos = new DataOutputStream(os);
32                 // s<li>.getInetAddress()獲取遠程ip地址,s<li>.getPort()遠程客戶端的斷后好
33                 // 向客戶端發送數據
34                 dos.writeUTF("你好,客戶端地址信息: " + socket.getInetAddress()
35                         + "\t客戶端通信端口號: " + socket.getPort());
36                 dos.writeUTF("i'm a server ,my name is hongten!");
37                 // 關閉打開的輸出流
38                 dos.close();
39                 // 關閉打開的socket對象
40                 socket.close();
41             }// 開始下一此循環
42         } catch (IOException e) {
43             e.printStackTrace();
44         }
45     }
46 }

客戶端代碼:

 1 package com.b510.socket1703;
 2 
 3 import java.io.*;
 4 import java.net.Socket;
 5 
 6 /**
 7  * 客戶端
 8  * @author Hongten
 9  * 
10  * @time 2012-4-29 2012
11  */
12 public class TestClient {
13     public static void main(String args[]) {
14         try {
15             // 創建socket對象,指定服務器的ip地址,和服務器監聽的端口號
16             // 客戶端在new的時候,就發出了連接請求,服務器端就會進行處理,如果服務器端沒有開啟服務,那么
17             // 這時候就會找不到服務器,並同時拋出異常==》java.net.ConnectException: Connection
18             // refused: connect
19             Socket s1 = new Socket("127.0.0.1", 8888);
20             // 打開輸入流
21             InputStream is = s1.getInputStream();
22             // 封裝輸入流
23             DataInputStream dis = new DataInputStream(is);
24             // 打印服務器端發送過來的信息
25             System.out.println(dis.readUTF());
26             System.out.println(dis.readUTF());
27             // 關閉輸入流
28             dis.close();
29             // 關閉打開的socket對象
30             s1.close();
31         } catch (IOException e) {
32             e.printStackTrace();
33         }
34     }
35 }

如果服務器端沒有打開,這時候運行客戶端,出現的結果:

 1 java.net.ConnectException: Connection refused: connect
 2     at java.net.PlainSocketImpl.socketConnect(Native Method)
 3     at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
 4     at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
 5     at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
 6     at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
 7     at java.net.Socket.connect(Socket.java:518)
 8     at java.net.Socket.connect(Socket.java:468)
 9     at java.net.Socket.<init>(Socket.java:365)
10     at java.net.Socket.<init>(Socket.java:179)
11     at com.b510.socket1703.TestClient.main(TestClient.java:19)

如果服務器端先打開服務,這時候客戶端連接服務器端,出現的效果:

1 你好,客戶端地址信息: /127.0.0.1    客戶端通信端口號: 2800
2 i'm a server ,my name is hongten!

============================================================ 

                                              2.實現單線程的聊天室

============================================================ 

服務器端代碼:

 1 package com.b510.socket1704.simplechatroom;
 2 
 3 import java.io.*;
 4 import java.net.Socket;
 5 import java.net.ServerSocket;
 6 import java.net.SocketException;
 7 
 8 /**
 9  * 服務器端程序,在while循環中所執行的動作是:
10  * 聽,說,聽,說,聽,說...
11  * 
12  * @author Hongten
13  * 
14  * @time 2012-4-29 2012
15  */
16 public class TestServer {
17     public static void main(String args[]) {
18         try {
19             //創建一個socket對象
20             ServerSocket s = new ServerSocket(8888);
21             //socket對象調用accept方法,等待連接請求
22             Socket s1 = s.accept();
23             //打開輸出流
24             OutputStream os = s1.getOutputStream();
25             //封裝輸出流
26             DataOutputStream dos = new DataOutputStream(os);
27             //打開輸入流
28             InputStream is = s1.getInputStream();
29             //封裝輸入流
30             DataInputStream dis = new DataInputStream(is);
31             //讀取鍵盤輸入流
32             InputStreamReader isr = new InputStreamReader(System.in);
33             //封裝鍵盤輸入流
34             BufferedReader br = new BufferedReader(isr);
35 
36             String info;
37             while (true) {
38                 //接受客戶端發送過來的信息
39                 info = dis.readUTF();
40                 //打印接受的信息
41                 System.out.println("對方說: " + info);
42                 //如果發現接受的信息為:bye,那么就結束對話
43                 if (info.equals("bye"))
44                     break;
45                 //讀取鍵盤的輸入流
46                 info = br.readLine();
47                 //寫入到網絡連接的另一邊,即客戶端
48                 dos.writeUTF(info);
49                 //如果服務器自己說:bye,也是結束對話
50                 if (info.equals("bye"))
51                     break;
52             }
53             //關閉輸入流
54             dis.close();
55             //關閉輸出流
56             dos.close();
57             //關閉socket對象
58             s1.close();
59             s.close();
60         } catch (SocketException e) {
61             System.out.println("網絡連接異常,程序退出!");
62         } catch (IOException e) {
63             e.printStackTrace();
64         }
65     }
66 }

 

客戶端代碼:

 1 package com.b510.socket1704.simplechatroom;
 2 
 3 import java.io.*;
 4 import java.net.Socket;
 5 import java.net.SocketException;
 6 /**
 7  * 客戶端程序,在while循環中所執行的動作是:
 8  * 說,聽,說,聽,說,聽....
 9  * @author Hongten
10  *
11  * @time 2012-4-29  2012
12  */
13 public class TestClient {
14     public static void main(String args[]) {
15         try {
16             // 創建socket對象,指定服務器的ip地址,和服務器監聽的端口號
17             // 客戶端在new的時候,就發出了連接請求,服務器端就會進行處理,如果服務器端沒有開啟服務,那么
18             // 這時候就會找不到服務器,並同時拋出異常==》java.net.ConnectException: Connection
19             // refused: connect
20             Socket s1 = new Socket("localhost", 8888);
21             //打開輸出流
22             OutputStream os = s1.getOutputStream();
23             //封裝輸出流
24             DataOutputStream dos = new DataOutputStream(os);
25             //打開輸入流
26             InputStream is = s1.getInputStream();
27             //封裝輸入流
28             DataInputStream dis = new DataInputStream(is);
29             //讀取鍵盤輸入流
30             InputStreamReader isr = new InputStreamReader(System.in);
31             //封裝鍵盤輸入流
32             BufferedReader br = new BufferedReader(isr);
33 
34             String info;
35             while (true) {
36                 //客戶端先讀取鍵盤輸入信息
37                 info = br.readLine();
38                 //把他寫入到服務器方
39                 dos.writeUTF(info);
40                 //如果客戶端自己說:bye,即結束對話
41                 if (info.equals("bye"))
42                     break;
43                 //接受服務器端信息
44                 info = dis.readUTF();
45                 //打印
46                 System.out.println("對方說: " + info);
47                 if (info.equals("bye"))
48                     break;
49             }
50             //關閉相應的輸入流,輸出流,socket對象
51             dis.close();
52             dos.close();
53             s1.close();
54         } catch (IOException e) {
55             e.printStackTrace();
56         }
57     }
58 }

運行效果:

服務器端效果>>>

1 對方說: hell
2 你好
3 對方說: 嘿嘿
4 你今天
5 對方說: 13
6 代售點

客戶端端效果>>>

1 hell
2 對方說: 你好
3 嘿嘿
4 對方說: 你今�?
5 13
6 對方說: 代售�?

當前的程序不管是服務器端,還是客戶端,都是單線程的。如: 服務器端說:"你好"

1 //讀取鍵盤的輸入流
2 info = br.readLine();
3 //寫入到網絡連接的另一邊,即客戶端
4 dos.writeUTF(info);
5 //如果服務器自己說:bye,也是結束對話

通過上面的代碼,把"你好"發送出去了,這時候,程序又開始循環,運行到:

1 //接受客戶端發送過來的信息
2 info = dis.readUTF();

這段代碼,其實在這里就阻塞在這里了。要等到客戶端那邊說了話,"嘿嘿",這時候這里的
阻塞才會變為非阻塞狀態,然后又繼續說,說完后又繼續阻塞......

而對於客戶端來說,其實是一樣的道理,客戶端說完"hello"后,進入:

1 //接受服務器端信息
2 info = dis.readUTF();

到收聽服務器端的信息,在這里也產生了阻塞,只有服務器端說了"你好",這個阻塞才變為非阻塞
狀態。然后又繼續接下來的動作....

============================================================ 

                                              3.實現多線程的聊天室

============================================================ 

服務器端代碼:

 

 1 package com.b510.socket1705.freeechatroom;
 2 
 3 import java.io.*;
 4 import java.net.*;
 5 
 6 /**
 7  * 服務器端程序
 8  * 
 9  * @author Hongten
10  * 
11  * @time 2012-4-29 2012
12  */
13 public class TestServer {
14     public static void main(String args[]) {
15         try {
16             // 創建一個socket對象
17             ServerSocket s = new ServerSocket(8888);
18             // socket對象調用accept方法,等待連接請求
19             Socket s1 = s.accept();
20 
21             // =========服務器端,在這里應該先打開輸出流,在打開輸入流,
22             // =========因為服務器端執行的操作是先聽,再說,聽,說,聽,說.....
23 
24             // 打開輸出流
25             OutputStream os = s1.getOutputStream();
26             // 封裝輸出流
27             DataOutputStream dos = new DataOutputStream(os);
28             // 打開輸入流
29             InputStream is = s1.getInputStream();
30             // 封裝輸入流
31             DataInputStream dis = new DataInputStream(is);
32             // 創建並啟用兩個線程
33             new MyServerReader(dis).start();
34             new MyServerWriter(dos).start();
35         } catch (IOException e) {
36             e.printStackTrace();
37         }
38     }
39 }
40 
41 // 接受並打印客戶端傳過來的信息
42 class MyServerReader extends Thread {
43     private DataInputStream dis;
44 
45     public MyServerReader(DataInputStream dis) {
46         this.dis = dis;
47     }
48 
49     public void run() {
50         String info;
51         try {
52             while (true) {
53                 // 如果對方,即客戶端沒有說話,那么就會阻塞到這里,
54                 // 這里的阻塞並不會影響到其他線程
55                 info = dis.readUTF();
56                 // 如果狀態有阻塞變為非阻塞,那么就打印接受到的信息
57                 System.out.println("對方說: " + info);
58                 if (info.equals("bye")) {
59                     System.out.println("對方下線,程序退出!");
60                     System.exit(0);
61                 }
62             }
63         } catch (IOException e) {
64             e.printStackTrace();
65         }
66     }
67 }
68 
69 // 從鍵盤獲得輸入流並寫入信息到客戶端
70 class MyServerWriter extends Thread {
71     private DataOutputStream dos;
72 
73     public MyServerWriter(DataOutputStream dos) {
74         this.dos = dos;
75     }
76 
77     public void run() {
78         // 讀取鍵盤輸入流
79         InputStreamReader isr = new InputStreamReader(System.in);
80         // 封裝鍵盤輸入流
81         BufferedReader br = new BufferedReader(isr);
82         String info;
83         try {
84             while (true) {
85                 info = br.readLine();
86                 dos.writeUTF(info);
87                 if (info.equals("bye")) {
88                     System.out.println("自己下線,程序退出!");
89                     System.exit(0);
90                 }
91             }
92         } catch (IOException e) {
93             e.printStackTrace();
94         }
95     }
96 }

 

客戶端代碼:

 1 package com.b510.socket1705.freeechatroom;
 2 
 3 import java.io.*;
 4 import java.net.*;
 5 
 6 /**
 7  * 客戶端程序
 8  * 
 9  * @author Hongten
10  * 
11  * @time 2012-4-29 2012
12  */
13 public class TestClient {
14     public static void main(String args[]) {
15         try {
16             // 創建socket對象,指定服務器的ip地址,和服務器監聽的端口號
17             // 客戶端在new的時候,就發出了連接請求,服務器端就會進行處理,如果服務器端沒有開啟服務,那么
18             // 這時候就會找不到服務器,並同時拋出異常==》java.net.ConnectException: Connection
19             // refused: connect
20             Socket s1 = new Socket("127.0.0.1", 8888);
21 
22             // =========客戶端,在這里應該先打開輸入流,在打開輸出流,
23             // =========因為客戶端執行的操作是先說,再聽,說,聽,說,聽.....
24 
25             // 打開輸入流
26             InputStream is = s1.getInputStream();
27             // 封裝輸入流
28             DataInputStream dis = new DataInputStream(is);
29             // 打開輸出流
30             OutputStream os = s1.getOutputStream();
31             // 封裝輸出流
32             DataOutputStream dos = new DataOutputStream(os);
33 
34             // 創建並啟用兩個線程
35             new MyClientReader(dis).start();
36             new MyClientWriter(dos).start();
37         } catch (IOException e) {
38             e.printStackTrace();
39         }
40     }
41 }
42 
43 // 接受並打印服務器端傳過來的信息
44 class MyClientReader extends Thread {
45     private DataInputStream dis;
46 
47     public MyClientReader(DataInputStream dis) {
48         this.dis = dis;
49     }
50 
51     public void run() {
52         String info;
53         try {
54             while (true) {
55                 info = dis.readUTF();
56                 System.out.println("對方說: " + info);
57                 if (info.equals("bye")) {
58                     System.out.println("對方下線,程序退出!");
59                     System.exit(0);
60                 }
61             }
62         } catch (IOException e) {
63             e.printStackTrace();
64         }
65     }
66 }
67 
68 // 從鍵盤獲得輸入流並寫入信息到服務器端
69 class MyClientWriter extends Thread {
70     private DataOutputStream dos;
71 
72     public MyClientWriter(DataOutputStream dos) {
73         this.dos = dos;
74     }
75 
76     public void run() {
77         InputStreamReader isr = new InputStreamReader(System.in);
78         BufferedReader br = new BufferedReader(isr);
79         String info;
80         try {
81             while (true) {
82                 info = br.readLine();
83                 dos.writeUTF(info);
84                 if (info.equals("bye")) {
85                     System.out.println("自己下線,程序退出!");
86                     System.exit(0);
87                 }
88             }
89         } catch (IOException e) {
90             e.printStackTrace();
91         }
92     }
93 }

客戶端運行效果:

1 這是客戶端
2 我是hongten
3 這是我說的第三句話,haha
4 對方說: 我是服務器端,這說我說的第一句話,hehe

服務器端運行效果:

1 對方說: 這是客戶�?
2 對方說: 我是hongten
3 對方說: 這是我說的第三句話,haha
4 我是服務器端,這說我說的第一句話,hehe

程序中加入了多線程后,不管是服務器端,還是客戶端,都可以連續的說話,另一邊連續的聽...

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM