網絡編程上(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