上面我們瞭解了Udp編程,接下來讓我們再來看看Tcp編程
首先分析一下Udp和Tcp之間的區別?
1)Udp是無連接,接收端只管接收;而Tcp是基於面向裏連接的(例如打電話的時候你得先撥號碼)
2)Udp無法確保數據的安全傳送,有可能會丟失數據;而Tcp是可以保證安全傳輸的
3)Udp是通過創建數據報包進行傳輸的,而Tcp是通過流的模式去進行傳輸的
4)Udp效率高傳輸速度快,但是安全性低;Tcp效率低傳輸速度慢,安全性高
Tcp編程的原理分析:
1)同樣需要客戶端和服務端都創建Socket對象,並且兩者的端口號必須一致
2)服務端必須去監聽客戶端的連接,這樣二者之間就會產生一種通道連接
3)當通道產生後,可以通過字節流去寫數據給服務器端或者服務器端也可以反饋信息給客戶端
4)最後關閉資源
首先用Tcp進行簡單的數據傳輸
package com.westos.Tcp;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
/**
*Tcp編程的引入
*
*/
public class ClientDome {
public static void main(String[] args) throws IOException {
/**
* 1)創建Socket類對象
* 構造方法:
* public Socket(String host, int port):創建客戶端套接字對象,並且指定端口號和ip文本形式
*/
Socket s=new Socket("192.168.43.204",12334);
/**
* 2)獲取通道內的輸出流對象
* public OutputStream getOutputStream():獲取套接字 的輸出流
*/
OutputStream out = s.getOutputStream();
/**
* 3)給服務器端寫數據
*/
out.write("成吉思汗,只識彎弓射大雕".getBytes());
/**
* 4)當服務器反饋給我們信息後客戶端也應該去接收它
*/
InputStream in = s.getInputStream();
//獲取數據
byte[] bys=new byte[1024];
int len = in.read(bys);
System.out.println(new String(bys,0,len));
//5)關閉資源
s.close();
}
}
package com.westos.Tcp;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDome {
public static void main(String[] args) throws IOException {
/**
* 1)創建ServerSocket類對象
* public ServerSocket(int port) throws IOException創建綁定到特定端口的服務器套接字
*/
ServerSocket ss=new ServerSocket(12334);
/**
* 2)監聽客戶端的連接
*/
Socket s = ss.accept();
/**
* 3)獲取通道內的輸入流對象
*/
InputStream in = s.getInputStream();
/**
* 4)讀取數據
*/
byte[] bys=new byte[1024];
int len = in.read(bys);
String data=new String(bys,0,len);
String ip = s.getInetAddress().getHostAddress();
/**
* 5)輸出數據
*/
System.out.println("from"+ip+"data is:"+data);
/**
* 6)當我們的服務器端收到客戶端的數據後,就需要反饋給客戶端
* 獲取通道內的輸出流對象
*/
OutputStream out = s.getOutputStream();
out.write("數據已經收到...".getBytes());
/**
* 7)關閉資源
*/
s.close();
}
}
練習1:
當我們想要去實現字符的傳輸時,應該怎麼做?
package com.westos.Tcp02;
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 ClientDome {
public static void main(String[] args) throws IOException {
//創建Socket對象
Socket s=new Socket("192.168.43.204",1112);
//創建字符緩衝輸入流的錄入方式
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
//封裝數據通道中的輸出流
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
//寫入數據
String line=null;
while((line=br.readLine())!=null) {
//進行結束的條件
if("over".equals(line)) {
break;
}
//寫入讀取的數據
bw.write(line);
bw.newLine();
bw.flush();
}
//關閉資源(在這裏不要關閉bw和br,因爲它要不停的錄入數據和讀取數據,)
s.close();
}
}
package com.westos.Tcp02;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 服務器端
*
*/
public class ServerDome {
public static void main(String[] args) throws IOException {
//創建Socket類對象
ServerSocket ss=new ServerSocket(1112);
//去監聽客戶端的連接
Socket s = ss.accept();
//封裝通道內的輸入流對象
BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
//讀取數據
String line=null;
while((line=br.readLine())!=null) {
System.out.println(line);
}
//關閉資源
s.close();
}
}
練習2:
當我們想將客戶端中的文本里的數據傳輸給服務器端應該怎麼做?
package com.westos.Tcp03;
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 ClientText {
public static void main(String[] args) throws IOException {
//創建Socket類對象
Socket s=new Socket("192.168.43.204",2202);
//創建字符輸入流對象
BufferedReader br=new BufferedReader(new FileReader("ReceiveDome.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.westos.Tcp03;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDome {
public static void main(String[] args) throws IOException {
//創建Socket類對象
ServerSocket ss=new ServerSocket(2202);
//去監聽客戶端的連接
Socket s = ss.accept();
//創建字符緩衝輸入流對象
BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
String line=null;
while((line=br.readLine())!=null) {
System.out.println(line);
}
//關閉資源
s.close();
}
}
練習3:
當我們想將客戶端中的文本數據copy到服務器端的文件中應該怎麼做?
package com.westos.Tcp04;
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 ClientDome {
public static void main(String[] args) throws IOException {
//創建Socket對象
Socket s=new Socket("192.168.43.204",23456);
//創建字符緩衝輸入流對象
BufferedReader br=new BufferedReader(new FileReader("ReceiveDome.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.shutdownOutput();
//當服務器端反饋給你信息後需要你去接收它
//創建通道中的輸入流對象
BufferedReader bwClient=new BufferedReader (new InputStreamReader(s.getInputStream()));
String str = bwClient.readLine();
System.out.println(str);
//關閉資源
s.close();
br.close();
}
}
package com.westos.Tcp04;
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 ServerDome {
public static void main(String[] args) throws IOException {
//創建Socket類對象
ServerSocket ss=new ServerSocket(23456);
//監聽客戶端的連接
Socket s = ss.accept();
//創建字符緩衝輸出流對象
BufferedWriter bw=new BufferedWriter(new FileWriter("copy.java"));
//封裝通道中的輸入流對象
BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
//讀取並寫入數據
String line=null;
while((line=br.readLine())!=null) {
bw.write(line);
bw.newLine();
bw.flush();
}
//數據讀取完畢後需要給客戶端反饋讀取完畢的信息
//創建通道中的字符緩衝輸出流對象
BufferedWriter bwServer=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
bwServer.write("文本複製好了...");
bwServer.newLine();
bwServer.flush();
//關閉資源
s.close();
bw.close();
}
}
練習4:
將圖片進行復制,但是在複製的時候有一些要點需要我們注意:
1)複製圖片的時候,我們應該運用字節流而不是字符流
2)在圖片複製完成後,我們會發現圖片的內存有差,沒有完全加載完,這是需要我們的OutputStream類中的Flush方法去強制刷新數據
例如:
package com.westos.Tcp05;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
/*
* 這裏我們將進行圖片的複製
* 這裏將不能使用字符流的形式了,應該改成字節流
*/
public class ClientDome {
public static void main(String[] args) throws IOException {
//創建Socket類對象
Socket s=new Socket("192.168.43.204",2345);
//封裝通道中的輸出流對象
BufferedOutputStream bos=new BufferedOutputStream(s.getOutputStream());
//創建字節緩衝輸入流對象
BufferedInputStream bis=new BufferedInputStream(new FileInputStream("圖7.jpg"));
//讀取數據
byte[] bys=new byte[1024];
int len=0;
while((len=bis.read(bys))!=-1) {
bos.write(bys, 0, len);
//flush() :刷新此輸出流並強制寫出所有緩衝的輸出字節
bos.flush();
}
//通知服務器端去接收數據
s.shutdownOutput();
//接收服務器端的反饋信息
InputStream in = s.getInputStream();
byte[] b=new byte[1024];
int l = in.read(b);
String date=new String(b, 0, l);
System.out.println(date);
//關閉資源
s.close();
bis.close();
}
}
package com.westos.Tcp05;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDome {
@SuppressWarnings("resource")
public static void main(String[] args) throws IOException {
//創建Socket對象
ServerSocket ss=new ServerSocket(2345);
//監聽客戶端的連接
Socket s = ss.accept();
//封裝通道內的輸入流對象
BufferedInputStream bis=new BufferedInputStream(s.getInputStream());
//創建字節緩衝輸出流對象
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("copy.jpg"));
//讀寫數據
byte[] bys=new byte[1024];
int len=0;
while((len=bis.read(bys))!=-1) {
bos.write(bys, 0, len);
//flush() :刷新此輸出流並強制寫出所有緩衝的輸出字節
bos.flush();
}
//讀取完畢後反饋給客戶端
OutputStream out = s.getOutputStream();
out.write("圖片已經複製好了...".getBytes());
//關閉資源
s.close();
bos.close();
}
}