1. 程式人生 > >JAVA網路程式設計(TCP篇入門)

JAVA網路程式設計(TCP篇入門)

此次部落格主要以程式碼為主,其中包含了豐富的註釋

簡單的tcp

簡單介紹tcp是如何傳送資料,以及接受資料

程式碼一:客戶端

package com.net.tcp;

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

/**
 * TCP協議傳送資料的步驟
 * A:建立傳送資料的socket物件。
 *  建立物件的時候要指定目標主機和埠
 * B:獲取socket物件的輸出流
 *  是位元組流還是字元流?位元組流。
 * C:寫資料
 * D:釋放資源
 * 
 * @author
yuliyang * @version $Id: ClientDemo.java, v 0.1 2016年11月23日 下午10:57:55 yuliyang Exp $ */
public class ClientDemo { public static void main(String[] args) throws IOException { //A:建立傳送資料的socket物件 //Socket(InetAddress address, int port) //Socket(String host, int port) //java.net.ConnectException: Connection refused: connect
//如果你先啟動了客戶端,發現如上錯誤,是因為服務端沒有開啟,TCP協議的程式,必須先開啟伺服器 Socket s = new Socket("192.168.31.222", 10086); //B:獲取socket物件的輸出流 OutputStream os = s.getOutputStream(); //C: os.write("hello write".getBytes()); //D: os.close(); s.close(); } }

程式碼一:服務端

package com.net.tcp;

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

/**
 * TCP協議接收資料的步驟
 * A:建立接收資料的socket物件。
 *  建立物件的時候要指定埠
 * B:監聽客戶端連線,
 *      等待客戶端連線
 * C:讀資料,並顯示在控制檯
 * D:釋放資源
 * 注意事項;伺服器需要先開啟
 * @author yuliyang
 * @version $Id: ClientDemo.java, v 0.1 2016年11月23日 下午10:57:55 yuliyang Exp $
 */
public class ServerDemo {
    public static void main(String[] args) throws IOException {
        //A:ServerSocket(int port) 
        ServerSocket serverSocket = new ServerSocket(10086);
        //B:監聽客戶端連線
        // Socket accept()  偵聽並接受到此套接字的連線。
        Socket s = serverSocket.accept();//此處為阻塞式方法
        //C:獲取socket物件的輸入流,並讀取資料
        InputStream is = s.getInputStream();
        byte[] buf = new byte[1024];
        int len = is.read(buf);
        //此處為解析收到的資料
        String data = new String(buf, 0, len);
        System.out.println("data" + data);
        //D:釋放資源
        is.close();
        serverSocket.close();
    }
}

如果上面的程式碼你看懂了的話,那就接著繼續玩耍吧。

程式碼二:客戶端,新增獲取了服務端返回的資訊

package com.net.tcp2;

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

public class ClientDemo {
    public static void main(String[] args) throws IOException {
        //建立客戶端socket
        Socket socket = new Socket("192.168.31.222", 12312);
        /**
         * 使用通道輸出流寫資料
         */
        OutputStream outputStream = socket.getOutputStream();

        outputStream.write("我是傳送的".getBytes());
        /**
         * 使用通道輸入流獲取返回的訊息
         */
        InputStream inputStream = socket.getInputStream();
        byte[] b = new byte[1024];
        int len = inputStream.read(b);
        String s = new String(b, 0, len);
        System.out.println("客戶端獲取到的響應是:" + s);
        socket.close();
    }
}

程式碼二:服務端

package com.net.tcp2;

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

public class ServerDemo {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(12312);
        Socket s = serverSocket.accept();
        InputStream inputStream = s.getInputStream();
        byte[] buf = new byte[1024];
        int len = inputStream.read(buf);
        String data = new String(buf, 0, len);
        System.out.println("服務端獲取到的資料是:" + data);
        /**
         * 使用通道返回響應,告訴客戶端結果
         */
        OutputStream outputStream = s.getOutputStream();
        outputStream.write("我接收到了".getBytes());
        //釋放資源
        serverSocket.close();
        inputStream.close();
        outputStream.close();
    }
}

程式碼三:客戶端 新增需求:看註釋

package com.net.tcp3;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

/**
 * 需求:把傳送的資料改進為來自鍵盤錄入,
 * 客戶端傳送資料用鍵盤錄入,服務端把資料顯示即可
 * 
 * @author yuliyang
 * @version $Id: ClientDemo.java, v 0.1 2016年11月24日 下午9:08:14 yuliyang Exp $
 */
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        Socket s = new Socket("192.168.31.222", 10010);
        //讀取鍵盤錄入的資料
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        //封裝:將通道內的輸出位元組流轉化為字元流
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        String line = null;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        s.close();
    }
}

程式碼三:服務端

package com.net.tcp3;

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

public class ServerDemo {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(10010);
        Socket s = serverSocket.accept();
        BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        String line = null;
        while ((line = br.readLine()) != null) {
            System.out.println("接收的資料為:" + line);
        }
        //釋放資源
        s.close();
        serverSocket.close();
    }
}

程式碼四:客戶端

需求:服務端需要將從客戶端獲取的資源寫入到檔案中

package com.net.tcp5;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class ClientDemo {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("192.168.31.222", 10086);
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line = null;
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        socket.close();
    }
}

程式碼四:服務端

package com.net.tcp5;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerDemo {
    public static void main(String[] args) throws IOException {
        //建立伺服器socket物件
        ServerSocket serverSocket = new ServerSocket(10086);
        //監聽客戶端連線
        Socket socket = serverSocket.accept();//阻塞式
        //封裝通道內的輸入流
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        //將資料寫入到檔案中
        BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\a.txt"));
        String line = null;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        bw.close();
        serverSocket.close();
    }
}

程式碼五:客戶端

需求:客戶端讀取本地檔案,並傳送給服務端,服務端收到檔案之後,並copy一份

package com.net.tcp6;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class ClientDemo {
    public static void main(String[] args) throws IOException {
        //建立客戶端的物件
        Socket s = new Socket("192.168.31.222", 10086);
        //讀取檔案的資料
        BufferedReader br = new BufferedReader(new FileReader("InetAddressDemo.java"));
        //把通道的輸出流包裝
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        String line = null;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        s.close();
        br.close();
    }
}

程式碼五:服務端

package com.net.tcp6;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerDemo {
    public static void main(String[] args) throws IOException {
        //建立伺服器物件
        ServerSocket serverSocket = new ServerSocket(10086);
        //監聽客戶端連線
        Socket s = serverSocket.accept();
        //把通道內的輸入流封裝一下
        BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        //把輸入流輸出到檔案
        BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.txt"));
        String line = null;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        serverSocket.close();
        bw.close();

    }
}

程式碼六:客戶端

需求:在檔案接收完成之後,伺服器需要通知客戶端,檔案接收完成
問題:會因為阻塞式,導致接收不到反饋訊息
解決方案:A:自定義結束標籤
B:使用socket自帶的方法
此處只展現socket自帶方案

package com.net.tcp7;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

/**
 * 我把檔案發給你了,你沒有告訴我檔案你是否收到檔案
 * 需要服務端給我一個反饋
 * 
 * @author yuliyang
 * @version $Id: ClientDemo.java, v 0.1 2016年11月24日 下午10:21:16 yuliyang Exp $
 */
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        //建立客戶端的物件
        Socket s = new Socket("192.168.31.222", 10086);
        //讀取檔案的資料
        BufferedReader br = new BufferedReader(new FileReader("InetAddressDemo.java"));
        //把通道的輸出流包裝
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        String line = null;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        /**
         * 接收從服務端返回的資訊
         * 此處發現無法進行到這裡,由於服務端阻塞,
         * 因為伺服器無法判斷我們之前的資料是否已經傳輸完畢,
         * 此時socket提供了一個方法:
         *  shutdownOutput
         * 禁用輸出流  方法
         */
        s.shutdownOutput();
        BufferedReader infoByServer = new BufferedReader(new InputStreamReader(s.getInputStream()));

        String data = infoByServer.readLine();//阻塞式
        System.out.println("client" + data);
        s.close();
        br.close();
    }
}

程式碼六:服務端

package com.net.tcp7;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 收到檔案之後,給客戶端一個反饋
 * 
 * @author yuliyang
 * @version $Id: ServerDemo.java, v 0.1 2016年11月24日 下午10:22:00 yuliyang Exp $
 */
public class ServerDemo {
    public static void main(String[] args) throws IOException {
        //建立伺服器物件
        ServerSocket serverSocket = new ServerSocket(10086);
        //監聽客戶端連線
        Socket s = serverSocket.accept();
        //把通道內的輸入流封裝一下
        BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        //把輸入流輸出到檔案
        BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.txt"));
        String line = null;
        while ((line = br.readLine()) != null) {//阻塞式
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        /**
         * 新增反饋
         * 從通道將反饋返回回去
         */
        BufferedWriter feadback = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        feadback.write("資料接收成功了");
        feadback.newLine();
        feadback.flush();
        serverSocket.close();
        bw.close();

    }
}

希望看到我的文章的人可以多給反饋,thanks