基於TCP和UDP的Socket實現(JAVA)


 本文介紹如何用Java實現Socket編程。首先介紹Java針對Socket編程提供的類,以及它們之間的關系。然后分別針對TCP和UDP兩種傳輸層協議實現Socket編程。

1 Java中的Socket編程接口介紹

Java為Socket編程封裝了幾個重要的類。

1.1 Socket類

Socket類實現了一個客戶端socket,作為兩台機器通信的終端,默認采用的傳輸層協議為TCP,是一個可靠傳輸的協議。Socket類除了構造函數返回一個socket外,還提供了connect, getOutputStream, getInputStream和close方法。connect方法用於請求一個socket連接,getOutputStream用於獲得寫socket的輸出流,getInputStream用於獲得讀socket的輸入流,close方法用於關閉一個流。

1.2 DatagramSocket類

DatagramSocket類實現了一個發送和接收數據報的socket,傳輸層協議使用UDP,不能保證數據報的可靠傳輸。DataGramSocket主要有send, receive和close三個方法。send用於發送一個數據報,Java提供了DatagramPacket對象用來表達一個數據報。receive用於接收一個數據報,調用該方法后,一直阻塞接收到直到數據報或者超時。close是關閉一個socket。

1.3 ServerSocket類

ServerSocket類實現了一個服務器socket,一個服務器socket等待客戶端網絡請求,然后基於這些請求執行操作,並返回給請求者一個結果。ServerSocket提供了bind、accept和close三個方法。bind方法為ServerSocket綁定一個IP地址和端口,並開始監聽該端口。accept方法為ServerSocket接受請求並返回一個Socket對象,accept方法調用后,將一直阻塞直到有請求到達。close方法關閉一個ServerSocket對象。

1.4 SocketAddress

SocketAddress提供了一個socket地址,不關心傳輸層協議。這是一個虛類,由子類來具體實現功能、綁定傳輸協議。它提供了一個不可變的對象,被socket用來綁定、連接或者返回數值。

1.5 InetSocketAddress

InetSocketAddress實現了IP地址的SocketAddress,也就是有IP地址和端口號表達Socket地址。如果不制定具體的IP地址和端口號,那么IP地址默認為本機地址,端口號隨機選擇一個。

1.6. DatagramPacket

DatagramSocket是面向數據報socket通信的一個可選通道。數據報通道不是對網絡數據報socket通信的完全抽象。socket通信的控制由DatagramSocket對象實現。DatagramPacket需要與DatagramSocket配合使用才能完成基於數據報的socket通信。

 2. 基於TCP的Socket編程

上面描述了Java對Socket編程提供的接口,本節介紹如何實現一個基於TCP連接的Socket通信。

下面例子是Server端等待從Client端接收一條消息,然后再給客戶端發送一個消息。

服務器端首先實例化ServerSocket對象,然后為其綁定一個本機地址,並開始監聽。一直阻塞狀態下等待客戶端請求,當獲得客戶端連接請求后,返回一個socket對象。然后用這個socket接收一條消息,並發送一條消息。代碼如下:

package server.socket.java;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;

public class SocketTcp {
    static private String TAG = "SocketTcp: ";
    
    public static void main(String[] args){
        try {
            ServerSocket server = new ServerSocket();
            SocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(), 10001);
            server.bind(address);
            System.out.println("==waiting for being connected...");
            Socket client = server.accept();
            System.out.println("==connected with " + 
                    client.getRemoteSocketAddress() );
            
            PrintWriter socketOut = new PrintWriter(client.getOutputStream());
            
            System.out.println("==waiting message from client...");
            byte buf[] = new byte[1024];
            if ( client.getInputStream().read(buf) > 0 ) {
                System.out.println("Receive Message: " + new String(buf));
            }
            
            System.out.println("==sending message to client...");
            String sendStr = "This is the message for client.";
            socketOut.write(sendStr);
            socketOut.flush();
            
            socketOut.close();
            client.close();
            server.close();
        } catch (IOException e) {
            System.out.println(TAG + e.getMessage());
            e.printStackTrace();
        }
    }
}
 
        

 客戶端首先實例化一個socket對象,用這個對象連接服務器端。連接成功后,發送一條消息,然后等待接收一條消息。代碼如下:

package client.socket.java;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;

public class SocketTcp {
    static private String TAG = "SocketTcp: ";
    
    public static void main(String[] args){
        try {
            final Socket socket = new Socket();
            SocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(), 10001);
            System.out.println("==connecting to server ...");
            socket.connect(address);
            
            PrintWriter socketOut = new PrintWriter(socket.getOutputStream());
            BufferedReader socketIn = new BufferedReader(
                    new InputStreamReader(socket.getInputStream()) );
            
            String sendStr = "This is the message for server.";
            System.out.println("==sending message to server ...");
            socketOut.write(sendStr);
            socketOut.flush();
            System.out.println("==waiting message from server ...");
            String receiveStr = socketIn.readLine();
            System.out.println("Receive Message: " + receiveStr);
            
            socketOut.close();
            socketIn.close();
            socket.close();
        } catch (IOException e) {
            System.out.println(TAG + e.getMessage());
            e.printStackTrace();
        } finally {
            
        }
    }
}

 服務器端運行結果: 

==waiting for being connected...
==connected with /172.26.176.69:53912
==waiting message from client...
Receive Message: This is the message for server.

 客戶端運行結果: 

==connecting to server ...
==sending message to server ...
==waiting message from server ...
Receive Message: This is the message for client.

 3 基於UDP的Socket編程示例

 基於UDP的Socket編程與基於TCP的socket編程稍有不同,socket server和client都用DatagramSocket實現。

 下面例子是Server端等待從Client端接收一條消息,然后再給客戶端發送一個消息。

 服務器端首先實例化DatagramSocket對象,然后為其綁定一個本機地址,並開始監聽。一直阻塞狀態下等待從客戶端接收數據報。然后從數據報中獲取數據報的源地址,然后用這個源地址作為目的地址打包一個數據報,然后發送出去。代碼如下:

package server.socket.java;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

public class SocketUdp {
    final private static String TAG = "SocketUdp: ";
    
    public static void main(String args[]) {
        DatagramSocket socket = null;
        DatagramPacket datapacket = null;
        InetSocketAddress address = null;
        
        try {
            address = new InetSocketAddress(InetAddress.getLocalHost(), 7778);
            socket = new DatagramSocket(address);
            // socket.bind(address);
            
            byte buf[] = new byte[1024];
            datapacket = new DatagramPacket(buf, buf.length);
            System.out.println("==block for receive messages...");
            socket.receive(datapacket);
            buf = datapacket.getData();
            InetAddress addr = datapacket.getAddress();
            int port = datapacket.getPort();
            System.out.println("Message Content: " + new String(buf) );
            System.out.println("Receive From " + addr + ":" + port);
            
            SocketAddress toAddress = datapacket.getSocketAddress();
            String sendStr = "I'm Server, this is the message for client.";
            buf = sendStr.getBytes();
            datapacket = new DatagramPacket(buf, buf.length);
            datapacket.setSocketAddress(toAddress);
            socket.send(datapacket);
            System.out.println("==message sended");
            
        } catch (UnknownHostException e) {
            System.out.println(TAG + e.getMessage());
            e.printStackTrace();
        } catch (SocketException e) {
            System.out.println(TAG + e.getMessage());
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println(TAG + e.getMessage());
            e.printStackTrace();
        }
    }

}

  客戶端首先實例化一個DatagramSocket對象。利用服務器地址和端口號作為目的地址打包一個數據報,並發送。然后等待從服務器回復的數據報。代碼如下: 

package client.socket.java;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

public class SocketUdp {
    final private static String TAG = "SocketUdp: ";
    
    public static void main(String args[]) {
        try {
            DatagramSocket getSocket = new DatagramSocket();
            DatagramPacket datapacket = null;
            InetSocketAddress toAddress = new InetSocketAddress(InetAddress.getLocalHost(), 7778);
            
            String sendStr = "I'm client, this is the message for server.";
            byte buf[] = sendStr.getBytes();
            datapacket = new DatagramPacket(buf, buf.length);
            datapacket.setSocketAddress(toAddress);
            getSocket.send(datapacket);
            System.out.println("==message sended");
            
            System.out.println("==block for receive messages...");
            getSocket.receive(datapacket);
            buf = datapacket.getData();
            System.out.println("Message Content: " + new String(buf));
        } catch (SocketException e) {
            System.out.println(TAG + e.getMessage());
            e.printStackTrace();
        } catch (UnknownHostException e) {
            System.out.println(TAG + e.getMessage());
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println(TAG + e.getMessage());
            e.printStackTrace();
        }
        
    }
}

 服務器端運行結果:

==block for receive messages...
Message Content: I'm client, this is the message for server.

 客戶端運行結果:

==message sended
==block for receive messages...
Message Content: I'm Server, this is the message for client.


免責聲明!

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



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