欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java使用Socket類接收和發(fā)送數(shù)據(jù)

 更新時間:2016年10月19日 14:21:15   作者:pangfc  
Socket類是負(fù)責(zé)處理客戶端通信的Java類。本文主要是介紹java使用Socket類接收和發(fā)送數(shù)據(jù),具有一定的參考價值,感興趣的小伙伴們可以參考一下。

網(wǎng)絡(luò)應(yīng)用分為客戶端和服務(wù)端兩部分,而Socket類是負(fù)責(zé)處理客戶端通信的Java類。通過這個類可以連接到指定IP或域名的服務(wù)器上,并且可以和服務(wù)器互相發(fā)送和接受數(shù)據(jù)。在本文及后面的數(shù)篇文章中將詳細(xì)討論Socket類的使用,內(nèi)容包括Socket類基礎(chǔ)、各式各樣的連接方式、get和set方法、連接過程中的超時以及關(guān)閉網(wǎng)絡(luò)連接等。

在本文中,我們將討論使用Socket類的基本步驟和方法。一般網(wǎng)絡(luò)客戶端程序在連接服務(wù)程序時要進(jìn)行以下三步操作。

  1. 連接服務(wù)器
  2. 發(fā)送和接收數(shù)據(jù)
  3. 關(guān)閉網(wǎng)絡(luò)連接

一、連接服務(wù)器

在客戶端可以通過兩種方式來連接服務(wù)器,一種是通過IP的方式來連接服務(wù)器,而另外一種是通過域名方式來連接服務(wù)器。

其實這兩種方式從本質(zhì)上來看是一種方式。在底層客戶端都是通過IP來連接服務(wù)器的,但這兩種方式有一定的差異,如果通過IP方式來連接服務(wù)端程序,客戶端只簡單地根據(jù)IP進(jìn)行連接,如果通過域名來連接服務(wù)器,客戶端必須通過DNS將域名解析成IP,然后再根據(jù)這個IP來進(jìn)行連接。

在很多程序設(shè)計語言或開發(fā)工具中(如C/C++、Delphi)使用域名方式連接服務(wù)器時必須自己先將域名解析成IP,然后再通過IP進(jìn)行連接,而在Java中已經(jīng)將域名解析功能包含在了Socket類中,因此,我們只需象使用IP一樣使用域名即可。

通過Socket類連接服務(wù)器程序最常用的方法就是通過Socket類的構(gòu)造函數(shù)將IP或域名以及端口號作為參數(shù)傳入Socket類中。Socket類的構(gòu)造函數(shù)有很多重載形式,在這一節(jié)只討論其中最常用的一種形式:public Socket(String host, int port)。從這個構(gòu)造函數(shù)的定義來看,只需要將IP或域名以及端口號直接傳入構(gòu)造函數(shù)即可。下面的代碼是一個連接服務(wù)端程序的例子程序:

package mysocket; 
import java.net.*; 
public class MyConnection
{
  public static void main(String[] args)
  {
    try
    {
      if (args.length > 0)
      {
        Socket socket = new Socket(args[0], 80);
        System.out.println(args[0] + "已連接成功!");
      }
      else
        System.out.println("請指定IP或域名!");
    }
    catch (Exception e)
    {
      System.err.println("錯誤信息:" + e.getMessage());
    }
  }
}

在上面的中,通過命令行參數(shù)將IP或域名傳入程序,然后通過Socket socket = new Socket(args[0], 80)連接通過命令行參數(shù)所指定的IP或域名的80端口。由于Socket類的構(gòu)造函數(shù)在定義時使用了throws,因此,在調(diào)用Socket類的構(gòu)造函數(shù)時,必須使用try…catch語句來捕捉錯誤,或者對main函數(shù)使用throws語句來拋出錯誤。

使用Socket類連接服務(wù)器可以判斷一臺主機有哪些端口被打開。下面的代碼是一個掃描本機有哪些端口被打開的程序。

二、發(fā)送和接收數(shù)據(jù)

在Socket類中最重要的兩個方法就是getInputStream和getOutputStream。這兩個方法分別用來得到用于讀取和寫入數(shù)據(jù)的InputStream和OutputStream對象。在這里的InputStream讀取的是服務(wù)器程序向客戶端發(fā)送過來的數(shù)據(jù),而OutputStream是客戶端要向服務(wù)端程序發(fā)送的數(shù)據(jù)。

在編寫實際的網(wǎng)絡(luò)客戶端程序時,是使用getInputStream,還是使用getOutputStream,以及先使用誰后使用誰由具體的應(yīng)用決定。如通過連接郵電出版社網(wǎng)站(www.ptpress.com.cn)的80端口(一般為HTTP協(xié)議所使用的默認(rèn)端口),并且發(fā)送一個字符串,最后再讀取從www.ptpress.com.cn返回的信息。

package mysocket;
import java.net.*;
import java.io.*; 
public class MyConnection2
{
  public static void main(String[] args) throws Exception
  {
    Socket socket = new Socket("www.ptpress.com.cn", 80);
    // 向服務(wù)端程序發(fā)送數(shù)據(jù)
    OutputStream ops = socket.getOutputStream();    
    OutputStreamWriter opsw = new OutputStreamWriter(ops);
    BufferedWriter bw = new BufferedWriter(opsw);
     
    bw.write("hello world\r\n\r\n");
    bw.flush();
     
    // 從服務(wù)端程序接收數(shù)據(jù)
    InputStream ips = socket.getInputStream();
    InputStreamReader ipsr = new InputStreamReader(ips);
    BufferedReader br = new BufferedReader(ipsr);
    String s = "";    
    while((s = br.readLine()) != null)
      System.out.println(s);    
    socket.close();
  }
}

在編寫上面代碼時要注意如下兩點:

1. 為了提高數(shù)據(jù)傳輸?shù)男?,Socket類并沒有在每次調(diào)用write方法后都進(jìn)行數(shù)據(jù)傳輸,而是將這些要傳輸?shù)臄?shù)據(jù)寫到一個緩沖區(qū)里(默認(rèn)是8192個字節(jié)),然后通過flush方法將這個緩沖區(qū)里的數(shù)據(jù)一起發(fā)送出去,因此,bw.flush();是必須的。

2. 在發(fā)送字符串時之所以在Hello World后加上 “\r\n\r\n”,這是因為HTTP協(xié)議頭是以“\r\n\r\n”作為結(jié)束標(biāo)志(HTTP協(xié)議的詳細(xì)內(nèi)容將在以后講解),因此,通過在發(fā)送字符串后加入“\r\n\r\n”,可以使服務(wù)端程序認(rèn)為HTTP頭已經(jīng)結(jié)束,可以處理了。如果不加“\r\n\r\n”,那么服務(wù)端程序?qū)⒁恢钡却鼿TTP頭的結(jié)束,也就是“\r\n\r\n”。如果是這樣,服務(wù)端程序就不會向客戶端發(fā)送響應(yīng)信息,而br.readLine()將因無法讀以響應(yīng)信息面被阻塞,直到連接超時。

三、關(guān)閉網(wǎng)絡(luò)連接

到現(xiàn)在為止,我們對Socket類的基本使用方法已經(jīng)有了初步的了解,但在Socket類處理完數(shù)據(jù)后,最合理的收尾方法是使用Socket類的close方法關(guān)閉網(wǎng)絡(luò)連接。雖然在中已經(jīng)使用了close方法,但使網(wǎng)絡(luò)連接關(guān)閉的方法不僅僅只有close方法,下面就讓我們看看Java在什么情況下可以使網(wǎng)絡(luò)連接關(guān)閉。

可以引起網(wǎng)絡(luò)連接關(guān)閉的情況有以下4種:

  1.  直接調(diào)用Socket類的close方法。
  2.  只要Socket類的InputStream和OutputStream有一個關(guān)閉,網(wǎng)絡(luò)連接自動關(guān)閉(必須通過調(diào)用InputStream和OutputStream的close方法關(guān)閉流,才能使網(wǎng)絡(luò)可愛接自動關(guān)閉)。
  3. 在程序退出時網(wǎng)絡(luò)連接自動關(guān)閉。
  4. 將Socket對象設(shè)為null或未關(guān)閉最使用new Socket(…)建立新對象后,由JVM的垃圾回收器回收為Socket對象分配的內(nèi)存空間后自動關(guān)閉網(wǎng)絡(luò)連接。  

雖然這4種方法都可以達(dá)到同樣的目的,但一個健壯的網(wǎng)絡(luò)程序最好使用第1種或第2種方法關(guān)閉網(wǎng)絡(luò)連接。這是因為第3種和第4種方法一般并不會馬上關(guān)閉網(wǎng)絡(luò)連接,如果是這樣的話,對于某些應(yīng)用程序,將會遺留大量無用的網(wǎng)絡(luò)連接,這些網(wǎng)絡(luò)連接會占用大量的系統(tǒng)資源。

在Socket對象被關(guān)閉后,我們可以通過isClosed方法來判斷某個Socket對象是否處于關(guān)閉狀態(tài)。然而使用isClosed方法所返回的只是Socket對象的當(dāng)前狀態(tài),也就是說,不管Socket對象是否曾經(jīng)連接成功過,只要處于關(guān)閉狀態(tài),isClosde就返回true。如果只是建立一個未連接的Socket對象,isClose也同樣返回true。如下面的代碼將輸出false。

Socket socket = new Socket();
System.out.println(socket.isClosed());

除了isClose方法,Socket類還有一個isConnected方法來判斷Socket對象是否連接成功??吹竭@個名字,也許讀者會產(chǎn)生誤解。其實isConnected方法所判斷的并不是Socket對象的當(dāng)前連接狀態(tài),而是Socket對象是否曾經(jīng)連接成功過,如果成功連接過,即使現(xiàn)在isClose返回true,isConnected仍然返回true。因此,要判斷當(dāng)前的Socket對象是否處于連接狀態(tài),必須同時使用isClose和isConnected方法,即只有當(dāng)isClose返回false,isConnected返回true的時候Socket對象才處于連接狀態(tài)。下面的代碼演示了上述Socket對象的各種狀態(tài)的產(chǎn)生過程。

package mysocket;
import java.net.*; 
public class MyCloseConnection
{
  public static void printState(Socket socket, String name)
  {
    System.out.println(name + ".isClosed():" + socket.isClosed());
    System.out.println(name + ".isConnected():" + socket.isConnected());
    if (socket.isClosed() == false && socket.isConnected() == true)
      System.out.println(name + "處于連接狀態(tài)!");
    else
      System.out.println(name + "處于非連接狀態(tài)!");
    System.out.println();
  }
  public static void main(String[] args) throws Exception
  {
    Socket socket1 = null, socket2 = null;
 
    socket1 = new Socket("www.ptpress.com.cn", 80);
    printState(socket1, "socket1");
 
    socket1.getOutputStream().close();
    printState(socket1, "socket1");
 
    socket2 = new Socket();
    printState(socket2, "socket2");
 
    socket2.close();
    printState(socket2, "socket2");
  }
}

運行上面的代碼后,將有如下的輸出結(jié)果:

socket1.isClosed():false
socket1.isConnected():true
socket1處于連接狀態(tài)!
socket1.isClosed():true
socket1.isConnected():true
socket1處于非連接狀態(tài)!
socket2.isClosed():false
socket2.isConnected():false
socket2處于非連接狀態(tài)!
socket2.isClosed():true
socket2.isConnected():false
socket2處于非連接狀態(tài)!

從輸出結(jié)果可以看出,在socket1的OutputStream關(guān)閉后,socket1也自動關(guān)閉了。而在上面的代碼我們可以看出,對于一個并未連接到服務(wù)端的Socket對象socket2,它的isClosed方法為false,而要想讓socket2的isClosed方法返回true,必須使用socket2.close顯示地調(diào)用close方法。

雖然在大多數(shù)的時候可以直接使用Socket類或輸入輸出流的close方法關(guān)閉網(wǎng)絡(luò)連接,但有時我們只希望關(guān)閉OutputStream或InputStream,而在關(guān)閉輸入輸出流的同時,并不關(guān)閉網(wǎng)絡(luò)連接。這就需要用到Socket類的另外兩個方法:shutdownInput和shutdownOutput,這兩個方法只關(guān)閉相應(yīng)的輸入、輸出流,而它們并沒有同時關(guān)閉網(wǎng)絡(luò)連接的功能。和isClosed、isConnected方法一樣,Socket類也提供了兩個方法來判斷Socket對象的輸入、輸出流是否被關(guān)閉,這兩個方法是isInputShutdown()和isOutputShutdown()。下面的代碼演示了只關(guān)閉輸入、輸出流的過程:

package mysocket;
import java.net.*; 
public class MyCloseConnection1
{
  public static void printState(Socket socket)
  {
    System.out.println("isInputShutdown:" + socket.isInputShutdown());
    System.out.println("isOutputShutdown:" + socket.isOutputShutdown());
    System.out.println("isClosed:" + socket.isClosed());
    System.out.println();
  }
  public static void main(String[] args) throws Exception
  {
    Socket socket = new Socket("www.ptpress.com.cn", 80);
    printState(socket);
    socket.shutdownInput();
    printState(socket);
    socket.shutdownOutput();
    printState(socket);
  }
}

在運行上面的代后,將得到如下的輸出結(jié)果:

isInputShutdown:false
isOutputShutdown:false
isClosed:false
isInputShutdown:true
isOutputShutdown:false
isClosed:false
isInputShutdown:true
isOutputShutdown:true
isClosed:false

從輸出結(jié)果可以看出,isClosed方法一直返回false,因此,可以肯定,shutdownInput和shutdownOutput并不影響Socket對象的狀態(tài)。

希望本文所述對你有所幫助,java使用Socket類接收和發(fā)送數(shù)據(jù)內(nèi)容就給大家介紹到這里了。希望大家繼續(xù)關(guān)注我們的網(wǎng)站!想要學(xué)習(xí)java可以繼續(xù)關(guān)注本站。

相關(guān)文章

  • java實現(xiàn)簡單學(xué)生成績檔案管理系統(tǒng)

    java實現(xiàn)簡單學(xué)生成績檔案管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)簡單學(xué)生成績檔案管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • Spring Boot使用Redisson實現(xiàn)滑動窗口限流的項目實踐

    Spring Boot使用Redisson實現(xiàn)滑動窗口限流的項目實踐

    滑動窗口限流是一種流量控制策略,用于控制在一定時間內(nèi)的請求頻率,本文主要介紹了Spring Boot使用Redisson實現(xiàn)滑動窗口限流的項目實踐,具有一定的參考價值,感興趣的可以了解一下
    2024-03-03
  • MyBatis的mapper.xml文件中入?yún)⒑头祷刂档膶崿F(xiàn)

    MyBatis的mapper.xml文件中入?yún)⒑头祷刂档膶崿F(xiàn)

    這篇文章主要介紹了MyBatis的mapper.xml文件中入?yún)⒑头祷刂档膶崿F(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • Java實現(xiàn)動物換位游戲完整?過程詳解

    Java實現(xiàn)動物換位游戲完整?過程詳解

    大家好,今天嘗試用Java編程設(shè)計一個GUI界面的動物換位游戲,游戲的結(jié)果是讓左右兩組的動物交換位置,以下是具體設(shè)計過程,供大家參考
    2022-07-07
  • 2020最新 idea下載、安裝與創(chuàng)建項目測試的教程圖解

    2020最新 idea下載、安裝與創(chuàng)建項目測試的教程圖解

    這篇文章主要介紹了2020最新 idea下載、安裝與創(chuàng)建項目測試的教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • 值得收藏!教你如何在IDEA中快速查看Java字節(jié)碼

    值得收藏!教你如何在IDEA中快速查看Java字節(jié)碼

    開發(fā)中如果我們想看JVM虛擬機怎么編譯我們的Java文件,生成字節(jié)碼的,用IDEA工具就可以查看,本篇文章就給大家詳細(xì)介紹,對正在學(xué)習(xí)java的小伙伴們很有幫助,需要的朋友可以參考下
    2021-05-05
  • springmvc實現(xiàn)文件上傳功能

    springmvc實現(xiàn)文件上傳功能

    這篇文章主要為大家詳細(xì)介紹了springmvc實現(xiàn)文件上傳功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • 詳解Spring Data Jpa 模糊查詢的正確用法

    詳解Spring Data Jpa 模糊查詢的正確用法

    本篇文章主要介紹了詳解Spring Data Jpa 模糊查詢的正確用法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-05-05
  • 詳解MySQL事務(wù)日志undo log

    詳解MySQL事務(wù)日志undo log

    眾所周知,事務(wù)的一大特點是原子性,即同一事務(wù)的SQL要同時成功或者失敗,那大家有沒有想過在MySQL的innoDB存儲引擎中是如何保證這樣的原子性操作的,接下來就帶大家一探究竟,感興趣的小伙伴和小編一起來探討吧
    2023-07-07
  • MySQL如何設(shè)置自動增長序列SEQUENCE的方法

    MySQL如何設(shè)置自動增長序列SEQUENCE的方法

    本文主要介紹了MySQL如何設(shè)置自動增長序列SEQUENCE的方法,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12

最新評論