搜尋
首頁Javajava教程Java之網路程式設計的使用詳解

Java之網路程式設計的使用詳解

Jun 30, 2017 am 09:57 AM
java入門網路程式設計

 
關鍵字:IP位址、、連接埠、UDP、DatagramPacket類別、DatagramSocket類別、TCP、ServerSocket類別、Socket類別、檔案上傳
一、基本概念
       1、基本概念
      ①MAC:MAC(Media Access Control或Medium Access Control)位址,意為媒體存取控制,或稱為實體位址、硬體位址,用來定義網路設備的位置。在OSI模型中,第三層網路層負責IP位址 ,第二層資料鏈結層則負責 MAC位址。因此一個主機會有一個MAC位址,而每個網路位址會有一個專屬於它的IP位址。
 
      ②IP位址:是指網際網路通訊協定位址(Internet Protocol Address,又翻譯為網路協定位址),是IP Address的縮寫。 IP位址是IP協定提供的一種統一的位址格式,它為網際網路上的每一個網路和每一台主機分配一個邏輯位址,以此來封鎖實體位址的差異。目前還有些ip代理軟​​體,但大部分都收費。
      
 
 
        ③連接埠:可視為裝置與外部通訊溝通的出口。
        連接埠號碼是用兩個位元組(16位元的二進位數)表示,它的取值範圍是0~65 535 ,其中0~1023之間的連接埠號碼用於以下知名的網路服務和應用,用戶的普通應用程式需要使用1024以上的連接埠號碼。連接埠分為實體連接埠和邏輯連接埠(軟體應用程式的數位識別)。

        ④TCP (Transmission Control Protocol)和UDP(User Datagram Protocol)協定屬於傳輸層協定。

        TCP協定是連結導向的通訊協議,提供IP環境下的資料可靠傳輸,它提供的服務包括資料流傳送、可靠性、有效流控、全雙工操作和多路復用。透過面向連接、端到端和可靠的資料包發送。通俗說,它是事先為所發送的資料開闢出連接好的通道,然後再進行資料發送;

         ⑤UDP是無線通訊協議,不為IP提供可靠性、流控或錯誤恢復功能。

 

         2、常見InetAddress類別的常用方法範例:
 1 public class Example1 {
 2     public static void main(String[] args) throws Exception{
 3         //创建一个表示本地主机的InetAddress对象
 4         InetAddress localAddress = InetAddress.getLocalHost(); 
 5         //获得指定主机的InetAddress对象
 6         InetAddress remoteAddress = InetAddress.getByName("www.itcast.cn");
 7         //得到IP地址的主机名。
 8         System.out.println("本机的IP地址:"+localAddress.getHostName());
 9         //获得字符串格式的原始IP地址
10         System.out.println("itcast的IP地址:"+remoteAddress.getHostAddress());
11         //判断指定的时间内地址是否可以到达
12         System.out.println("3秒是否可达:"+remoteAddress.isReachable(3000));
13        
14         System.out.println("itcast的主机名为:"+remoteAddress.getHostName());
15     }
16 }

執行結果:

本机的IP地址:wrt.local
itcast的IP地址:123.57.45.99
3秒是否可达:false
itcast的主机名为:www.itcast.cn

 

 二、UDP通訊

      1、DatagramPacket

      此類別類似於貨櫃,在建立傳送端和接收端的DatagramPacket物件時,使用的建構方法有所不同,接收端的建構方法只需要接收一個字節數組來存放接收到的數據,而發送端的構造方法不但要接收存放了發送數據的字節數組還需要製定發送端IP地址和端口號。

      DatagramPacket建構方法:

##卷和數據大小。

       ②DatagramPacket(byte[] buf,int length,InetAddress addr,int port)

       用於傳送端, 建立DatagramPacket物件時,指定了封裝資料的位元組陣列、資料大小、位元組數組、資料大小封包的目標IP位址(addr)以及連接埠號碼(port)。

       ③DatagramPacket(byte[] buf,int offset,int length)

        用於接收端,建立DatagramPacket物件時,指定了封裝資料的位元組起始組、資料大小,以及為存取端,在建立DatagramPacket物件時,指定了封裝資料的位元組起始組、資料大小,以及為位元組數位置。 offset 參數用於指定接收的資料在放入buf緩衝數組時是從offset處開始的。

        ④DatagramPacket(byte[] buf,int offset,int length,InetAddress addr,int port)

       用於傳送端, 資料大小、資料包的目標IP位址(addr)以及連接埠號碼(port)。 offset 參數用於指定發送資料的偏移量為offset,即從offset位置開始傳送資料。

TCP/IP 網路模式

 

應用層

#如HTTP、FTP、DNS

##傳輸層

如TCP、UDP

#網路層

如IP、ICMP、IGMP

鏈鋸層

如驅動程式、介面

                                                                                              DatagramPacket類中的常用方法方法聲明功能描述InetAddress  getAddress()該方法用於返回發送端或接收端的IP位址,如果發送端的DatagramPacket對象,就返回接收端的IP位址,反之,就傳回發送端的IP位址int getPort()該方法用於返回發送端或接收端的連接埠號,如果發送端的DatagramPacket對象,就返回接收端的連接埠號,反之,就傳回發送端的連接埠號碼byte[] getData()該方法用於傳回將要接收或將要傳送的數據,如果是發送端的DatagramPacket對象,就傳回將要傳送的數據,反之,就傳回接收到的資料int getLength()該方法用於傳回將要接收或將要傳送資料的長度,如果是發送端的DatagramPacket對象,就傳回將要傳送的資料長度,反之,就回傳接收到資料的長度
##

      2、DatagramSocket

      DatagramSocket類似與碼頭,實例物件就可以傳送和接收DatagramPacket資料包,在建立傳送端和接收端的DatagramSocket物件時,所使用的建構方法有所不同。

      DatagramSocket建構方法:

       ①DatagramSocket()

      收到端的Data 用於建立物件時,在建立物件時,並沒有指定連接埠號碼,此時,系統會傳送端的DatagramSocket物件時,在建立物件時,並沒有指定連接埠號,此時,指派一個沒有被其他網路程式使用的連接埠號碼。

       ②DatagramSocket(int port)

       此方法可用於建立接收端的DatagramSocket對象,可建立傳送端的DatagramSocket對象,在建立接收端的DatagramSocket對象,可建立傳送端的DatagramSocket對象,在建立接收端的DatagramSocket一個連接埠號,這樣就可以監聽指定的連接埠。

       ③DatagramSocket(int port,InetAddress addr)

       使用此建構方法在DatagramSocket時,不僅指定連接埠號碼,也指定了相關的IP位址,此情況適用於計算上有多塊網路卡的情況。                                                                                               DatagramSocket類中的常用方法方法聲明功能描述void receive(DatagramPacket p)此方法用於將接收到的資料填入DatagramPacket資料包中,在接收到資料之前會一直處於阻塞狀態,只有當接收到資料包時,該方法才會回傳。 void  send(DatagramPacket p)#此方法用於傳送DatagramPacket封包,傳送的封包中包含將要傳送的資料、資料的長度、遠端主機的IP位址和連接埠號碼void close()#關閉目前的Socket,通知驅動程式釋放為這個Socket保留的資源。
###

     3、UDP 网络程序

     在通信时只有接收端程序先运行,才能避免因发送端发送的数据无法接收,而造成数据丢失。示例:

 1 import java.net.DatagramPacket;
 2 import java.net.DatagramSocket;
 3 
 4 //接收端程序
 5 public class Example2 {
 6     public static void main(String[] args) throws Exception{
 7         //创建一个长度为1024的字节数组,用于接收数据
 8         byte [] buf = new byte[1024];
 9         //定义一个DatagramSocket对象,监听的端口为8954
10         DatagramSocket ds = new DatagramSocket(8954);
11         //定义一个DatagramPacket对象,用于接收数据
12         DatagramPacket dp = new DatagramPacket(buf,1024);
13         System.out.println("等待接收数据");
14         ds.receive(dp);          //等待接收数据,如果没有数据则会阻塞
15         //调用DatagramPacket的方法获得接收的消息,包括内容、长度、IP地址和端口号
16         String str = new String(dp.getData(),0,dp.getLength())
17                 +"from"+dp.getAddress().getHostAddress()+":"+dp.getPort();
18         System.out.println(str); //打印收到的信息
19         ds.close();              //释放资源
20     }
21 }
22 
23 
24 import java.net.DatagramPacket;
25 import java.net.DatagramSocket;
26 import java.net.InetAddress;
27 
28 //发送端程序
29 public class Example3 {
30     public static void main(String[] args) throws Exception {
31         //创建一个DatagramSocket对象
32         DatagramSocket ds = new DatagramSocket(3000);
33         String str = "Hello World!";     //要发送的数据
34         /*
35          * 创建一个要发送的数据包,包括发送数据,数据长度,接收端IP地址以及端口号
36          */
37         DatagramPacket dp = new DatagramPacket(str.getBytes(),str.length(),
38                 InetAddress.getByName("localhost"),8954);
39         System.out.println("发送消息");
40         ds.send(dp);                     //发送数据
41         ds.close();                      //释放资源
42     }

运行结果

发送消息

等待接收数据
Hello World!from127.0.0.1:3000

解析:发送货物(数据)前,确定到货码头是否能接收。

         创建空间(数据容器)接收货物(数据),创建码头【DatagramSocket(8954)】并实时监听发货码头发货通道(端口),创建集装箱并将空间加入用于接收货物,一直等待接收货物,接收码头将货物填充到集装箱中,获取到货物信息(数据等信息)。

         发送货物需要建一个码头【DatagramSocket(3000)】,码头可指定发送通道即端口(也可以不指定发送通道),将要发送货物(数据)装进集装箱(DatagramPacket

)中,并指定发送到的码头名字(IP地址或主机名)及接收通道(端口),通过码头把集装箱发出去[send()],腾出空间(close)。

 

三、TCP通信

      1、ServerSocket

       在开发TCP程序时,首先需要创建服务器端程序,其构造方法如下:

      ①ServerSocket()

      使用该构造方法在创建ServerSocket对象时并没有绑定端口号,不能直接使用,还需要继续调用bind(SocketAddress endpoint)方法将其绑定到指定的端口上,才能正常使用。

      ②ServerSocket(int port)【最常用】

      使用用该构造方法在创建ServerSocket对象时,就可以将其绑定到一个指定的端口号上。

      ③ServerSocket(int port,int backlog)

      backlog 参数用于指定在服务器忙时,可以与之保持连接请求的等待客户数量,如果没有指定这个参数默认为50 。

      ④ServerSocket(int port,int backlog,InetAddress bindAddr)

      指定了相关的IP地址,适用于计算机上有多块网卡和多个IP的情况。

     

ServerSocket类中的常用方法
方法声明 功能描述
Socket accept() 该方法用于等待客户端的连接,在客户端连接之前一直处于阻塞状态,如果有客户端连接就会返回一个与之对应的Socket对象
InetAddress getInetAddress() 该方法用于返回一个InetAddress对象,该对象封装了ServerSocket绑定的IP地址
boolean isClosed() 该方法用于判断ServerSocket对象是否为关闭状态,如果是关闭状态则返回true,反之则返回false
void bind(SocketAddress endpoint) 该方法用于判断ServerSocket对象绑定到指定的IP地址和端口号,其中参数endpoint封装了IP地址和端口号。

      

     2、Socket

         Socket类常用构造方法:
         ①Socket()
        使用该构造方法在创建Socket对象时,并没指定IP地址和端口号,创建对象后还需调用connect(SocketAddress endpoint)方法,才能完成与指定服务器的连接,参数endpoint封装了IP地址和端口号。
         ②Socket(String host,int port)
         使用该构造方法在创建Socket对象时,根据参数去连接在指定IP地址和端口上运行的服务器程序,其中参数host接收的一个字符类型的IP地址。
         ③Socket(InetAddress addres,int port)
         与第二个构造方法类似,参数address用于接收一个InetAddress类型的对象,该对象用于封装一个IP地址。
 
Socket类中的常用方法
方法声明 功能描述
int getPort() 该方法返回一个int类型对象,该对象时Socket对象与服务器端连接的端口号
InetAddress getLocalAddress() 该方法用于获取Socket对象绑定的本地IP地址,并将IP地址封装成InetAddress类型的对象返回
void close() 该方法用于关闭Socket连接,结束本次通信。在关闭Socket之前,应将于Socket相关的所有的输入与输出流全部关闭,这是因为一个良好的程序应该在执行完毕时释放所有的资源
IputStream getInputStream() 该方法返回一个InputStream类型的输入流对象,如果该对象是由服务器端的Socket返回,就用于读取客户端发送的数据,反之,用于读取服务器端发送的数据
OutputStream getOutputStream() 该方法返回一个OutputStream类型的输出流对象,如果该对象是由服务器端的Socket返回,就用于向客户端发送数据,反之,用于向服务器端发送数据
 
     3、简单的TCP网络程序
 1 import java.io.OutputStream;
 2 import java.net.ServerSocket;
 3 import java.net.Socket;
 4 
 5 public class Example4 {
 6     public static void main(String[] args) throws Exception {
 7         new TCPServer().listen();      //创建TCPServer对象,并调用listen()方法
 8     }
 9 }
10 //TCP服务器端
11 class TCPServer{
12     private static final int PORT= 7788;//定义一个端口号
13 
14     public void listen() throws Exception{ //定义一个listen()方法,抛出一个异常
15         ServerSocket serverSocket = new ServerSocket(PORT);//创建ServerSocket对象
16         Socket client=serverSocket.accept();  //调用ServerSocket的accept()方法接收数据
17         OutputStream os = client.getOutputStream(); //获取客户端的输出流
18         System.out.println("开始与客户端交换数据");
19         os.write(("Java欢迎你!").getBytes());
20         Thread.sleep(5000);      //模拟执行其他功能占用的时间
21         System.out.println("结束与客户端交互数据");
22         os.close();
23         client.close();
24     }
25 }

 

 1 import java.io.InputStream;
 2 import java.net.InetAddress;
 3 import java.net.Socket;
 4 
 5 public class Example5 {
 6     public static void main(String[] args) throws Exception{
 7         new TCPClient().connect();//创建TCPClient对象,并调用connect()方法
 8     }
 9 }
10 //TCP客户端
11 class TCPClient{
12     private static final int PORT=7788;//服务端的端口号
13     public void connect() throws Exception{
14         //创建一个Socket并连接到给出地址和端口号的计算机
15         Socket client = new Socket(InetAddress.getLocalHost(),PORT);
16         InputStream is = client.getInputStream(); //得到接收数据的流
17         byte[] buf = new byte[1024];  //定义1024个字节数组的缓冲区
18         int len=is.read(buf);    //将数据读取到缓冲区中
19         System.out.println(new String(buf,0,len));  //将缓冲区中的数据输出
20         client.close();       //关闭Socket对象,释放资源
21     }
22 }

 

Example4 运行结果:
开始与客户端交换数据
结束与客户端交互数据

Example5 运行结果:
Java欢迎你!

 

  4、TCP案例——文件上传

      实现图片上传到服务器的功能。

 服务端程序:

 1 import java.io.File;
 2 import java.io.FileOutputStream;
 3 import java.io.InputStream;
 4 import java.io.OutputStream;
 5 import java.net.ServerSocket;
 6 import java.net.Socket;
 7 
 8 public class Example7 {
 9     public static void main(String[] args) throws Exception{
10         ServerSocket serverSocket = new ServerSocket(10001);//创建ServerSocket对象
11         while (true){
12             //调用accept()方法接收客户端请求,得到Socket对象
13             Socket s = serverSocket.accept();
14             //每当和客户端建立Socket连接后,单独开启一个线程处理和客户端的交互
15             new Thread(new ServerThread(s)).start();
16         }
17     }
18 }
19 class ServerThread implements Runnable{
20     private Socket socket ;     //持有一个Socket类型的属性
21     public ServerThread(Socket socket){   //构造方法中吧Socket对象作为实参传入
22         this.socket=socket;
23     }
24 
25     @Override
26     public void run() {
27         String ip = socket.getInetAddress().getHostAddress(); //获取客户端的IP地址
28         int count =1;        //上传图片个数
29         try{
30             InputStream in = socket.getInputStream();
31             //创建上传图片目录的File对象
32             File parentFile =new File("/Users/adims/Downloads/upload/");
33             if (!parentFile.exists()){  //如果不存在,就创建这个目录
34                 parentFile.mkdir();
35             }
36             //把客户端的IP地址作为上传出文件的文件名
37             File file = new File(parentFile,ip+"("+count+").jpeg");
38             while (file.exists()){
39                 //如果文件名存在,则把count++
40                 file=new File(parentFile,ip+"("+(count++)+").jpeg");
41             }
42             //创建FileOutputStream对象
43             FileOutputStream fos = new FileOutputStream(file);
44             byte[] buf=new byte[1024];  //定义一个字节数组
45             int len=0;     //定义一个int类型的变量len,初始值为0
46             while ((len=in.read(buf))!=-1){   //循环读取数据
47                 fos.write(buf,0,len);
48             }
49             OutputStream out = socket.getOutputStream();  //获取服务端的输出流
50             out.write(("上传成功").getBytes());    //上传成功后向客户端写出"上传成功"
51             fos.close();                          //关闭输出流对象
52             socket.close();                       //关闭Socket对象
53         }catch (Exception e){
54               throw new RuntimeException(e);
55         }
56     }
57 }

客户端程序:

 1 import java.io.FileInputStream;
 2 import java.io.InputStream;
 3 import java.io.OutputStream;
 4 import java.net.InetAddress;
 5 import java.net.Socket;
 6 
 7 public class Example8 {
 8     public static void main(String[] args) throws Exception{
 9         Socket socket= new Socket(InetAddress.getLocalHost(),10001);  //创建客户端Socket对象,指定IP地址和端口号
10         OutputStream out= socket.getOutputStream();  //获取Socket的输出流对象
11         //创建FileInputStream对象
12         FileInputStream fis = new FileInputStream("/Users/adims/Downloads/WechatIMG1.jpeg");
13         byte[] buf =new byte[1024]; //定义一个字节数组
14         int len;       //定义一个int类型的变量len
15         while ((len=fis.read(buf))!=-1){    //循环读取数据
16             out.write(buf,0,len);
17         }
18         socket.shutdownOutput();      //关闭客户端输出流
19         InputStream in = socket.getInputStream();   //获取Socket的输入流对象
20         byte[] bufMsg = new byte[1024];    //定义一个字节数组
21         int num =in.read(bufMsg);          //接收服务端的信息
22         String Msg = new String(bufMsg,0,num);
23         System.out.println(Msg);
24         fis.close();                   //关闭输入流对象
25         socket.close();                //关闭Socket对象
26     }
27 }

需注意:shutdownOutput()方法非常重要,因为服务器端程序在while循环中读取客户端发送的数据,当读取到-1时才会结束循环,如果客户端不调用shutdownOutput()方法关闭输出流,服务器端就不会读到-1,而会一直执行while循环,同时客户端服务器端的read(byte[])方法也是一个阻塞方法,这样客户端与服务器端进入一个“死锁”状态。

以上是Java之網路程式設計的使用詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
為什麼Java是開發跨平台桌面應用程序的流行選擇?為什麼Java是開發跨平台桌面應用程序的流行選擇?Apr 25, 2025 am 12:23 AM

javaispopularforcross-platformdesktopapplicationsduetoits“ writeonce,runany where”哲學。 1)itusesbytiesebyTecodeThatrunsonAnyJvm-備用Platform.2)librarieslikeslikeslikeswingingandjavafxhelpcreatenative-lookingenative-lookinguisis.3)

討論可能需要在Java中編寫平台特定代碼的情況。討論可能需要在Java中編寫平台特定代碼的情況。Apr 25, 2025 am 12:22 AM

在Java中編寫平台特定代碼的原因包括訪問特定操作系統功能、與特定硬件交互和優化性能。 1)使用JNA或JNI訪問Windows註冊表;2)通過JNI與Linux特定硬件驅動程序交互;3)通過JNI使用Metal優化macOS上的遊戲性能。儘管如此,編寫平台特定代碼會影響代碼的可移植性、增加複雜性、可能帶來性能開銷和安全風險。

與平台獨立性相關的Java開發的未來趨勢是什麼?與平台獨立性相關的Java開發的未來趨勢是什麼?Apr 25, 2025 am 12:12 AM

Java將通過雲原生應用、多平台部署和跨語言互操作進一步提昇平台獨立性。 1)雲原生應用將使用GraalVM和Quarkus提升啟動速度。 2)Java將擴展到嵌入式設備、移動設備和量子計算機。 3)通過GraalVM,Java將與Python、JavaScript等語言無縫集成,增強跨語言互操作性。

Java的強鍵入如何有助於平台獨立性?Java的強鍵入如何有助於平台獨立性?Apr 25, 2025 am 12:11 AM

Java的強類型系統通過類型安全、統一的類型轉換和多態性確保了平台獨立性。 1)類型安全在編譯時進行類型檢查,避免運行時錯誤;2)統一的類型轉換規則在所有平台上一致;3)多態性和接口機制使代碼在不同平台上行為一致。

說明Java本機界面(JNI)如何損害平台獨立性。說明Java本機界面(JNI)如何損害平台獨立性。Apr 25, 2025 am 12:07 AM

JNI會破壞Java的平台獨立性。 1)JNI需要特定平台的本地庫,2)本地代碼需在目標平台編譯和鏈接,3)不同版本的操作系統或JVM可能需要不同的本地庫版本,4)本地代碼可能引入安全漏洞或導致程序崩潰。

是否有任何威脅或增強Java平台獨立性的新興技術?是否有任何威脅或增強Java平台獨立性的新興技術?Apr 24, 2025 am 12:11 AM

新興技術對Java的平台獨立性既有威脅也有增強。 1)雲計算和容器化技術如Docker增強了Java的平台獨立性,但需要優化以適應不同雲環境。 2)WebAssembly通過GraalVM編譯Java代碼,擴展了其平台獨立性,但需與其他語言競爭性能。

JVM的實現是什麼,它們都提供了相同的平台獨立性?JVM的實現是什麼,它們都提供了相同的平台獨立性?Apr 24, 2025 am 12:10 AM

不同JVM實現都能提供平台獨立性,但表現略有不同。 1.OracleHotSpot和OpenJDKJVM在平台獨立性上表現相似,但OpenJDK可能需額外配置。 2.IBMJ9JVM在特定操作系統上表現優化。 3.GraalVM支持多語言,需額外配置。 4.AzulZingJVM需特定平台調整。

平台獨立性如何降低發展成本和時間?平台獨立性如何降低發展成本和時間?Apr 24, 2025 am 12:08 AM

平台獨立性通過在多種操作系統上運行同一套代碼,降低開發成本和縮短開發時間。具體表現為:1.減少開發時間,只需維護一套代碼;2.降低維護成本,統一測試流程;3.快速迭代和團隊協作,簡化部署過程。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器