網絡編程下(TCP)

網絡編程上(UDP):
https://blog.csdn.net/Veer_c/article/details/103843591
網絡編程下(TCP):
https://blog.csdn.net/Veer_c/article/details/103843825

TCP協議要點:

TCP協議:(寫一個demo)
特點:
1.需要建立通道
2.傳送大量數據無限制
3.面向連接
4.可靠
5.速度慢

TCp協議書寫步驟:
			發送端:
			   /* TCP協議發送數據步驟:
				* A:創建TCP協議發送端Socket對象
				* 指定服務器IP及端口
				Socket sk = new Socket(“192.168.3.120” , 9527) ;
				* B:獲取輸出流,並寫數據
				OutputStream outputStream = sk.getOutputStream() ;
				outputStream.write(“hello,TCP我來了”.getBytes()) ;
				* C:釋放資源
				sk.close() ;
				* java.net.ConnectException: Connection refused: connect
				* TCP協議是不能直接運行客戶端的,必須先運行服務器。因爲他是一種可靠的協議。  */
             接收端:
             /*  * TCP協議接收數據步驟:
                 * A:創建TCP協議接收端Socket對象
                   ServerSocket ss = new ServerSocket(9527) ;
                 * B:監聽客戶端連接
                   Socket sk = ss.accept() ;
                 * C:獲取輸入流,並讀取數據,顯示在控制檯
                 // 讀取數據
                byte[] bytes = new byte[1024] ;
                int len = inputStream.read(bytes) ;
                // public InetAddress getInetAddress()獲取IP地址
                InetAddress inetAddress = sk.getInetAddress() ;
                String ip = inetAddress.getHostAddress() ;
                // 輸出
                System.out.println(ip + "發來數據是: " + new String(bytes , 0 , len));
                 * D:釋放資源
                 sk.close() ;            */

用TCP協議寫一個數據的發送和接收,接收端接收到數據之後給發送端一個反饋

//客戶端:
package com.edu_06;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class TcpClient {
    public static void main(String[] args) throws Exception {
        //創建tcp發送端的sockt對象
        Socket sk = new Socket("127.0.0.1", 10000);
        //從通道中獲取輸出流
        OutputStream os = sk.getOutputStream();
        //網通道中寫數據
        os.write("今晚約嗎".getBytes());
        //接受來自服務器端的反饋
        InputStream is = sk.getInputStream();
        //解析is
        byte[] buf = new byte[1024];
        int len = is.read(buf);
        System.out.println(new String(buf, 0, len));
        //釋放資源
        sk.close();
    }
}
//服務端:
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServer {
    public static void main(String[] args) throws Exception {
        //創建服務器端的socket對象
        ServerSocket ss = new ServerSocket(10000);
        //監聽來自客戶端的連接
        Socket sk = ss.accept();
        //從通道中獲取輸入流讀取數據
        InputStream is = sk.getInputStream();
        //解析is
        byte[] buf = new byte[1024];
        int len = is.read(buf);
        System.out.println(new String(buf, 0, len));
        //給客戶端一個反饋
        OutputStream os = sk.getOutputStream();
        os.write("不約".getBytes());
        //釋放資源
        sk.close();
    }
}

注意:在運行程序的時候,不能先運行客戶端,會拋出java.net.ConnectException: Connection refused: connect 異常
因爲服務端還沒有建立一個鏈接,客戶端就將數據傳輸過來了,因此會拋出異常,由此也證明了tcp協議是面向連接過程的一個協議。

tcp協議數據的發送和接收
tcp協議在傳輸過程的時候,是需要一連接的,首先在客戶端和服務端分別創建socket對象,而在服務端的socket對象必須調用accept方法,因爲他要監聽來自客戶端的鏈接,一旦連接成功之後,客戶端和服務端會形成一個傳遞信息的通道,客戶端利用IO流將數據寫入同道中,服務端將數據讀取 ,這就完成了數據在客戶端和服務端的傳遞。

需求1: 客戶端鍵盤錄入數據,服務器端接收數據在控制檯輸出。

package com.edu_07;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
/*  需求: 客戶端鍵盤錄入數據,服務器端接收數據在控制檯輸出 */
public class TcpClient {
    public static void main(String[] args) throws Exception {
        //創建tcp發送端socket對象
        Socket sk = new Socket("192.168.191.1", 20000);
        //創建鍵盤錄入對象
        Scanner sc = new Scanner(System.in);
        String line;
        while ((line=sc.nextLine())!=null) {
            //將line這個數據寫如通道
            OutputStream os = sk.getOutputStream();
            os.write(line.getBytes());
        }
        sk.close();
    }
}

需求2:客戶端鍵盤錄入數據,服務端將數據寫入文件。

package com.edu_08;
//客戶端
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class TcpClient {
    public static void main(String[] args) throws Exception {
        /**
         * 2.5
            需求:客戶端鍵盤錄入數據,服務端將數據寫入文件
            客戶端
            一次寫一行

            服務端:
            一次讀取一行,將讀取到的內容寫入文件
         */
        //創建tcp客戶端socket對象
        Socket sk = new Socket("127.0.0.1", 10010);
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(sk.getOutputStream()));

        //創建鍵盤錄入對象
        Scanner sc = new Scanner(System.in);
        String line;
        while ((line=sc.nextLine())!=null) {
            //往通道中寫數據,一次寫一行
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        sk.close();
    }
}
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 TcpServer {
    public static void main(String[] args) throws Exception {
        //創建服務器端的socket對象
        ServerSocket ss = new ServerSocket(10010);
        //監聽客戶端連接
        Socket sk = ss.accept();
        //從sk的通道中讀取數據,一次讀取一行
        BufferedReader br = new BufferedReader(new InputStreamReader(sk.getInputStream()));
        BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
        //一次讀取一行數據
        String line;
        while ((line=br.readLine())!=null) {
            //line就是已經讀取到的數據,我們現在需要將line這個數據寫入文件
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        sk.close();
        bw.close();
        br.close();
    }
}

需求3:客戶端讀取文本文件中的內容發送給服務端,服務端將內容控制檯輸出

package com.edu_09;

import java.io.BufferedReader;
public class TcpClient {
    public static void main(String[] args) throws Exception {
        //創建socket對象
        Socket sk = new Socket("192.168.20.254", 2000);
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(sk.getOutputStream()));
        //讀取文本一次讀取一行
        BufferedReader br = new BufferedReader(new FileReader("a.txt"));
        String line;
        while ((line=br.readLine())!=null) {
            //line就是我讀取到的數據,我需要將這個數據寫入通道,一次寫一行
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        //釋放資源
        br.close();
        bw.close();
        sk.close();
    }
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServer {
    public static void main(String[] args) throws Exception {
        //創建服務器端的socket對象
        ServerSocket ss = new ServerSocket(2000);
        //蔣婷來自於客戶端的連接
        Socket sk = ss.accept();
        //創建BufferedReader一次讀取一行數據
        BufferedReader br = new BufferedReader(new InputStreamReader(sk.getInputStream()));
        String line;
        while ((line=br.readLine())!=null) {
            System.out.println(line);
        }
        //釋放資源
        br.close();
        sk.close();
    }
}

注意:我們在UDP協議中,再創建socket對象的時候調用的是DatagramSocket()這個方法,在傳輸數據的時候,需要創建數據包, 調用的是DatagramPacket()方法,在接受數據的時候我們還需要創建一個空包來讀取數據。
而在TCP協議中我們創建客戶端對象的時候,我們可以調用Socket方法,直接將ip地址和端口傳進去,而在創建服務端的對象的時候,我們要調用ServerSocket()方法,然後在調用accept方法,監聽來自客戶端的鏈接。在運行的時候,我們先運行服務端,程序運行在ss.accept()阻塞,然後運行客戶端,服務端與客戶端建立鏈接,程序才能繼續往下運行。

需求4: 上傳文本文件
客戶端:
a: 讀取文本文件中的數據
b: 發送到服務器端
服務器:
a: 讀取流通道中的數據
b: 把數據寫入到文本文件中

需求5:運用多線程改進需求4:

package com.edu_10;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
/**
 *  需求5:客戶端讀取文本文件中的內容發送給服務端,服務端將內容控制檯輸出
 *  客戶端:
 *  1.讀取文本文件,一次讀取一行
 *  2.將讀取到的內容寫入通道,一次寫一行
 *  3.釋放資源
 *  服務器端:   
 *  1.從通道中讀取數據,一次讀取一行
 *  2.輸出    */
public class TcpClient {
    public static void main(String[] args) throws Exception {
        //創建socket對象
        Socket sk = new Socket("192.168.20.254", 2000);
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(sk.getOutputStream()));
        //讀取文本一次讀取一行
        BufferedReader br = new BufferedReader(new FileReader("InetAddressDemo.java"));
        String line;
        while ((line=br.readLine())!=null) {
            //line就是我讀取到的數據,我需要將這個數據寫入通道,一次寫一行
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        //釋放資源
        br.close();
        bw.close();
        sk.close();
    }
}
package com.edu_10;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class ServerThread implements Runnable{
    Socket sk;
    public ServerThread(Socket sk){
        this.sk = sk;
    }
    @Override
    public void run() {
        try {
            //創建BufferedReader一次讀取一行數據
            BufferedReader br = new BufferedReader(new InputStreamReader(sk.getInputStream()));
            BufferedWriter bw = new BufferedWriter(new FileWriter(UUIDUtils.getFileName()));
            String line;
            while ((line=br.readLine())!=null) {
                bw.write(line);
                bw.newLine();
                bw.flush();
                //System.out.println(line);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
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 TcpServer {
    public static void main(String[] args) throws Exception {
        //創建服務器端的socket對象
        ServerSocket ss = new ServerSocket(2000);
        while (true) {
            //蔣婷來自於客戶端的連接
            Socket sk = ss.accept();
            //啓動一個子線程,去執行復制文件的動作
            new Thread(new ServerThread(sk)).start();
        }
    }
}
//創建UUIDUtils類,用於創鍵隨機產生的文件名稱
import java.util.UUID;
import org.junit.Test;
public class UUIDUtils {
    @Test
    public static String getFileName(){
        String fileName = UUID.randomUUID().toString();
        fileName = fileName.replaceAll("-", "")+".txt";
        return fileName;
    }
}

注意:在上傳文件的時候,我們可以利用 UUID這個類,獲取類型 4(僞隨機生成的)UUID 的靜態工廠, 使用加密的強僞隨機數生成器生成該 UUID。

提問:我們以後倒是使用udp協議還是tcp協議呢?
以後使用的軟件當中基本都是udp和tcp混用的。

網絡編程上(UDP):
https://blog.csdn.net/Veer_c/article/details/103843591
網絡編程下(TCP):
https://blog.csdn.net/Veer_c/article/details/103843825

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章