利用socket技術實現用java實現客戶端向服務端傳送檔案,伺服器端接收檔案並給出一個響應。
通訊是網路程式設計中重要的組成部分,而socket程式設計是網路程式設計的基礎。利用socket可以實現客戶端和伺服器端的通訊。下面我先把客戶端和伺服器端的程式碼粘上去再進行詳細的分析。
package test1; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import org.junit.Test; public class test2 { @Test public void client(){ Socket socket = null; OutputStream oo = null; FileInputStream fis = null; InputStream io = null; try { //1.建立socket物件例項 socket = new Socket("127.0.0.1", 8989); //2.呼叫getOutputStream()方法,目的是建立資料緩衝區,將資料傳送到伺服器端 oo = socket.getOutputStream(); //3.建立FileInputStream物件例項,將要傳送的檔案寫入到輸出流資料緩衝區中 File file=new File("D:\\123.avi"); fis = new FileInputStream(file); byte[] b=new byte[1024]; int len; while((len=fis.read(b))!=-1){ oo.write(b, 0, len); } //這行程式碼的意思是告訴伺服器端我傳送的資料完畢。 socket.shutdownOutput(); //4.呼叫getInputStream()方法:目的是接收從伺服器端傳送的資料 io = socket.getInputStream(); byte[] b1=new byte[1024]; int len1; while((len1=io.read(b1))!=-1){ String str=new String(b1, 0, len1); System.out.println(str); } } catch (Exception e) { // 關閉各個連線 e.printStackTrace(); }finally{ if(io != null){ try { io.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(fis !=null){ try { fis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(oo != null){ try { oo.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(socket !=null){ try { socket.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } @Test public void server(){ ServerSocket ss = null; Socket s = null; InputStream is = null; FileOutputStream fos = null; OutputStream os = null; try { //1.建立ServerSocket物件的例項。 ss = new ServerSocket(8989); //2.呼叫accept()方法來建立通訊連線,期間經歷了三次握手,只不過我們看不到 s = ss.accept(); //3.呼叫getInputStream()方法來接收客戶端傳送的檔案 is = s.getInputStream(); //4.建立FileOutputStream()物件例項來儲存從客戶端傳送的檔案,並將檔案寫入到物件中 fos = new FileOutputStream(new File("D:\\123567.avi")); byte[] b=new byte[1024]; int len; while((len=is.read(b))!=-1){ fos.write(b, 0, len); } //5.向客戶端反饋資訊,將資訊儲存在資料緩衝區中 os = s.getOutputStream(); os.write("你傳送的視訊我已經接收".getBytes()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ if(os !=null){ try { os.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(fos != null){ try { fos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(is !=null){ try { is.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(s != null){ try { s.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(ss != null){ try { ss.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
基本知識點補充:
上述程式碼塊中我利用了junit進行模組測試,利用junit進行測試需要匯入junit-4.12.jar和hamcrest-core-1.3.jar這兩個jar包。在上面的程式碼中用到的知識點有socket,輸入流(InputStream)和輸出流(OutputStream)以及檔案輸入流(FileInputStream)和檔案輸出流(FileOutputStream)。
1.
從客戶端(Client)來看:socket.getInputStream()方法是接收服務端傳送的資料。socket.getOutputStream()方法是類似於一個數據緩衝器,用於儲存向伺服器端傳送的資料。
從伺服器端(Server)來看: socket.getInputStream()方法是接收客戶端傳送的資料。socket.getOutputStream()方法是類似於一個數據緩衝器,用於儲存向客戶端傳送的資料。
2.
FileInputStream:檔案輸入流是用來讀入資料的 ----------->讀入
FileOutputStream:檔案輸出流是用來寫出資料的----------->寫出
3.計算機網路中三次握手實現原理
在TCP/IP協議中,TCP協議提供可靠的連線服務,採用三次握手建立一個連線。
第一次握手:建立連線時,客戶端傳送syn包(syn=j)到伺服器,並進入SYN_SEND狀態,等待伺服器確認;
第二次握手:伺服器收到syn包,必須確認客戶的SYN(ack=j+1),同時自己也傳送一個SYN包(syn=k),即SYN+ACK包,此時伺服器進入SYN_RECV狀態; 第三次握手:客戶端收到伺服器的SYN+ACK包,向伺服器傳送確認包ACK(ack=k+1),此包傳送完畢,客戶端和伺服器進入ESTABLISHED狀態,完成三次握手。 完成三次握手,客戶端與伺服器開始傳送資料.
如果大家有什麼疑問的可以提出問題我來一一為大家解答。