天天看點

socket通信程式設計

Socket程式設計

一、網絡基礎知識(參考計算機網絡)

關于計算機網絡部分可以參考相關部落格:

《TCP/IP協定棧及OSI參考模型詳解》

http://wangdy.blog.51cto.com/3845563/1588379

1、兩台計算機間進行通訊需要以下三個條件:

IP位址、協定、端口号

2、TCP/IP協定:

是目前世界上應用最為廣泛的協定,是以TCP和IP為基礎的不同層次上多個協定的集合,也成TCP/IP協定族、或TCP/IP協定棧

TCP:Transmission Control Protocol 傳輸控制協定

IP:Internet Protocol 網際網路協定

3、TCP/IP五層模型

應用層:HTTP、FTP、SMTP、Telnet等

傳輸層:TCP/IP

網絡層:

資料鍊路層:

實體層:網線、雙絞線、網卡等

4、IP位址

為實作網絡中不同計算機之間的通信,每台計算機都必須有一個唯一的辨別—IP位址。

32位二進制

5、端口

區分一台主機的多個不同應用程式,端口号範圍為0-65535,其中0-1023位為系統保留。

如:HTTP:80 FTP:21 Telnet:23

IP位址+端口号組成了所謂的Socket,Socket是網絡上運作的程式之間雙向通信鍊路的終結點,是TCP和UDP的基礎

6、Socket套接字:

網絡上具有唯一辨別的IP位址和端口組合在一起才能構成唯一能識别的辨別符套接字。

Socket原理機制:

通信的兩端都有Socket

網絡通信其實就是Socket間的通信

資料在兩個Socket間通過IO傳輸

7、Java中的網絡支援

針對網絡通信的不同層次,Java提供了不同的API,其提供的網絡功能有四大類:

InetAddress:用于辨別網絡上的硬體資源,主要是IP位址

URL:統一資源定位符,通過URL可以直接讀取或寫入網絡上的資料

Sockets:使用TCP協定實作的網絡通信Socket相關的類

Datagram:使用UDP協定,将資料儲存在使用者資料報中,通過網絡進行通信。

二、InetAddress

InetAddress類用于辨別網絡上的硬體資源,辨別網際網路協定(IP)位址。

該類沒有構造方法

1 //擷取本機的InetAddress執行個體

2 InetAddress address =InetAddress.getLocalHost();

3 address.getHostName();//擷取計算機名

4 address.getHostAddress();//擷取IP位址

5 byte[] bytes = address.getAddress();//擷取位元組數組形式的IP位址,以點分隔的四部分

6

7 //擷取其他主機的InetAddress執行個體

8 InetAddress address2 =InetAddress.getByName(“其他主機名”);

9 InetAddress address3 =InetAddress.getByName(“IP位址”);

複制代碼

三、URL類

1、URL(Uniform Resource Locator)統一資源定位符,表示Internet上某一資源的位址,協定名:資源名稱

1 //建立一個URL的執行個體

2 URL baidu =new URL(“http://www.baidu.com“);

3 URL url =new URL(baidu,”/index.html?username=tom#test”);//?表示參數,#表示錨點

4 url.getProtocol();//擷取協定

5 url.getHost();//擷取主機

6 url.getPort();//如果沒有指定端口号,根據協定不同使用預設端口。此時getPort()方法的傳回值為 -1

7 url.getPath();//擷取檔案路徑

8 url.getFile();//檔案名,包括檔案路徑+參數

9 url.getRef();//相對路徑,就是錨點,即#号後面的内容

10 url.getQuery();//查詢字元串,即參數

2、使用URL讀取網頁内容
       通過URL對象的openStream()方法可以得到指定資源的輸入流,通過流能夠讀取或通路網頁上的資源      
           

1 //使用URL讀取網頁内容

2 //建立一個URL執行個體

3 URL url =new URL(“http://www.baidu.com“);

4 InputStream is = url.openStream();//通過openStream方法擷取資源的位元組輸入流

5 InputStreamReader isr =newInputStreamReader(is,”UTF-8”);//将位元組輸入流轉換為字元輸入流,如果不指定編碼,中文可能會出現亂碼

6 BufferedReader br =newBufferedReader(isr);//為字元輸入流添加緩沖,提高讀取效率

7 String data = br.readLine();//讀取資料

8 while(data!=null){

9 System.out.println(data);//輸出資料

10 data = br.readerLine();

11 }

12 br.close();

13 isr.colose();

14 is.close();

四、TCP程式設計

1、TCP協定是面向連接配接的、可靠的、有序的、以位元組流的方式發送資料,通過三次握手方式建立連接配接,形成傳輸資料的通道,在連接配接中進行大量資料的傳輸,效率會稍低

2、Java中基于TCP協定實作網絡通信的類

用戶端的Socket類

伺服器端的ServerSocket類

3、Socket通信的步驟
             ① 建立ServerSocket和Socket
             ② 打開連接配接到Socket的輸入/輸出流
             ③ 按照協定對Socket進行讀/寫操作
             ④ 關閉輸入輸出流、關閉Socket
       4、伺服器端:
             ① 建立ServerSocket對象,綁定監聽端口
             ② 通過accept()方法監聽用戶端請求
             ③ 連接配接建立後,通過輸入流讀取用戶端發送的請求資訊
             ④ 通過輸出流向用戶端發送鄉音資訊
             ⑤ 關閉相關資源
           

1

4 //1、建立一個伺服器端Socket,即ServerSocket,指定綁定的端口,并監聽此端口

5 ServerSocket serverSocket =newServerSocket(10086);//1024-65535的某個端口

6 //2、調用accept()方法開始監聽,等待用戶端的連接配接

7 Socket socket = serverSocket.accept();

8 //3、擷取輸入流,并讀取用戶端資訊

9 InputStream is = socket.getInputStream();

10 InputStreamReader isr =newInputStreamReader(is);

11 BufferedReader br =newBufferedReader(isr);

12 String info =null;

13 while((info=br.readLine())!=null){

14 System.out.println(“我是伺服器,用戶端說:”+info);

15 }

16 socket.shutdownInput();//關閉輸入流

17 //4、擷取輸出流,響應用戶端的請求

18 OutputStream os = socket.getOutputStream();

19 PrintWriter pw = new PrintWriter(os);

20 pw.write(“歡迎您!”);

21 pw.flush();

22

23

24 //5、關閉資源

25 pw.close();

26 os.close();

27 br.close();

28 isr.close();

29 is.close();

30 socket.close();

31 serverSocket.close();

5、用戶端:

             ① 建立Socket對象,指明需要連接配接的伺服器的位址和端口号
             ② 連接配接建立後,通過輸出流想伺服器端發送請求資訊
             ③ 通過輸入流擷取伺服器響應的資訊
             ④ 關閉響應資源 
           

1 //用戶端

2 //1、建立用戶端Socket,指定伺服器位址和端口

3 Socket socket =newSocket(“localhost”,10086);

4 //2、擷取輸出流,向伺服器端發送資訊

5 OutputStream os = socket.getOutputStream();//位元組輸出流

6 PrintWriter pw =newPrintWriter(os);//将輸出流包裝成列印流

7 pw.write(“使用者名:admin;密碼:123”);

8 pw.flush();

9 socket.shutdownOutput();

10 //3、擷取輸入流,并讀取伺服器端的響應資訊

11 InputStream is = socket.getInputStream();

12 BufferedReader br = new BufferedReader(new InputStreamReader(is));

13 String info = null;

14 while((info=br.readLine())!null){

15 System.out.println(“我是用戶端,伺服器說:”+info);

16 }

17

18 //4、關閉資源

19 br.close();

20 is.close();

21 pw.close();

22 os.close();

23 socket.close();

6、應用多線程實作伺服器與多用戶端之間的通信

           ① 伺服器端建立ServerSocket,循環調用accept()等待用戶端連接配接
           ② 用戶端建立一個socket并請求和伺服器端連接配接
           ③ 伺服器端接受苦讀段請求,建立socket與該客戶建立專線連接配接
           ④ 建立連接配接的兩個socket在一個單獨的線程上對話
           ⑤ 伺服器端繼續等待新的連接配接        
           

1 //伺服器線程處理

2 //和本線程相關的socket

3 Socket socket =null;

4 //

5 public serverThread(Socket socket){

6 this.socket = socket;

7 }

8

9 publicvoid run(){

10 //伺服器處理代碼

11 }

12

13 //============================================

14 //伺服器代碼

15 ServerSocket serverSocket =newServerSocket(10086);

16 Socket socket =null;

17 int count =0;//記錄用戶端的數量

18 while(true){

19 socket = serverScoket.accept();

20 ServerThread serverThread =newServerThread(socket);

21 serverThread.start();

22 count++;

23 System.out.println(“用戶端連接配接的數量:”+count);

24 }

五、UDP程式設計

UDP協定(使用者資料報協定)是無連接配接的、不可靠的、無序的,速度快

進行資料傳輸時,首先将要傳輸的資料定義成資料報(Datagram),大小限制在64k,在資料報中指明資料索要達到的Socket(主機位址和端口号),然後再将資料報發送出去

DatagramPacket類:表示資料報包

DatagramSocket類:進行端到端通信的類

1、伺服器端實作步驟

① 建立DatagramSocket,指定端口号

② 建立DatagramPacket

③ 接受用戶端發送的資料資訊

④ 讀取資料

1 //伺服器端,實作基于UDP的使用者登入

2 //1、建立伺服器端DatagramSocket,指定端口

3 DatagramSocket socket =new datagramSocket(10010);

4 //2、建立資料報,用于接受用戶端發送的資料

5 byte[] data =newbyte[1024];//

6 DatagramPacket packet =newDatagramPacket(data,data.length);

7 //3、接受用戶端發送的資料

8 socket.receive(packet);//此方法在接受資料報之前會一緻阻塞

9 //4、讀取資料

10 String info =newString(data,o,data.length);

11 System.out.println(“我是伺服器,用戶端告訴我”+info);

12

13

14 //=========================================================

15 //向用戶端響應資料

16 //1、定義用戶端的位址、端口号、資料

17 InetAddress address = packet.getAddress();

18 int port = packet.getPort();

19 byte[] data2 = “歡迎您!”.geyBytes();

20 //2、建立資料報,包含響應的資料資訊

21 DatagramPacket packet2 = new DatagramPacket(data2,data2.length,address,port);

22 //3、響應用戶端

23 socket.send(packet2);

24 //4、關閉資源

25 socket.close();

2、用戶端實作步驟

       ① 定義發送資訊
       ② 建立DatagramPacket,包含将要發送的資訊
       ③ 建立DatagramSocket
       ④ 發送資料
           

1 //用戶端

2 //1、定義伺服器的位址、端口号、資料

3 InetAddress address =InetAddress.getByName(“localhost”);

4 int port =10010;

5 byte[] data =”使用者名:admin;密碼:123”.getBytes();

6 //2、建立資料報,包含發送的資料資訊

7 DatagramPacket packet = newDatagramPacket(data,data,length,address,port);

8 //3、建立DatagramSocket對象

9 DatagramSocket socket =newDatagramSocket();

10 //4、向伺服器發送資料

11 socket.send(packet);

12

13

14 //接受伺服器端響應資料

15 //======================================

16 //1、建立資料報,用于接受伺服器端響應資料

17 byte[] data2 = new byte[1024];

18 DatagramPacket packet2 = new DatagramPacket(data2,data2.length);

19 //2、接受伺服器響應的資料

20 socket.receive(packet2);

21 String raply = new String(data2,0,packet2.getLenth());

22 System.out.println(“我是用戶端,伺服器說:”+reply);

23 //4、關閉資源

24 socket.close();

六、注意問題:

1、多線程的優先級問題:
        根據實際的經驗,适當的降低優先級,否側可能會有程式運作效率低的情況
2、是否關閉輸出流和輸入流:
         對于同一個socket,如果關閉了輸出流,則與該輸出流關聯的socket也會被關閉,是以一般不用關閉流,直接關閉socket即可
 3、使用TCP通信傳輸對象,IO中序列化部分
 4、socket程式設計傳遞檔案,IO流部分
           

繼續閱讀