Java Socket 套接字編程

IP 地址+端口號(hào)組成了 Socket,Socket 是網(wǎng)絡(luò)上運(yùn)行的程序之間雙向通信鏈路的終點(diǎn),是 TCP 和 UDP 的基礎(chǔ),網(wǎng)絡(luò)通信其實(shí)就是 Socket 間的通信,數(shù)據(jù)在兩個(gè) Socket 間通過 IO 傳輸

InetAddress

  • 用于標(biāo)識(shí)網(wǎng)絡(luò)上的硬件資源
//獲取本機(jī)的InetAddress實(shí)例
InetAddress address = InetAddress.getLocalHost();
//獲取計(jì)算機(jī)名
address.getHostName();
//獲取IP地址
address.getHostAddress();
//獲取字節(jié)數(shù)組形式的 IP 地址,以點(diǎn)分隔的四部分
byte[] bytes = address.getAddress();
//獲取其他主機(jī)的 InetAddress 實(shí)例
InetAddress address3 = InetAddress.getByName("127.0.0.1");

URL

  • 統(tǒng)一資源定位符,通過URL可以直接讀取或?qū)懭刖W(wǎng)絡(luò)的數(shù)據(jù)資源
//創(chuàng)建一個(gè) URL 的實(shí)例
URL baidu = new URL("http://www.baidu.com");
URL url = new URL(baidu, "/index.html?username=tom#test");//?表示參數(shù),#表示錨點(diǎn)
url.getProtocol();//獲取協(xié)議
url.getHost();//獲取主機(jī)
url.getPort();//如果沒有指定端口號(hào),根據(jù)協(xié)議不同使用默認(rèn)端口。此時(shí)getPort()方法的返回值為 -1
url.getPath();//獲取文件路徑
url.getFile();//文件名,包括文件路徑+參數(shù)
url.getRef();//相對(duì)路徑,就是錨點(diǎn),即#號(hào)后面的內(nèi)容
url.getQuery();//查詢字符串,即參數(shù)
  • 通過 URL 對(duì)象的 openStream() 方法可以得到指定資源的輸入流,通過流能夠讀取或訪問網(wǎng)頁上的資源
URL baidu = new URL("http://www.baidu.com");
InputStream is = baidu.openStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String content = null;
while ((content = br.readLine()) != null) {
    System.out.println(content);
}
br.close();
is.close();

TCP 編程

  • TCP 協(xié)議是面向連接、可靠的、有序的、以字節(jié)流的方式發(fā)送數(shù)據(jù),基于 TCP 協(xié)議實(shí)現(xiàn)的網(wǎng)絡(luò)通信,通信模型流程如下
TCP通信流程

客戶端 Socket

  • 客戶端的 Socket 類,需指明要連接的服務(wù)器地址和端口號(hào),建立連接后通過輸入、輸出流發(fā)送和響應(yīng)信息
public class Client {
    public static void main(String[] args) {
        try (Socket socket = new Socket("127.0.0.1",8999)){
            // 像服務(wù)器端發(fā)送信息
            OutputStream os = socket.getOutputStream();
            PrintWriter pw = new PrintWriter(os);
            pw.write("我是客戶端 linyuan");
            pw.flush();
            // 接收服務(wù)器端消息
            InputStream is = socket.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String message = null;
            while ((message = br.readLine()) != null) {
                System.out.println("服務(wù)器說:" + message);
            }
            // 關(guān)閉資源.....
            pw.close();
            os.close();
            is.close();
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

服務(wù)器端 ServerSocket

  • 創(chuàng)建服務(wù)器端 ServerSocket 并綁定端口,通過 accept() 方法監(jiān)聽客戶端請(qǐng)求,建立連接后通過輸入、輸出流發(fā)送和響應(yīng)信息
public class Server {
    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(8999)) {
            System.out.println("服務(wù)器啟動(dòng)................");
            while (true) {
                // 監(jiān)聽客戶端連接
                Socket socket = serverSocket.accept();
                // 接收客戶端消息
                InputStream is = socket.getInputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(is));
                String message;
                while ((message = br.readLine()) != null) {
                    System.out.println("客戶端說:" + message);
                }
                // 向客戶端發(fā)送消息
                OutputStream os = socket.getOutputStream();
                PrintWriter pw = new PrintWriter(os);
                pw.write("歡迎加入 xxx 服務(wù)器.........");
                pw.flush();
                // 關(guān)閉資源.....
                br.close();
                is.close();
                pw.close();
                os.close();
                socket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

UDP 編程

  • UDP 協(xié)議(用戶數(shù)據(jù)報(bào)協(xié)議)是無連接的、不可靠的、無序的,速度快
  • 進(jìn)行數(shù)據(jù)傳輸時(shí),首先將要傳輸?shù)臄?shù)據(jù)定義成數(shù)據(jù)報(bào)(DatagramPacket),大小限制在 64k,并指名要發(fā)送的地址 Socket(主機(jī)地址和端口號(hào)),然后再將數(shù)據(jù)報(bào)發(fā)送出去

服務(wù)器端實(shí)現(xiàn)

  • 創(chuàng)建 DatagramSocket 并綁定端口,創(chuàng)建 DatagramPacket 并調(diào)用 receive 方法接收客戶端發(fā)送的數(shù)據(jù)報(bào)(該方法會(huì)阻塞到接收到數(shù)據(jù)報(bào)為止),讀取數(shù)據(jù)
public class Server {
    public static void main(String[] args) {
        try{
            byte[] data = new byte[1024];
            // 接收客戶端數(shù)據(jù)報(bào)
            DatagramSocket socket = new DatagramSocket(10000);
            DatagramPacket rPacket = new DatagramPacket(data,0,data.length);
            socket.receive(rPacket);
            String info = new String(data,0,rPacket.getLength());
            System.out.println("客戶端發(fā)送內(nèi)容:"+info);
            // 響應(yīng)客戶端
            InetSocketAddress socketAddress = new InetSocketAddress(rPacket.getAddress(),rPacket.getPort());
            data = "新的一天!".getBytes();
            DatagramPacket sPacket = new DatagramPacket(data,0,data.length,socketAddress);
            socket.send(sPacket);
            socket.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

客戶端實(shí)現(xiàn)

  • 定義要發(fā)送的消息,創(chuàng)建 DatagramPacket,通過 DatagramSocket 發(fā)送數(shù)據(jù)
public class Client {
    public static void main(String[] args) {
        try{
            InetSocketAddress socketAddress = new InetSocketAddress("localhost",10000);
            byte[] data = "我是客戶端".getBytes();
            DatagramPacket packet = new DatagramPacket(data,0,data.length,socketAddress);
            DatagramSocket socket = new DatagramSocket();
            socket.send(packet);    
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 網(wǎng)絡(luò)編程 網(wǎng)絡(luò)編程對(duì)于很多的初學(xué)者來說,都是很向往的一種編程技能,但是很多的初學(xué)者卻因?yàn)楹荛L(zhǎng)一段時(shí)間無法進(jìn)入網(wǎng)絡(luò)編...
    程序員歐陽閱讀 2,113評(píng)論 1 37
  • Socket編程 1基礎(chǔ)知識(shí) 協(xié)議 端口號(hào)(辨別不同應(yīng)用) TCP/IP協(xié)議 是目前世界上應(yīng)用最廣泛的協(xié)議是以TC...
    __豆約翰__閱讀 1,196評(píng)論 0 3
  • 計(jì)算機(jī)網(wǎng)絡(luò)概述 網(wǎng)絡(luò)編程的實(shí)質(zhì)就是兩個(gè)(或多個(gè))設(shè)備(例如計(jì)算機(jī))之間的數(shù)據(jù)傳輸。 按照計(jì)算機(jī)網(wǎng)絡(luò)的定義,通過一定...
    蛋炒飯_By閱讀 1,370評(píng)論 0 10
  • 個(gè)人認(rèn)為,Goodboy1881先生的TCP /IP 協(xié)議詳解學(xué)習(xí)博客系列博客是一部非常精彩的學(xué)習(xí)筆記,這雖然只是...
    貳零壹柒_fc10閱讀 5,199評(píng)論 0 8
  • 1.1 TCP/IP協(xié)議組 TCP/IP協(xié)議(傳輸控制協(xié)議)由網(wǎng)絡(luò)層的IP協(xié)議和傳輸層的TCP協(xié)議組成 IP層負(fù)責(zé)...
    F麥子閱讀 2,923評(píng)論 0 25

友情鏈接更多精彩內(nèi)容