Java---網路程式設計(3)-TCP-互傳檔案和圖片
☆ TCP
建立連線,形成傳輸資料的通道。
在連線中進行大資料量傳輸
通過三次握手完成連線,是可靠協議
必須建立連線,效率會稍低
Socket 和
ServerSocket類
TCP傳輸
TCP Socket:IP地址和埠,套接字
Socket和ServerSocket
建立客戶端和伺服器端
建立連線後,通過Socket中的IO流進行資料的傳輸
關閉socket
同樣,客戶端與伺服器端是兩個獨立的應用程式。
TCP傳輸程式設計
☆基本思路(客戶端)
客戶端需要明確伺服器的ip地址以及埠,這樣才可以去試著建立連線,如果連線失敗,會出現異常。
連線成功,說明客戶端與服務端建立了通道,那麼通過IO流就可以進行資料的傳輸,而Socket物件已經提供了輸入流和輸出流物件,通過getInputStream(), getOutputStream()獲取即可。
與服務端通訊結束後,關閉Socket。
☆基本思路(伺服器端)
服務端需要明確它要處理的資料是從哪個埠進入的。
當有客戶端訪問時,要明確是哪個客戶端,可通過accept()獲取已連線的客戶端物件,並通過該物件與客戶端通過IO流進行資料傳輸。
當該客戶端訪問結束,關閉該客戶端。
基於TCP的Socket通訊流程
TCP傳輸程式設計程式碼:
☆客戶端
通過Socket建立物件並指定要連線的服務端主機以及埠。
Socket s = new Socket(“192.168.1.1”,9999);
OutputStream out = s.getOutputStream();
out.write(“hello”.getBytes ());
s.close();
☆伺服器端
建立服務端需要監聽一個埠
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 ();
最簡單的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();
//傳送資料
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();
}
}
}
伺服器端程式碼:
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("準備接收一個數據...");
Socket s = server.accept();//阻塞式方法
System.out.println("接收了一個數據...");
//讀--從客戶端讀資料
InputStream in = s.getInputStream();
byte buf[] = new byte[1024];
in.read(buf);
System.out.println("read info: "+new String(buf));
//寫--應答客戶端--向他寫資料
OutputStream out = s.getOutputStream();
DataOutputStream dout = new DataOutputStream(out);
dout.writeUTF("你好,"+s.getInetAddress().getHostAddress()+" ,你的資訊已收到。");
dout.close();
s.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
客戶端執行結果:
你好,10.30.7.95 ,你的資訊已收到。
伺服器端執行結果:
☆思考
對於Web伺服器而言,當有多個客戶端同時訪問伺服器時,服務端又如何提供服務呢?
☆TCP傳輸最容易出現的問題
客戶端連線上服務端,兩端都在等待,沒有任何資料傳輸。
通過例程分析:
因為read方法或者readLine方法是阻塞式。
解決辦法:
自定義結束標記(必須定義傳輸檔案中沒有這個這個字串的,不然會出現接收資料不完整)
使用shutdownInput,shutdownOutput方法。
程式設計練習
☆上傳文字檔案
讀取一個本地文字檔案,將資料傳送到服務端,伺服器端對資料進行儲存。 儲存完畢後,給客戶端一個提示。
文字檔案傳送的客戶端
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;
/**
* 文字檔案傳送的客戶端
* @author 陳浩翔
*
* 2016-5-10
*/
public class UploadTextClient {
public static void main(String[] args) {
try {
Socket s = new Socket("", 10006);
//思路:把本地檔案的資料讀取出來通過 s.getOutputStream()獲得的out物件傳送出去
BufferedReader bf = new BufferedReader(new FileReader("tempfiles\\client.txt"));
OutputStream out = s.getOutputStream();//這裡的輸出流 對應的是伺服器端的輸入流
PrintWriter pw = new PrintWriter(out,true);//建議不要用BufferedWriter
//!!!!!!!!!!!!!!!!!這個true不要忘了!---自動重新整理
//現在大家寫網路傳輸檔案,一般是用PrintWriter
String str=null;
while((str=bf.readLine())!=null){
pw.println(str);
}
//給伺服器傳送結束標記---上傳結束,要加結束標記,
//否則伺服器在資料接收完畢時再呼叫read()或readLine()時會出異常
//法1:pw.println("over#[email protected]#@$");//不能出現檔案中存在的結束關鍵字---搞特殊一點
//法2---建議採用該種方式---由socket內部來指定結束標記
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();
}
}
}
文字檔案接收的伺服器端
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()+"...傳送訊息來");
//讀取客戶端上傳過來的文字檔案
//源 ---socket(位元組流)---額外:需要轉換成字元流 ,快取流
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#[email protected]#@$".equals(line)){//自己定義的結束標誌
// 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();
}
}
}
測試通過!
☆上傳圖片檔案
客戶端需求:把一個圖片檔案傳送到服務端並讀取回饋資訊。要求判斷檔案是否存在及格式是否為jpg或gif並要求檔案小於2M。
服務端需求:接收客戶端傳送過來的圖片資料。進行儲存後,回饋一個 上傳成功字樣。支援多使用者的併發訪問。
圖片檔案的傳送-客戶端
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;
/**
* 圖片檔案的傳送-客戶端
* @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));
//關流
out.close();
bin.close();
s.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
圖片檔案接收-伺服器端
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+"...發來圖片");
try {
BufferedInputStream bin = new BufferedInputStream(s.getInputStream());
File dir = new File("g:\\mypic");
if(!dir.exists()){
dir.mkdir();//資料夾不存在,建立mypic資料夾
}
int count=1;
//我覺得這裡的字尾名,需要通過傳送方也發過來的
File file = new File(dir, ip+".jpg");
while(file.exists()){
file = new File(dir,ip+"("+(count++) +")"+".jpg"); //帶號的檔名
}
FileOutputStream fout = new FileOutputStream(file);
//從socket流中讀取資料,儲存到本地檔案。相當於對拷
byte buf[] = new byte[1024];
int len=0;
while( (len=bin.read(buf))!=-1){
fout.write(buf, 0, len);
}
//圖片接收完畢
//向客戶端傳送回饋資訊
OutputStream out = s.getOutputStream();
out.write( "上傳成功".getBytes() );
fout.close();
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
有一個小bug。是服務端接收的,因為我把字尾名統一為jpg了,gif的圖片可以上傳,只是變成靜圖了(jpg)。可以通過改字尾名,再把這圖片改回去動圖。還有一種方法,在上傳的時候,把字尾名也上傳,再通過伺服器解析就可以解決這個問題。
因為時間問題,我就不寫了,這個很簡單的。
只是多傳送了一個字尾名過去而已。
我還是把那個字尾名的解決辦法寫了下:
在客戶端:修改的程式碼如下:
//上傳
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));
//關流
out.close();
bin.close();
s.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
伺服器端:
@Override
public void run() {
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip+"...發來圖片");
try {
BufferedInputStream bin = new BufferedInputStream(s.getInputStream());
File dir = new File("g:\\mypic");
if(!dir.exists()){
dir.mkdir();//資料夾不存在,建立mypic資料夾
}
//讀取上傳過來的圖片字尾是什麼!#########
char cbuf[] = new char[4];
InputStreamReader insr = new InputStreamReader(bin);
insr.read(cbuf);
String str = new String(cbuf);
int count=1;
//我覺得這裡的字尾名,需要通過傳送方也發過來的
File file = new File(dir, ip+str);
while(file.exists()){
file = new File(dir,ip+"("+(count++) +")"+str); //帶號的檔名
}
FileOutputStream fout = new FileOutputStream(file);
//從socket流中讀取資料,儲存到本地檔案。相當於對拷
byte buf[] = new byte[1024];
int len=0;
//#########必須有這一句
bin.read(buf, 0, 8);
while( (len=bin.read(buf))!=-1){
fout.write(buf, 0, len);
}
//圖片接收完畢
//向客戶端傳送回饋資訊
OutputStream out = s.getOutputStream();
out.write( "上傳成功".getBytes() );
fout.close();
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
好了,基本上就是這樣的,如果想要更好,做個圖形介面就好看了。自己動下手吧~~
相關推薦
Java---網路程式設計(3)-TCP-互傳檔案和圖片
☆ TCP 建立連線,形成傳輸資料的通道。 在連線中進行大資料量傳輸 通過三次握手完成連線,是可靠協議 必須建立連線,效率會稍低 Socket 和 ServerSocket類 TCP傳輸 TCP Socket:IP地址和埠,套接字 Sock
網路程式設計——3.TCP/UDP實現跨平臺檔案傳輸
一、實驗目的 在上次檔案傳輸的程式基礎上,利用循環面向連線、迴圈無連線方式完成linux和windows平臺的檔案傳輸,並完成客戶端、伺服器端程式碼的封裝。 二、實驗分析 1.使用TCP實現 在上次實驗基礎上,使用tcp_server.c的程式碼
網路程式設計3-TCP/UDP
4.2 Socket程式設計 基礎知識: 1.在windows/linux下都有一個ping命令,用來檢查對方主機是否連通。若請求超時:對方關機或離線;己方沒有連網;對方線上,但遮蔽了ping服務。 2.檢視自己的IP,windows:ipconfig;linux:ifconfig。
Java網路程式設計7.TCP網路程式設計之客戶端鍵盤錄入伺服器控制檯輸出
TCP網路程式設計之客戶端鍵盤錄入伺服器控制檯輸出 1、鍵盤錄入資料 BufferedReader br = new BufferedReader(new InputStreamReader(S
java網路程式設計基於TCP的多客戶端連線伺服器
package com.test.net; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.S
JAVA 網路程式設計UDP TCP
UDP協議 UDP是無連線通訊協議,即在資料傳輸時,資料的傳送端和接收端不建立邏輯連線。簡單來說,當一臺計算機向另外一臺計算機發送資料時,傳送端不會確認接收端是否存在,就會發出資料,同樣接收端在收到資料時,也不會向傳送端反饋是否收到資料UDP的交換過程如下圖所示。 優
java 網路程式設計(Socket) TCP/UDP 總結案例
網路程式設計:關注的是底層的資料傳輸 網頁程式設計:資料的展示 1、基本概念 一、網路:將不同的計算機連線在一起區域網 都會網路 網際網路 二、地址:Ip地址確定網路上的絕對的地址位置 房子的地址 三、埠號(相當於房門):區分計算機上的軟體 相當於房門兩個位元組
Java網路程式設計(一) TCP/IP,http,socket,長連線,短連線
TCP/IP TCP/IP是個協議組,可分為三個層次:網路層、傳輸層和應用層。 在網路層有IP協議、ICMP協議、ARP協議、RARP協議和BOOTP協議。 在傳輸層中有TCP協議與UDP協議。 在應用層有:TCP包括FTP、HTTP、TELNET、SMTP等協議
Java 網路程式設計 之 TCP協議
TCP協議 (伺服器端程先啟動,等待客戶端連線) TCP協議是面向連線的通訊協議,即在傳輸資料前先在傳送端和接收端建立邏輯連線,然後再傳輸資料 保證傳輸資料的全性安,檔案資料不易丟失 在JDK中提供了兩個類用於實現TCP程式,一個是ServerSocket類,用於表示伺
JAVA網路程式設計 ——基於TCP的Socket程式設計(1)——實現伺服器端與客戶端的實時對話
第一篇文章,我先介紹以及記錄一下我所學的知識點。(總結了一下視訊老師講的東西)一,HTTP與Socket1.HTTP:超文字傳輸協議特點:客戶端傳送的請求需要伺服器端每次來響應,在請求結束之後主動釋放連線,從建立連線到關閉連線稱為“一次連線”,所以HTTP是“短連線”。2.S
JAVA網路程式設計(TCP篇入門)
此次部落格主要以程式碼為主,其中包含了豐富的註釋 簡單的tcp 簡單介紹tcp是如何傳送資料,以及接受資料 程式碼一:客戶端 package com.net.tcp; import java.io.IOException; import java.io.Out
Linux網路程式設計之Tcp/Udp socket檔案傳輸示例
本文所述示例程式是基於Linux平臺的socket網路程式設計,實現檔案傳輸功能。該示例是基於TCP流協議實現的socket網路檔案傳輸程式。採用C語言編寫。最終能夠實現傳輸任何格式檔案的檔案傳輸程式。 具體實現程式碼如下: /***********************
【Java網路程式設計】:Netty實現OIO和NIO
承接上文:https://blog.csdn.net/hxcaifly/article/details/85274664 前言 單純地使用Java JDK來實現網路NIO是一件開發成本非常高的事情。然而,Netty 為它所有的傳輸實現提供了一個通用API,這使得這種
ueditor1.4.3 單獨上傳檔案以及圖片的使用和配置
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%String contextPath = request.getContextP
JAVA 網路程式設計(簡單的傳送端和接受端)
/* UDP 1,將資料及源和目的封裝成資料包中,不需要建立連線 2,每個資料報的大小在限制在64k 3,因為無連線,是不可靠協議的 4,不需要建立連線,速度快 TCP 1,建立連線,
java網路程式設計(3)TCP
使用TCP進行網路資料傳輸的時候,TCP會在需要傳輸資料的兩端建立兩個Socket(插座),並且在兩個Socket之間建立一條虛擬鏈路,然後這兩臺主機就可以進行通訊了。 下面是一個很簡單的例子。 Server類建立一個ServerSocket物件,用於監聽客戶端Socke
Java網路程式設計例子2_TCP檔案上傳
注意:網路程式設計的正常步驟先跑服務端,再跑客戶端; 第一步先用eclipse執行server端; 第二步用命令列執行客戶端; 檢視結果: 把檔案copy出去改下字尾,發現檔案可以開啟 package cn.njit.internet.fileUploa
javaSE (四十)網路程式設計(TCP傳輸、伺服器多執行緒、網路程式設計練習:反轉字串、上傳檔案)
1、TCP傳輸: 1.客戶端 建立Socket連結服務端(指定ip地址,埠號),通過ip地址找到對應的伺服器 呼叫Socket的getInputStream和getOutputStream方法獲取和伺服器端相連的IO流 2.伺服器端 建立Se
java網路程式設計--socket上傳檔案
直接程式碼不多說! 服務端: package scoket.file.server; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; impo
java 網路程式設計——TCP 的三次握手和四次揮手
文章目錄 TCP報頭 三次握手 未連線佇列 四次揮手 狀態詳解 在TCP/IP協議中,TCP協議提供可靠的連線服務,採用三次握手建立一個連線. TCP報頭 埠號:用來標識