java實現一個簡單的網絡聊天程序


代碼

服務器端

package socket_demo;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class server {
    public static void main(String[] args) throws Exception {
        // 監聽指定的端口,阻塞直至客戶端連接此端口
        int port = 23333;
        ServerSocket server = new ServerSocket(port);
        System.out.println("server is waiting...");
        Socket socket = server.accept();
        System.out.println("Connected!");

        // 讀取從客戶端返回的輸入流,至尾端時返回-1
        InputStream input = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len;
        StringBuilder get = new StringBuilder();
        while ((len = input.read(bytes)) != -1) {
            get.append(new String(bytes, 0, len, "UTF-8"));
        }
        System.out.println("get message from client: " + get);

        OutputStream output = socket.getOutputStream();
        String sent = "Hi there";
        output.write(sent.getBytes("UTF-8"));
        System.out.println("sent message to client: " + sent);

        // 關閉socket與服務器端
        input.close();
        output.close();
        socket.close();
        server.close();
    }
}

 
客戶端

package socket_demo;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;


public class client {
    public static void main(String args[]) throws Exception {
        // 連接本地主機,端口自設,與服務端一致即可
        String host = "127.0.0.1";
        int port = 23333;
        // 通過socket與服務端建立連接
        Socket socket = new Socket(host, port);
        if(socket.isConnected()){
            System.out.println("Connected!");
        }
        // 將要發送的信息寫入輸出流
        OutputStream output = socket.getOutputStream();
        String sent = "hello";
        socket.getOutputStream().write(sent.getBytes("UTF-8"));
        // 關閉客戶端的輸出流(單向,並未關閉socket)
        socket.shutdownOutput();
        System.out.println("sent message to server: " + sent);

        // 讀取從server返回的輸入流
        InputStream input = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len;
        StringBuilder get = new StringBuilder();
        while ((len = input.read(bytes)) != -1) {
            get.append(new String(bytes, 0, len,"UTF-8"));
        }
        System.out.println("get message from server: " + get);

        // 關閉socket
        input.close();
        output.close();
        socket.close();
    }
}

測試結果

服務器端

 
客戶端

JAVA Socket API分析

以上代碼用到的JAVA SOCKET API主要有:
Socket(InetAddress address, int port) --創建一個流套接字並將其連接到指定的IP地址與指定端口
ServerSocket(int port)--服務器端綁定一個窗口
server.accept()--服務器端等待連接(持續阻塞)
socket.getInputStream()--返回此套接字的輸入流
socket.getOutputStream()--返回此套接字的輸出流
socket.close()--關閉此套接字
JAVA中方法的實現都要通過JVM翻譯給系統執行,所以JAVA SOCKET API與系統(本例為windows)SOCKET API有着對應關系。
我們通過在IDEA中使用Ctrl+Alt+HCtrl+Alt+B跟蹤查看api的調用棧,以server.accept()為例

雙擊右邊函數名,查看其調用,進一步查看ServerSocket.implAccept(Socket)






這里accept0()是一個native api,無法再繼續上溯
完整的調用棧為server.accept()->ServerSocket.implAccept(Socket) (java.net)->SocketImpl.accept(SocketImpl)
->AbstractPlainSocketImpl.socketAccept(SocketImpl)->PlainSocketImpl.accept0(int, InetSocketAddress[])
綜上,java socket中的server.accept()對應windows socket中的accept0(int var0, InetSocketAddress[] var1)
其它socket api也都有着類似的對應關系,通過查看調用棧可以一一查找,這里不再贅述


免責聲明!

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



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