Java---網(wǎng)絡(luò)編程(3)-TCP-互傳文件和圖片

      網(wǎng)友投稿 673 2022-05-29

      ☆ TCP

      建立連接,形成傳輸數(shù)據(jù)的通道。

      在連接中進行大數(shù)據(jù)量傳輸

      通過三次握手完成連接,是可靠協(xié)議

      必須建立連接,效率會稍低

      Socket 和

      ServerSocket類

      TCP傳輸

      TCP Socket:IP地址和端口,套接字

      Socket和ServerSocket

      建立客戶端和服務器端

      建立連接后,通過Socket中的IO流進行數(shù)據(jù)的傳輸

      關(guān)閉socket

      同樣,客戶端與服務器端是兩個獨立的應用程序。

      TCP傳輸編程

      ☆基本思路(客戶端)

      客戶端需要明確服務器的ip地址以及端口,這樣才可以去試著建立連接,如果連接失敗,會出現(xiàn)異常。

      連接成功,說明客戶端與服務端建立了通道,那么通過IO流就可以進行數(shù)據(jù)的傳輸,而Socket對象已經(jīng)提供了輸入流和輸出流對象,通過getInputStream(), getOutputStream()獲取即可。

      與服務端通訊結(jié)束后,關(guān)閉Socket。

      ☆基本思路(服務器端)

      服務端需要明確它要處理的數(shù)據(jù)是從哪個端口進入的。

      當有客戶端訪問時,要明確是哪個客戶端,可通過accept()獲取已連接的客戶端對象,并通過該對象與客戶端通過IO流進行數(shù)據(jù)傳輸。

      當該客戶端訪問結(jié)束,關(guān)閉該客戶端。

      基于TCP的Socket通信流程

      TCP傳輸編程代碼:

      ☆客戶端

      通過Socket建立對象并指定要連接的服務端主機以及端口。

      Socket s = new Socket(“192.168.1.1”,9999); OutputStream out = s.getOutputStream(); out.write(“hello”.getBytes()); s.close();

      1

      2

      3

      4

      ☆服務器端

      建立服務端需要監(jiān)聽一個端口

      ServerSocket ss = new ServerSocket(9999); Socket s = ss.accept (); InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int num = in.read(buf); String str = new String(buf,0,num); System.out.println(s.getInetAddress().toString()+”:”+str); s.close(); ss.close();

      1

      2

      3

      4

      5

      6

      7

      8

      9

      最簡單的TCP演示實例:

      客戶端代碼:

      package cn.hncu.tcp; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; /** * 客戶端 * @author 陳浩翔 * * 2016-5-10 */ public class MyClientSocket { public static void main(String[] args) { try { //因為是在自己本機上演示,IP就直接填寫本機10.30.7.95的了。 //這個端口和IP都是服務器端的(自己可以改的) Socket s = new Socket("10.30.7.95", 9999); //和服務器進行三次握手,若失敗則出異常,否則返回和對方通訊的socket OutputStream os = s.getOutputStream(); //發(fā)送數(shù)據(jù) os.write("你好,服務器!".getBytes()); //接收服務器端的反饋 InputStream in = s.getInputStream(); DataInputStream din = new DataInputStream(in); System.out.println(din.readUTF()); s.close(); din.close(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      服務器端代碼:

      package cn.hncu.tcp; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; /** * 服務器端 * @author 陳浩翔 * * 2016-5-10 */ public class MyServerSocket { public static void main(String[] args) { try { ServerSocket server = new ServerSocket(9999); while(true){ System.out.println("準備接收一個數(shù)據(jù)..."); Socket s = server.accept();//阻塞式方法 System.out.println("接收了一個數(shù)據(jù)..."); //讀--從客戶端讀數(shù)據(jù) InputStream in = s.getInputStream(); byte buf[] = new byte[1024]; in.read(buf); System.out.println("read info: "+new String(buf)); //寫--應答客戶端--向他寫數(shù)據(jù) OutputStream out = s.getOutputStream(); DataOutputStream dout = new DataOutputStream(out); dout.writeUTF("你好,"+s.getInetAddress().getHostAddress()+" ,你的信息已收到。"); dout.close(); s.close(); } } catch (IOException e) { e.printStackTrace(); } } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      客戶端運行結(jié)果:

      你好,10.30.7.95 ,你的信息已收到。

      1

      2

      服務器端運行結(jié)果:

      ☆思考

      對于Web服務器而言,當有多個客戶端同時訪問服務器時,服務端又如何提供服務呢?

      1

      ☆TCP傳輸最容易出現(xiàn)的問題

      客戶端連接上服務端,兩端都在等待,沒有任何數(shù)據(jù)傳輸。

      通過例程分析:

      因為read方法或者readLine方法是阻塞式。

      解決辦法:

      自定義結(jié)束標記(必須定義傳輸文件中沒有這個這個字符串的,不然會出現(xiàn)接收數(shù)據(jù)不完整)

      使用shutdownInput,shutdownOutput方法。

      編程練習

      ☆上傳文本文件

      讀取一個本地文本文件,將數(shù)據(jù)發(fā)送到服務端,服務器端對數(shù)據(jù)進行存儲。 存儲完畢后,給客戶端一個提示。

      文本文件發(fā)送的客戶端

      package cn.hncu.tcp.upload; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.net.Socket; import java.net.UnknownHostException; /** * 文本文件發(fā)送的客戶端 * @author 陳浩翔 * * 2016-5-10 */ public class UploadTextClient { public static void main(String[] args) { try { Socket s = new Socket("", 10006); //思路:把本地文件的數(shù)據(jù)讀取出來通過 s.getOutputStream()獲得的out對象發(fā)送出去 BufferedReader bf = new BufferedReader(new FileReader("tempfiles\client.txt")); OutputStream out = s.getOutputStream();//這里的輸出流 對應的是服務器端的輸入流 PrintWriter pw = new PrintWriter(out,true);//建議不要用BufferedWriter //!!!!!!!!!!!!!!!!!這個true不要忘了!---自動刷新 //現(xiàn)在大家寫網(wǎng)絡(luò)傳輸文件,一般是用PrintWriter String str=null; while((str=bf.readLine())!=null){ pw.println(str); } //給服務器發(fā)送結(jié)束標記---上傳結(jié)束,要加結(jié)束標記, //否則服務器在數(shù)據(jù)接收完畢時再調(diào)用read()或readLine()時會出異常 //法1:pw.println("over#$@#@$");//不能出現(xiàn)文件中存在的結(jié)束關(guān)鍵字---搞特殊一點 //法2---建議采用該種方式---由socket內(nèi)部來指定結(jié)束標記 s.shutdownOutput(); bf.close(); //接收服務器端反饋 InputStream in = s.getInputStream(); DataInputStream din = new DataInputStream(in); System.out.println("server應答:"+din.readUTF()); s.close(); din.close(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63

      64

      65

      66

      文本文件接收的服務器端

      package cn.hncu.tcp.upload; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; /** * 文本文件接收的服務器端 * @author 陳浩翔 * * 2016-5-10 */ public class UploadTextServer { public static void main(String[] args) { try { ServerSocket server = new ServerSocket(10006); Socket s = server.accept(); System.out.println(s.getInetAddress().getHostAddress()+"...發(fā)送消息來"); //讀取客戶端上傳過來的文本文件 //源 ---socket(字節(jié)流)---額外:需要轉(zhuǎn)換成字符流 ,緩存流 InputStream in = s.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(in)); //目的 ---硬盤字符流 FileWriter---額外:打印流 PrintWriter pw = new PrintWriter(new FileWriter("tempfiles\server.txt"),true); String line = null; while((line=br.readLine())!=null){ // if("over#$@#@$".equals(line)){//自己定義的結(jié)束標志 // break; // } pw.println(line); } pw.close(); //上傳成功,給客戶端一個提示信息 OutputStream out = s.getOutputStream(); DataOutputStream dout = new DataOutputStream(out); dout.writeUTF("文件上傳成功!"); s.close(); server.close(); dout.close(); } catch (IOException e) { e.printStackTrace(); } } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63

      64

      65

      測試通過!

      ☆上傳圖片文件

      客戶端需求:把一個圖片文件發(fā)送到服務端并讀取回饋信息。要求判斷文件是否存在及格式是否為jpg或gif并要求文件小于2M。

      服務端需求:接收客戶端發(fā)送過來的圖片數(shù)據(jù)。進行存儲后,回饋一個 上傳成功字樣。支持多用戶的并發(fā)訪問。

      圖片文件的發(fā)送-客戶端

      package cn.hncu.tcp.upload; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; import java.util.Scanner; import javax.swing.JOptionPane; /** * 圖片文件的發(fā)送-客戶端 * @author 陳浩翔 * * 2016-5-10 */ public class UploadPicClient { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("請輸入圖片路徑:"); String str = sc.next(); File file = new File(str); if(!(file.exists()&& file.isFile())){ JOptionPane.showMessageDialog(null, "文件不存在!"); return ; } if(!(file.getName().endsWith(".jpg")||file.getName().endsWith(".gif"))){ JOptionPane.showMessageDialog(null, "文件格式不對,文件擴展名必須是jpg或gif!"); return ; } if( file.length()>=1024*1024*2){ JOptionPane.showMessageDialog(null, "文件過大,不應超過2M,請重新上傳!"); return; } //上傳 try { Socket s = new Socket("10.30.7.95", 10007); BufferedInputStream bin = new BufferedInputStream(new FileInputStream(str)); OutputStream out = s.getOutputStream(); byte buf[] = new byte[1024]; int len=0; while((len=bin.read(buf))!=-1){ out.write(buf, 0, len); } s.shutdownOutput();//告訴服務器,文件上傳完畢 //讀取服務器的回饋信息 InputStream in = s.getInputStream(); byte buf2[] = new byte[1024]; int len2 = in.read(buf2); System.out.println(new String(buf2, 0, len2)); //關(guān)流 out.close(); bin.close(); s.close(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63

      64

      65

      66

      67

      68

      69

      70

      71

      72

      73

      74

      75

      76

      77

      78

      79

      圖片文件接收-服務器端

      package cn.hncu.tcp.upload; import java.io.BufferedInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; /** * 圖片文件接收-服務器端 * @author 陳浩翔 * * 2016-5-10 */ public class UploadPicServer { public static void main(String[] args) { try { ServerSocket server = new ServerSocket(10007); while(true){ Socket s = server.accept();//阻塞方法 //只負責和客戶端進行握手 new Thread(new UploadThread(s) ).start(); } } catch (IOException e) { e.printStackTrace(); } } } class UploadThread implements Runnable{ private Socket s; public UploadThread(Socket s) { this.s = s; } @Override public void run() { String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"...發(fā)來圖片"); try { BufferedInputStream bin = new BufferedInputStream(s.getInputStream()); File dir = new File("g:\mypic"); if(!dir.exists()){ dir.mkdir();//文件夾不存在,創(chuàng)建mypic文件夾 } int count=1; //我覺得這里的后綴名,需要通過發(fā)送方也發(fā)過來的 File file = new File(dir, ip+".jpg"); while(file.exists()){ file = new File(dir,ip+"("+(count++) +")"+".jpg"); //帶號的文件名 } FileOutputStream fout = new FileOutputStream(file); //從socket流中讀取數(shù)據(jù),存儲到本地文件。相當于對拷 byte buf[] = new byte[1024]; int len=0; while( (len=bin.read(buf))!=-1){ fout.write(buf, 0, len); } //圖片接收完畢 //向客戶端發(fā)送回饋信息 OutputStream out = s.getOutputStream(); out.write( "上傳成功".getBytes() ); fout.close(); s.close(); } catch (IOException e) { e.printStackTrace(); } } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63

      64

      65

      66

      67

      68

      69

      70

      71

      72

      73

      74

      Java---網(wǎng)絡(luò)編程(3)-TCP-互傳文件和圖片

      75

      76

      77

      78

      79

      80

      81

      82

      83

      84

      85

      86

      87

      88

      有一個小bug。是服務端接收的,因為我把后綴名統(tǒng)一為jpg了,gif的圖片可以上傳,只是變成靜圖了(jpg)。可以通過改后綴名,再把這圖片改回去動圖。還有一種方法,在上傳的時候,把后綴名也上傳,再通過服務器解析就可以解決這個問題。

      因為時間問題,我就不寫了,這個很簡單的。

      只是多發(fā)送了一個后綴名過去而已。

      我還是把那個后綴名的解決辦法寫了下:

      在客戶端:修改的代碼如下:

      //上傳 try { Socket s = new Socket("10.30.7.95", 10007); BufferedInputStream bin = new BufferedInputStream(new FileInputStream(str)); //上傳文件后綴###########增加的 OutputStream out = s.getOutputStream(); String fileName = file.getName(); out.write(fileName.substring(fileName.length()-4, fileName.length()).getBytes()); byte buf[] = new byte[1024]; int len=0; while((len=bin.read(buf))!=-1){ out.write(buf, 0, len); } s.shutdownOutput();//告訴服務器,文件上傳完畢 //讀取服務器的回饋信息 InputStream in = s.getInputStream(); byte buf2[] = new byte[1024]; int len2 = in.read(buf2); System.out.println(new String(buf2, 0, len2)); //關(guān)流 out.close(); bin.close(); s.close(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      服務器端:

      @Override public void run() { String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"...發(fā)來圖片"); try { BufferedInputStream bin = new BufferedInputStream(s.getInputStream()); File dir = new File("g:\\mypic"); if(!dir.exists()){ dir.mkdir();//文件夾不存在,創(chuàng)建mypic文件夾 } //讀取上傳過來的圖片后綴是什么!######### char cbuf[] = new char[4]; InputStreamReader insr = new InputStreamReader(bin); insr.read(cbuf); String str = new String(cbuf); int count=1; //我覺得這里的后綴名,需要通過發(fā)送方也發(fā)過來的 File file = new File(dir, ip+str); while(file.exists()){ file = new File(dir,ip+"("+(count++) +")"+str); //帶號的文件名 } FileOutputStream fout = new FileOutputStream(file); //從socket流中讀取數(shù)據(jù),存儲到本地文件。相當于對拷 byte buf[] = new byte[1024]; int len=0; //#########必須有這一句 bin.read(buf, 0, 8); while( (len=bin.read(buf))!=-1){ fout.write(buf, 0, len); } //圖片接收完畢 //向客戶端發(fā)送回饋信息 OutputStream out = s.getOutputStream(); out.write( "上傳成功".getBytes() ); fout.close(); s.close(); } catch (IOException e) { e.printStackTrace(); } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      好了,基本上就是這樣的,如果想要更好,做個圖形界面就好看了。自己動下手吧~~

      Java TCP/IP 網(wǎng)絡(luò)

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔相應法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:全網(wǎng)最全Python項目體系練習500例(附源代碼),練完可就業(yè)
      下一篇:一文入門ETCD
      相關(guān)文章
      亚洲乱码在线观看| 亚洲国产成人九九综合| 亚洲国产欧美国产综合一区| 亚洲人成网站看在线播放| 久久久亚洲裙底偷窥综合| 亚洲男人第一av网站| 久久亚洲成a人片| 亚洲av无码一区二区三区乱子伦| 亚洲中文字幕无码爆乳av中文 | 久久精品国产亚洲AV无码偷窥| 国产亚洲A∨片在线观看| 亚洲精品美女久久777777| 亚洲色成人WWW永久网站| 亚洲精品~无码抽插| 亚洲AV永久无码精品一百度影院| 久久精品亚洲日本佐佐木明希| 亚洲AV无码久久精品色欲| 亚洲短视频男人的影院| 久久亚洲中文字幕精品有坂深雪 | 欧洲亚洲综合一区二区三区| 精品韩国亚洲av无码不卡区| 国产成人精品亚洲一区| 亚洲女同成人AⅤ人片在线观看 | 亚洲av无码片在线观看| 一区二区亚洲精品精华液| 亚洲国产一区二区三区在线观看| 亚洲AV无码一区二区三区电影 | 亚洲高清最新av网站| 亚洲午夜久久久久久噜噜噜| 亚洲av午夜福利精品一区人妖| 亚洲精选在线观看| 亚洲乱码一二三四区国产| 亚洲精品无码专区在线| 亚洲成a人一区二区三区| 国产AⅤ无码专区亚洲AV| 亚洲AV无码精品色午夜在线观看| 亚洲一区综合在线播放| 亚洲视频在线观看2018| 久久综合亚洲色hezyo| JLZZJLZZ亚洲乱熟无码| 亚洲国产精品一区二区成人片国内 |