首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 入門筆記:Socket 網路程式設計完整指南

     編輯:Java 相關知識

1. Client/Server 網路模型

Java 透過 Socket 完成所有網路底層通訊。Socket 是通訊管道,透過特定連接埠收發資料。Java Socket 分兩大類:

  • Datagram Sockets(資料包 Socket):基於 UDP
  • Stream Sockets(串流 Socket):基於 TCP

2. Datagram Socket (UDP)

特點

  • 不保證送達、不保證順序、無連線開銷、資源較少。
  • 資料以包為單位傳送,需自行加入序號重組。

核心類別

  • DatagramSocket:實作基本功能
  • DatagramPacket:封裝資料包

DatagramSocket 關鍵方法

方法說明
DatagramSocket()隨機繫結有效連接埠
DatagramSocket(int port)繫結指定連接埠
send(DatagramPacket p)發送資料包(目的地址已在封包中)
receive(DatagramPacket p)接收資料包(線程安全)
close()關閉 Socket

不分 Client/Server,發送者為 Client,接收者為 Server。

DatagramPacket 關鍵建構子

  • DatagramPacket(byte[] buf, int length):接收用
  • DatagramPacket(byte[] buf, int length, InetAddress addr, int port):發送用

完整範例:Fortune Server/Client

Server 端(多線程)

import java.io.*;
import java.net.*;

class FortuneServer extends Thread {
    DatagramSocket serverSocket;
    public FortuneServer() {
        super("FortuneServer");
        try {
            serverSocket = new DatagramSocket(1114);
            System.out.println("FortuneServer up and running...");
        } catch (SocketException e) {
            System.err.println("Exception: couldn't create datagram socket");
            System.exit(1);
        }
    }
    public static void main(String[] args) {
        new FortuneServer().start();
    }
    public void run() {
        if (serverSocket == null) return;
        while (true) {
            try {
                byte[] data = new byte[256];
                DatagramPacket packet = new DatagramPacket(data, data.length);
                serverSocket.receive(packet);
                InetAddress address = packet.getAddress();
                int port = packet.getPort();
                File inFile = new File("Fortunes.txt");
                FileInputStream inStream = new FileInputStream(inFile);
                if (inStream.read(data) <= 0)
                    System.err.println("Error: couldn't read fortunes");
                packet = new DatagramPacket(data, data.length, address, port);
                serverSocket.send(packet);
            } catch (Exception e) {
                System.err.println("Exception: " + e);
                e.printStackTrace();
            }
        }
    }
}

Client 端

import java.io.*;
import java.net.*;

class FortuneClient {
    public static void main(String[] args) {
        FortuneClient client = new FortuneClient();
        System.out.println(client.getMessage());
    }
    public String getMessage() {
        try {
            DatagramSocket socket = new DatagramSocket();
            byte[] data = new byte[256];
            DatagramPacket packet = new DatagramPacket(data, data.length,
                InetAddress.getByName("127.0.0.1"), 1114);
            socket.send(packet);
            packet = new DatagramPacket(data, data.length);
            socket.receive(packet);
            String fortune = new String(packet.getData(), 0);
            socket.close();
            return fortune;
        } catch (Exception e) {
            System.err.println("Exception: " + e);
            e.printStackTrace();
            return null;
        }
    }
}

3. Stream Socket (TCP)

特點

  • 永久連線、可靠傳輸、資源較多。
  • 分 Socket(Client)與 ServerSocket(Server)。

Socket 關鍵方法

  • Socket(String host, int port) / Socket(InetAddress, int port):建立連線
  • getInputStream()、getOutputStream():取得輸入/輸出串流
  • close()

連線建立後,操作方式與一般串流無異。

ServerSocket 關鍵方法

  • ServerSocket(int port) / ServerSocket(int port, int backlog) / ServerSocket(int port, int backlog, InetAddress bindAddr)
  • accept():阻塞等待連線,回傳 Socket 物件
  • close()

分層架構範例:聊天程式

三層設計:

  1. Receiver/Sender:處理串流讀寫(執行緒)
  2. SocketPerformer:建立串流並啟動上層執行緒
  3. Server/Client:建立 Socket 並委派

Receiver

package socketChat;
import java.io.BufferedReader;
public class Receiver extends Thread {
    BufferedReader reader;
    public Receiver(BufferedReader r) { reader = r; }
    public void run() {
        try {
            while (true) {
                String words = reader.readLine();
                System.out.println("\r\n<<< " + words);
            }
        } catch (Exception e) { e.printStackTrace(); }
    }
}

Sender

package socketChat;
import java.io.*;
public class Sender extends Thread {
    PrintWriter writer;
    public Sender(PrintWriter w) { writer = w; }
    public void run() {
        try {
            BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
            while (true) {
                String input = console.readLine();
                writer.write(input + "\r\n");
                writer.flush();
            }
        } catch (Exception e) { e.printStackTrace(); }
    }
}

SocketPerformer

package socketChat;
import java.io.*;
import java.net.Socket;
public class SocketPerformer {
    Socket socket;
    public SocketPerformer(Socket s) { socket = s; }
    public void execut() throws Exception {
        BufferedReader socketReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        PrintWriter socketWriter = new PrintWriter(socket.getOutputStream());
        System.out.println("connection built !");
        new Receiver(socketReader).start();
        new Sender(socketWriter).start();
    }
}

Server

package socketChat;
import java.net.*;
public class Server {
    public static void main(String[] args) throws Exception {
        ServerSocket server = new ServerSocket(30000, 5);
        System.out.println("waiting incoming connection...");
        Socket socket = server.accept();
        System.out.println("a connection built! peer ip: " + socket.getInetAddress().getHostAddress());
        new SocketPerformer(socket).execut();
        server.close();
    }
}

Client

package socketChat;
import java.net.*;
public class Client {
    public static void main(String[] args) throws Exception {
        String ip = "127.0.0.1";
        int port = 30000;
        System.out.println("connecting to server: " + ip + " at port: " + port + " ...");
        Socket soc = new Socket(ip, port);
        new SocketPerformer(soc).execut();
    }
}

4. Java 基礎語法補充

  • final:常數、不可繼承類別、不可覆寫方法
  • static:類別變數/方法
  • instanceof:型別判斷
  • getClass().getName():取得類別名稱
  • 核心套件:java.lang、java.util、java.io、java.net、java.awt、java.applet
  • null、基本型別包裝類別(int→Integer)
  • 建構子、this()、super()、多類別單一檔案、介面與抽象類別差異
  • String.copyValueOf()、new String(buf, offset, count)
  • 標準串流:System.in (InputStream)、System.out/err (PrintStream)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved