詳解 ServerSocket與Socket類


(請觀看本人博文 —— 《詳解 網絡編程》)



ServerSocket與Socket

首先,本人來講解下 ServerSocket 類:

ServerSocket 類:

概述

這個類實現了服務器套接字
該類是遵循 TCP協議的,所以,必須要和客戶端Socket建立連接,才能完成信息的接送
服務器套接字等待來自網絡的請求
它基於該請求執行某些操作,然后可能向請求者返回結果。
服務器套接字的實際工作由SocketImpl類的一個實例進行。
一個應用程序可以更改創建套接字實現的套接字工廠
配置自己創建適合本地防火牆的套接字

那么,本人再來展示下這個類的構造方法
構造方法

  • ServerSocket()
    創建一個綁定服務器套接字
  • ServerSocket(int port)
    創建一個服務器套接字,綁定到指定的端口
  • ServerSocket(int port, int backlog)
    創建一個服務器套接字,並將其綁定到指定的本地端口號,並使用指定的積壓
  • ServerSocket(int port, int backlog, InetAddress bindAddr)
    用指定的端口創建一個服務器,聽積壓,和本地IP地址綁定

現在,本人再來展示下這個類的API
API

  • Socket accept()
    監聽要對這個套接字作出的連接並接受它
  • void bind(SocketAddress endpoint)
    ServerSocket綁定到一個特定的地址(IP地址和端口號)
  • void bind(SocketAddress endpoint, int backlog)
    ServerSocket綁定到一個特定的地址(IP地址和端口號)
  • void close()
    關閉這個套接字。
  • ServerSocketChannel getChannel()
    返回與此套接字關聯的獨特的 ServerSocketChannel對象,如果任何
  • InetAddress getInetAddress()
    返回此服務器套接字的本地地址
  • int getLocalPort()
    返回此套接字正在偵聽的端口號
  • SocketAddress getLocalSocketAddress()
    返回此套接字綁定到的端點的地址
  • int getReceiveBufferSize()
    得到這個 ServerSocket的 SO_RCVBUF期權的價值,即該緩沖區的大小,將用於接受來自這 ServerSocket插座
  • boolean getReuseAddress()
    如果 SO_REUSEADDR啟用
  • int getSoTimeout()
    檢索設置 SO_TIMEOUT
  • protected void implAccept(Socket s)
    子類使用此方法重載ServerSocket()返回自己的子類的插座
  • boolean isBound()
    返回的ServerSocket綁定狀態
  • boolean isClosed()
    返回的ServerSocket關閉狀態
  • void setPerformancePreferences(int connectionTime, int latency, int bandwidth)
    設置此ServerSocket性能偏好
  • void setReceiveBufferSize(int size)
    設置一個默認值為提出接受這 ServerSocket插座 SO_RCVBUF選項
  • void setReuseAddress(boolean on)
    啟用/禁用 SO_REUSEADDR套接字選項
  • static void setSocketFactory(SocketImplFactory fac)
    設置服務器套接字實現工廠為應用程序。
  • void setSoTimeout(int timeout)
    啟用/禁用 SO_TIMEOUT以指定的超時時間,以毫秒為單位
  • String toString()
    返回此套接字作為 String實現的地址與端口

由於該類必須與Socket類對象建立連接后才能進行正常的網絡通信,所以,本人在講解完Socket類之后再來展示部分API的使用。


Socket類:

概述

這個類實現了客戶端套接字(也被稱為“套接字”)
該類遵循TCP協議,所以必須與ServerSocket建立連接后,才能進行信息的接送
套接字是兩台機器之間的通信的一個端點
套接字的實際工作是由該類的一個實例進行SocketImpl
一個應用程序,通過改變創建套接字實現的套接字工廠,可以配置自己創建適合本地防火牆的套接字

現在,本人來展示下這個類的構造方法
構造方法

  • Socket()
    創建一個連接的套接字,與socketimpl系統默認的類型。
  • Socket(InetAddress address, int port)
    創建一個流套接字,並將其與指定的IP地址中的指定端口號連接起來。
  • Socket(InetAddress host, int port, boolean stream)
    過時的。
    使用UDP傳輸DatagramSocket。
  • Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
    創建一個套接字,並將其與指定的遠程端口上的指定的遠程地址連接起來。
  • Socket(Proxy proxy)
    創建一個連接的套接字類型,指定代理,如果有,應該使用無論任何其他設置。
  • protected Socket(SocketImpl impl)
    創建一個用戶指定的socketimpl連接插座。
  • Socket(String host, int port)
    創建一個流套接字,並將其與指定的主機上的指定端口號連接起來。
  • Socket(String host, int port, boolean stream)
    過時的。
    使用UDP傳輸DatagramSocket。
  • Socket(String host, int port, InetAddress localAddr, int localPort)
    創建一個套接字,並將其連接到指定的遠程端口上的指定的遠程主機上

那么,本人再來展示下這個類的API
API

  • void bind(SocketAddress bindpoint)
    將套接字綁定到本地地址。
  • void close()
    關閉這個套接字。
  • void connect(SocketAddress endpoint)
    將此套接字連接到服務器。
  • void connect(SocketAddress endpoint, int timeout)
    將此套接字與指定的超時值連接到服務器。
  • SocketChannel getChannel()
    返回與此套接字關聯的獨特的 SocketChannel對象,如果任何。
  • InetAddress getInetAddress()
    返回套接字連接的地址。
  • InputStream getInputStream()
    返回此套接字的輸入流。
  • boolean getKeepAlive()
    如果 SO_KEEPALIVE啟用。
  • InetAddress getLocalAddress()
    獲取綁定的套接字的本地地址。
  • int getLocalPort()
    返回此套接字綁定的本地端口號。
  • SocketAddress getLocalSocketAddress()
    返回此套接字綁定到的端點的地址。
  • boolean getOOBInline()
    如果 SO_OOBINLINE啟用。
  • OutputStream getOutputStream()
    返回此套接字的輸出流。
  • int getPort()
    返回此套接字連接的遠程端口號。
  • int getReceiveBufferSize()
    得到這個 Socket的 SO_RCVBUF選項的值,是由平台用於該 Socket輸入緩沖區的大小。
  • SocketAddress getRemoteSocketAddress()
    返回此套接字連接的端點的地址,或如果它是無關的 null。
  • boolean getReuseAddress()
    如果 SO_REUSEADDR啟用。
  • int getSendBufferSize()
    得到這個 Socket的 SO_SNDBUF期權價值,即緩沖區的大小由平台用於輸出在這 Socket。
  • int getSoLinger()
    返回設置 SO_LINGER。
  • int getSoTimeout()
    返回設置 SO_TIMEOUT。
  • boolean getTcpNoDelay()
    如果 TCP_NODELAY啟用。
  • int getTrafficClass()
    獲取從這個套接字發送的數據包的IP頭中的業務類或服務類型
  • boolean isBound()
    返回套接字的綁定狀態。
  • boolean isClosed()
    返回套接字的關閉狀態。
  • boolean isConnected()
    返回套接字的連接狀態。
  • boolean isInputShutdown()
    返回套接字連接的讀半是否關閉。
  • boolean isOutputShutdown()
    返回套接字連接的寫是否關閉的是否關閉。
  • void sendUrgentData(int data)
    在套接字上發送一個字節的緊急數據。
  • void setKeepAlive(boolean on)
    啟用/禁用 SO_KEEPALIVE。
  • void setOOBInline(boolean on)
    啟用/禁用 SO_OOBINLINE(TCP緊急數據收據)默認情況下,此選項是禁用TCP套接字上接收緊急數據是默默丟棄。
  • void setPerformancePreferences(int connectionTime, int latency, int bandwidth)
    設置此套接字的性能首選項。
  • void setReceiveBufferSize(int size)
    集 SO_RCVBUF選項,這 Socket指定值。
  • void setReuseAddress(boolean on)
    啟用/禁用 SO_REUSEADDR套接字選項。
  • void setSendBufferSize(int size)
    設置這個 Socket指定值的 SO_SNDBUF選項。
  • static void setSocketImplFactory(SocketImplFactory fac)
    設置客戶端套接字實現工廠的應用程序。
  • void setSoLinger(boolean on, int linger)
    啟用/禁用 SO_LINGER與指定的逗留的時間秒。
  • void setSoTimeout(int timeout)
    啟用/禁用 SO_TIMEOUT以指定的超時時間,以毫秒為單位。
  • void setTcpNoDelay(boolean on)
    啟用/禁用 TCP_NODELAY(禁用/啟用Nagle的算法)。
  • void setTrafficClass(int tc)
    集交通類或從該套接字發送數據包的IP報頭字節型服務。
  • void shutdownInput()
    將此套接字的輸入流放在“流結束”中。
  • void shutdownOutput()
    禁用此套接字的輸出流。
  • String toString()
    將這一 String插座

那么,現在,本人來通過兩個例子來展示下這兩個類的使用:
例1

題目
這天右轉哥玩游戲的時候,意外發現了游戲的一個Bug,於是,就向游戲公司發送信息,准備上報這個Bug
要求
編寫一個服務器端的代碼,再編寫一個客戶端的代碼,完成客戶端向服務器端的Bug上報

那么,本人來展示下代碼:

首先是服務器端的代碼:

package edu.youzg.about_net.about_tcp.core;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPServer {

    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(6666);
        System.out.println("服務器已經開啟,等待連接。。。");
        Socket sk = ss.accept();
        //循環讀取客戶端發來的消息
        while (true){
            InputStream in = sk.getInputStream();
            String ip = sk.getInetAddress().getHostAddress();
            byte[] bytes = new byte[1024];
            int len = in.read(bytes);
            String s = new String(bytes, 0, len);
            if(s.equals("byebye")){
                break;
            }
            System.out.println(ip+":給你發來消息內容是:"+s);
        }
        ss.close();
    }

}

現在是客戶端的代碼:

package edu.youzg.about_net.about_tcp.core;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;

public class TCPClient {

    public static void main(String[] args) throws IOException {
        //客戶端鍵盤錄入服務器控制台輸出
        Socket sk = new Socket("localhost", 6666);
        BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));
        while (true){
            System.out.println("請輸入消息");
            String msg= bfr.readLine();
            //發送給服務端
            OutputStream out= sk.getOutputStream();
            out.write(msg.getBytes());
            if ("byebye".equals(msg)) {
                break;
            }
        }
        //釋放資源
        bfr.close();
    }

}

那么,現在,本人再來展示下運行結果

首先是客戶端的控制台:
在這里插入圖片描述

接下來是服務器端的控制台:
在這里插入圖片描述


例2

題目
有一個壁紙很好康,右轉哥的兩個朋友十分想要,但是在網上找不到,朋友電腦上只有能運行Java程序的App,所以只能求右轉哥想辦法
要求
通過網絡編程所學知識,將目標圖片傳送至那兩個朋友的電腦上

首先是 一個能夠上傳文件的線程實現類:

package edu.youzg.about_net.upload_file.core;

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

public class ServerThread extends Thread{
    Socket sk;
    public ServerThread(Socket sk) {
        this.sk=sk;
    }

    @Override
    public void run() {
        try {
            InputStream in = sk.getInputStream();
            OutputStream out = sk.getOutputStream();
            BufferedWriter bfw = new BufferedWriter(new FileWriter(System.currentTimeMillis() + "copyFile.txt"));   //由於本人只有一台電腦,所以就將文件名跟事件相關
            //包裝一下輸入流
            BufferedReader bfr = new BufferedReader(new InputStreamReader(in));
            String line = null;
            while ((line = bfr.readLine()) != null) {
                bfw.write(line);
                bfw.newLine();
                bfw.flush();
            }
            //告訴客戶端,文件上傳成功
            out.write("文件上傳成功".getBytes());

            bfw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

那么,本人先來展示下右轉哥要運行的代碼:

package edu.youzg.about_net.upload_file.core;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPServer {

    public static void main(String[] args) throws IOException {
        //服務器告訴瀏覽器上傳成功了
        ServerSocket ss = new ServerSocket(5555);
        System.out.println("服務器已經開啟。。。");
        int i=1;
        while (true){
            Socket sk = ss.accept(); //偵聽客戶端
            System.out.println((i++)+"個客戶端已經連接");
            //為每一個客戶端,開啟一個線程,去處理
            new ServerThread(sk).start();
        }
    }

}

接下來,本人再來展示下兩個朋友要運行的代碼:

package edu.youzg.about_net.upload_file.core;

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

public class TCPClient {

    public static void main(String[] args) throws IOException {
        //給服務上傳一個文本文件
        Socket socket = new Socket("localhost", 5555);
        //獲取通道中的輸入輸出流
        InputStream in= socket.getInputStream();
        OutputStream out = socket.getOutputStream();
        //讀取文本文件
        BufferedReader bfr = new BufferedReader(new FileReader("test.txt"));
        String line=null;
        //把通道中的輸出流包裝一下
        BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(out));
        while ((line=bfr.readLine())!=null){
            bfw.write(line);
            bfw.newLine();
            bfw.flush();
        }
        //禁用此套接字的輸出流。
        socket.shutdownOutput();
        //讀取服務端反饋
        byte[] bytes = new byte[1024];
        int len = in.read(bytes);//阻塞式方法

        String s = new String(bytes, 0, len);
        System.out.println(s);
        //釋放資源
        bfr.close();
        socket.close();

    }

}

那么,現在,本人來展示下運行結果:
首先,本人來展示下源文件的目錄信息和源文件內容:
在這里插入圖片描述
現在,本人來展示下運行后所生成的文件和該文件的內容:
在這里插入圖片描述
在這里插入圖片描述
那么,可以看到,我們將文件上傳成功了!


(本人 網絡編程 總集篇博文鏈接:https://www.cnblogs.com/codderYouzg/p/12419011.html)


免責聲明!

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



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