JAVA網路程式設計(TCP篇入門)
阿新 • • 發佈:2019-01-12
此次部落格主要以程式碼為主,其中包含了豐富的註釋
簡單的tcp
簡單介紹tcp是如何傳送資料,以及接受資料
程式碼一:客戶端
package com.net.tcp;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
/**
* TCP協議傳送資料的步驟
* A:建立傳送資料的socket物件。
* 建立物件的時候要指定目標主機和埠
* B:獲取socket物件的輸出流
* 是位元組流還是字元流?位元組流。
* C:寫資料
* D:釋放資源
*
* @author yuliyang
* @version $Id: ClientDemo.java, v 0.1 2016年11月23日 下午10:57:55 yuliyang Exp $
*/
public class ClientDemo {
public static void main(String[] args) throws IOException {
//A:建立傳送資料的socket物件
//Socket(InetAddress address, int port)
//Socket(String host, int port)
//java.net.ConnectException: Connection refused: connect
//如果你先啟動了客戶端,發現如上錯誤,是因為服務端沒有開啟,TCP協議的程式,必須先開啟伺服器
Socket s = new Socket("192.168.31.222", 10086);
//B:獲取socket物件的輸出流
OutputStream os = s.getOutputStream();
//C:
os.write("hello write".getBytes());
//D:
os.close();
s.close();
}
}
程式碼一:服務端
package com.net.tcp;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* TCP協議接收資料的步驟
* A:建立接收資料的socket物件。
* 建立物件的時候要指定埠
* B:監聽客戶端連線,
* 等待客戶端連線
* C:讀資料,並顯示在控制檯
* D:釋放資源
* 注意事項;伺服器需要先開啟
* @author yuliyang
* @version $Id: ClientDemo.java, v 0.1 2016年11月23日 下午10:57:55 yuliyang Exp $
*/
public class ServerDemo {
public static void main(String[] args) throws IOException {
//A:ServerSocket(int port)
ServerSocket serverSocket = new ServerSocket(10086);
//B:監聽客戶端連線
// Socket accept() 偵聽並接受到此套接字的連線。
Socket s = serverSocket.accept();//此處為阻塞式方法
//C:獲取socket物件的輸入流,並讀取資料
InputStream is = s.getInputStream();
byte[] buf = new byte[1024];
int len = is.read(buf);
//此處為解析收到的資料
String data = new String(buf, 0, len);
System.out.println("data" + data);
//D:釋放資源
is.close();
serverSocket.close();
}
}
如果上面的程式碼你看懂了的話,那就接著繼續玩耍吧。
程式碼二:客戶端,新增獲取了服務端返回的資訊
package com.net.tcp2;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class ClientDemo {
public static void main(String[] args) throws IOException {
//建立客戶端socket
Socket socket = new Socket("192.168.31.222", 12312);
/**
* 使用通道輸出流寫資料
*/
OutputStream outputStream = socket.getOutputStream();
outputStream.write("我是傳送的".getBytes());
/**
* 使用通道輸入流獲取返回的訊息
*/
InputStream inputStream = socket.getInputStream();
byte[] b = new byte[1024];
int len = inputStream.read(b);
String s = new String(b, 0, len);
System.out.println("客戶端獲取到的響應是:" + s);
socket.close();
}
}
程式碼二:服務端
package com.net.tcp2;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(12312);
Socket s = serverSocket.accept();
InputStream inputStream = s.getInputStream();
byte[] buf = new byte[1024];
int len = inputStream.read(buf);
String data = new String(buf, 0, len);
System.out.println("服務端獲取到的資料是:" + data);
/**
* 使用通道返回響應,告訴客戶端結果
*/
OutputStream outputStream = s.getOutputStream();
outputStream.write("我接收到了".getBytes());
//釋放資源
serverSocket.close();
inputStream.close();
outputStream.close();
}
}
程式碼三:客戶端 新增需求:看註釋
、
package com.net.tcp3;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
/**
* 需求:把傳送的資料改進為來自鍵盤錄入,
* 客戶端傳送資料用鍵盤錄入,服務端把資料顯示即可
*
* @author yuliyang
* @version $Id: ClientDemo.java, v 0.1 2016年11月24日 下午9:08:14 yuliyang Exp $
*/
public class ClientDemo {
public static void main(String[] args) throws IOException {
Socket s = new Socket("192.168.31.222", 10010);
//讀取鍵盤錄入的資料
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//封裝:將通道內的輸出位元組流轉化為字元流
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();
}
}
程式碼三:服務端
package com.net.tcp3;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(10010);
Socket s = serverSocket.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println("接收的資料為:" + line);
}
//釋放資源
s.close();
serverSocket.close();
}
}
程式碼四:客戶端
需求:服務端需要將從客戶端獲取的資源寫入到檔案中
package com.net.tcp5;
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 ClientDemo {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("192.168.31.222", 10086);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
socket.close();
}
}
程式碼四:服務端
package com.net.tcp5;
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 ServerDemo {
public static void main(String[] args) throws IOException {
//建立伺服器socket物件
ServerSocket serverSocket = new ServerSocket(10086);
//監聽客戶端連線
Socket socket = serverSocket.accept();//阻塞式
//封裝通道內的輸入流
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//將資料寫入到檔案中
BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\a.txt"));
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
bw.close();
serverSocket.close();
}
}
程式碼五:客戶端
需求:客戶端讀取本地檔案,並傳送給服務端,服務端收到檔案之後,並copy一份
package com.net.tcp6;
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 ClientDemo {
public static void main(String[] args) throws IOException {
//建立客戶端的物件
Socket s = new Socket("192.168.31.222", 10086);
//讀取檔案的資料
BufferedReader br = new BufferedReader(new FileReader("InetAddressDemo.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.net.tcp6;
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 ServerDemo {
public static void main(String[] args) throws IOException {
//建立伺服器物件
ServerSocket serverSocket = new ServerSocket(10086);
//監聽客戶端連線
Socket s = serverSocket.accept();
//把通道內的輸入流封裝一下
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
//把輸入流輸出到檔案
BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.txt"));
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
serverSocket.close();
bw.close();
}
}
程式碼六:客戶端
需求:在檔案接收完成之後,伺服器需要通知客戶端,檔案接收完成
問題:會因為阻塞式,導致接收不到反饋訊息
解決方案:A:自定義結束標籤
B:使用socket自帶的方法
此處只展現socket自帶方案
package com.net.tcp7;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
/**
* 我把檔案發給你了,你沒有告訴我檔案你是否收到檔案
* 需要服務端給我一個反饋
*
* @author yuliyang
* @version $Id: ClientDemo.java, v 0.1 2016年11月24日 下午10:21:16 yuliyang Exp $
*/
public class ClientDemo {
public static void main(String[] args) throws IOException {
//建立客戶端的物件
Socket s = new Socket("192.168.31.222", 10086);
//讀取檔案的資料
BufferedReader br = new BufferedReader(new FileReader("InetAddressDemo.java"));
//把通道的輸出流包裝
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
/**
* 接收從服務端返回的資訊
* 此處發現無法進行到這裡,由於服務端阻塞,
* 因為伺服器無法判斷我們之前的資料是否已經傳輸完畢,
* 此時socket提供了一個方法:
* shutdownOutput
* 禁用輸出流 方法
*/
s.shutdownOutput();
BufferedReader infoByServer = new BufferedReader(new InputStreamReader(s.getInputStream()));
String data = infoByServer.readLine();//阻塞式
System.out.println("client" + data);
s.close();
br.close();
}
}
程式碼六:服務端
package com.net.tcp7;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 收到檔案之後,給客戶端一個反饋
*
* @author yuliyang
* @version $Id: ServerDemo.java, v 0.1 2016年11月24日 下午10:22:00 yuliyang Exp $
*/
public class ServerDemo {
public static void main(String[] args) throws IOException {
//建立伺服器物件
ServerSocket serverSocket = new ServerSocket(10086);
//監聽客戶端連線
Socket s = serverSocket.accept();
//把通道內的輸入流封裝一下
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
//把輸入流輸出到檔案
BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.txt"));
String line = null;
while ((line = br.readLine()) != null) {//阻塞式
bw.write(line);
bw.newLine();
bw.flush();
}
/**
* 新增反饋
* 從通道將反饋返回回去
*/
BufferedWriter feadback = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
feadback.write("資料接收成功了");
feadback.newLine();
feadback.flush();
serverSocket.close();
bw.close();
}
}