1. 程式人生 > >《Java開發實戰1200例》(第2卷)學習筆記—TCP套接字

《Java開發實戰1200例》(第2卷)學習筆記—TCP套接字

Socket基礎

例項307:建立伺服器套接字

-通過ServerSocket類建立繫結到指定埠的伺服器套接字物件,然後呼叫ServerSocket類的accept()方法監聽客戶端的連線。
全部程式碼如下:

import java.awt.BorderLayout;
import java.net.*;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class ServerSocketFrame extends JFrame {
    private
JTextArea ta_info; private ServerSocket server; // 宣告ServerSocket物件 private Socket socket; // 宣告Socket物件socket public void getServer() { try { server = new ServerSocket(1978); // 例項化Socket物件 ta_info.append("伺服器套接字已經建立成功\n"); // 輸出資訊 while (true) { // 如果套接字是連線狀態
ta_info.append("等待客戶機的連線......\n"); // 輸出資訊 socket = server.accept(); // 例項化Socket物件 ta_info.append("連線成功......\n"); } } catch (Exception e) { e.printStackTrace(); // 輸出異常資訊 } } public static void main(String[] args) { // 主方法
ServerSocketFrame frame = new ServerSocketFrame(); // 建立本類物件 frame.setVisible(true); frame.getServer(); // 呼叫方法 } public ServerSocketFrame() { super(); setTitle("建立伺服器套接字"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 260, 167); final JScrollPane scrollPane = new JScrollPane(); getContentPane().add(scrollPane, BorderLayout.CENTER); ta_info = new JTextArea(); scrollPane.setViewportView(ta_info); } }

注意:在進行套接字程式設計時,應該使用大於1024的埠號,這樣可以避免埠衝突,因為0~1024之間的埠已經被一些特殊的協議和服務所佔用,如80埠被HTTP協議所佔用、21埠被FTP服務所佔用等。

例項308:建立客戶端套接字

通過Socket類建立到指定伺服器和埠的套接字物件,從而實現與伺服器的連線。
全部程式碼如下:

import java.awt.BorderLayout;
import java.net.*;
import javax.swing.*;
import javax.swing.JScrollPane;

public class ClientSocketFrame extends JFrame { // 建立類繼承JFrame類
    private Socket socket; // 宣告Socket物件
    private JTextArea ta_info = new JTextArea(); // 建立JtextArea物件

    public ClientSocketFrame() { // 構造方法
        super(); // 呼叫父類的構造方法
        setTitle("建立客戶端套接字");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 254, 166);
        final JScrollPane scrollPane = new JScrollPane();
        getContentPane().add(scrollPane, BorderLayout.CENTER);
        scrollPane.setViewportView(ta_info);
    }

    private void connect() { // 連線套接字方法
        ta_info.append("嘗試連線......\n"); // 文字域中資訊資訊
        try { // 捕捉異常
            socket = new Socket("127.0.0.1", 1978); // 例項化Socket物件
            ta_info.append("完成連線。\n"); // 文字域中提示資訊
        } catch (Exception e) {
            e.printStackTrace(); // 輸出異常資訊
        }
    }

    public static void main(String[] args) { // 主方法
        ClientSocketFrame clien = new ClientSocketFrame(); // 建立本例物件
        clien.setVisible(true); // 將窗體顯示
        clien.connect(); // 呼叫連線方法
    }
}

注意:本例單獨執行時會發生異常,因此需要先執行例項307.
在使用Socket類建立客戶端套接字時,所指定的IP地址和埠號一定要與伺服器相同,否則將無法連線到伺服器。

例項309:設定等待連線的超時時間

通過ServerSocket類的例項呼叫setSoTimeout()方法,設定連線的等待超時時間,從而實現設定等待連線的超時時間。
主要程式碼如下:

server=new ServerSocket(1978);
server.setSoTimeout(10000);//設定連線超時時間為10秒

注意:可以使用Socket類的setTcpNoDelay()方法,將引數設定為true,禁用網路傳輸中的資料延遲;設定為false,啟用資料延遲。對於一般的網路通訊,是允許資料延遲的,而對於一些特殊的網路應用,如果允許資料延遲,將會極大地影響資料傳輸的速度,例如需要實時監控的網路程式以及遊戲,就必須禁用資料延遲。

例項310:獲取Socket資訊

通過Socket類的getInetAddress()方法獲得遠端伺服器的地址,使用getLocalAddress()方法獲得客戶端的地址實現的。
主要程式碼如下:

socket=new Socket("伺服器IP地址",埠號);//例項化Socket物件
InetAddress netAddress=socket.getInetAddress();//獲得遠端伺服器的地址
String netIp=netAddress.getHostAddress();//獲得遠端伺服器的地址
int netPort=socket.getPort();//獲得遠端伺服器的埠號
InetAddress localAddress=socket.getLocalAddress();//獲得客戶端的地址
String localIp=localAddress.getHostAddress();//獲得客戶端的IP地址
int localPort=socket.getLocalPort();//獲得客戶端的埠號

接收和傳送Socket資訊

本例項主要是通過Socket類的getInputStream()方法獲得輸入流物件,使用getOutputStream()方法獲得輸出流物件實現的。
全部程式碼如下:

//客戶端程式
import java.awt.*;
import java.awt.BorderLayout;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import javax.swing.*;
import javax.swing.JScrollPane;

public class ClientSocketFrame extends JFrame { // 建立類繼承JFrame類
    private PrintWriter writer; // 宣告PrintWriter類物件
    private Socket socket; // 宣告Socket物件
    private JTextArea ta_info = new JTextArea(); // 建立JtextArea物件
    private JTextField tf_send = new JTextField(); // 建立JtextField物件
    private Container cc; // 宣告Container物件

    public ClientSocketFrame() { // 構造方法
        super(); // 呼叫父類的構造方法
        setTitle("客戶端程式");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 351, 257);
        cc = this.getContentPane(); // 例項化物件
        cc.add(tf_send, "South"); // 將文字框放在窗體的下部
        tf_send.addActionListener(new ActionListener() { // 繫結事件
                    public void actionPerformed(ActionEvent e) {
                        writer.println(tf_send.getText()); // 將文字框中資訊寫入流
                        ta_info.append("客戶端傳送的資訊是:" + tf_send.getText() + "\n"); // 將文字框中資訊顯示在文字域中
                        tf_send.setText(""); // 將文字框清空
                    }
                });
        final JScrollPane scrollPane = new JScrollPane();
        getContentPane().add(scrollPane, BorderLayout.CENTER);
        scrollPane.setViewportView(ta_info);
    }

    private void connect() { // 連線套接字方法
        ta_info.append("嘗試連線......\n"); // 文字域中資訊資訊
        try { // 捕捉異常
            socket = new Socket("192.168.1.193", 1978); // 例項化Socket物件
            writer = new PrintWriter(socket.getOutputStream(), true);// 建立輸出流物件
            ta_info.append("完成連線。\n"); // 文字域中提示資訊
        } catch (Exception e) {
            e.printStackTrace(); // 輸出異常資訊
        }
    }

    public static void main(String[] args) { // 主方法
        ClientSocketFrame clien = new ClientSocketFrame(); // 建立本例物件
        clien.setVisible(true); // 將窗體顯示
        clien.connect(); // 呼叫連線方法
    }
}
//伺服器端程式
import java.awt.BorderLayout;
import java.io.*;
import java.net.*;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class ServerSocketFrame extends JFrame {
    private JTextArea ta_info;// 宣告文字域,用於顯示連線資訊和接收到的資訊
    private BufferedReader reader; // 宣告BufferedReader物件
    private ServerSocket server; // 宣告ServerSocket物件
    private Socket socket; // 宣告Socket物件socket

    public void getServer() {
        try {
            server = new ServerSocket(1978); // 例項化Socket物件
            ta_info.append("伺服器套接字已經建立成功\n"); // 輸出資訊
            while (true) { // 如果套接字是連線狀態
                ta_info.append("等待客戶機的連線......\n"); // 輸出資訊
                socket = server.accept(); // 例項化Socket物件
                ta_info.append("連線成功。\n"); // 輸出資訊
                reader = new BufferedReader(new InputStreamReader(socket
                        .getInputStream())); // 例項化BufferedReader物件
                getClientInfo(); // 呼叫getClientInfo()方法
            }
        } catch (Exception e) {
            e.printStackTrace(); // 輸出異常資訊
        }
    }

    private void getClientInfo() {
        try {
            while (true) { // 如果套接字是連線狀態
                ta_info.append("接收到客戶機發送的資訊:" + reader.readLine() + "\n"); // 獲得客戶端資訊
            }
        } catch (Exception e) {
            ta_info.append("客戶端已退出。\n"); // 輸出異常資訊
        } finally {
            try {
                if (reader != null) {
                    reader.close();// 關閉流
                }
                if (socket != null) {
                    socket.close(); // 關閉套接字
                }
            } catch (IOException e) {
                e.printStackTrace();
            } 
        }
    }

    public static void main(String[] args) { // 主方法
        ServerSocketFrame frame = new ServerSocketFrame(); // 建立本類物件
        frame.setVisible(true);
        frame.getServer(); // 呼叫方法
    }

    public ServerSocketFrame() {
        super();
        setTitle("伺服器端程式");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 336, 257);

        final JScrollPane scrollPane = new JScrollPane();
        getContentPane().add(scrollPane, BorderLayout.CENTER);

        ta_info = new JTextArea();
        scrollPane.setViewportView(ta_info);
    }
}

例項312:關閉Socket緩衝

通過Socket類的例項,呼叫setTcpNoDelay()方法,將引數設定為true來關閉Socket緩衝的。
主要程式碼如下:

socket=server.accept();//例項化Socket物件
socket.setTcpNoDelay(true);//關閉Socket緩衝,提高資料傳輸速度