Java網絡編程之TCP網絡通信

1? ? ? 網絡編程----TCPNo24

public class Server {

public static void main(String[] args){

try {

ServerSocket ss =new ServerSocket(8888);//在8888端口上建立ServerSocket

Socket s =ss.accept();//監聽客戶端的連接請求,一旦連接請求到達,建立連接,會返回一個服務器端的Socket

InputStream is =s.getInputStream();//獲取這個Socket的輸入流,用于讀取客戶端傳來的信息

int b = is.read();//讀一個字節

System.out.println(b);//打印

s.close();//關閉和客戶端的連接

ss.close();//關閉ServerSocket,之后不再去監聽端的連接請求

} catch (IOException e) {

// TODOAuto-generated catch block

e.printStackTrace();

}

}

}

public class Client {

public static void main(String[] args){

try {

Socket s = newSocket("127.0.0.1",8881);//向本機8888端口發送連接請求

OutputStream os =s.getOutputStream();//獲取客戶端Socket的輸出流

os.write(100);//寫一個字節100

s.close();//關閉套接字

} catch (IOException e) {

// TODOAuto-generated catch block

e.printStackTrace();

}

}

}

網絡

Protocol協議就是一種格式、約定,網絡兩端的主機可以根據這個約定來進行信息的交互和傳輸

網絡四層協議體系架構TCP/IP

1、應用層? http、ftp

2、傳輸層? TCP、UDP

3、網絡互聯層? IP

4、主機到網絡層

1.1????基本網絡知識

1.1.1? Ip地址

InetAddress類的使用:

getByName(Stringhost):根據主機名獲取IP對象

getHostAddress():獲取主機地址

getHostName():獲取主機名

getAllByName(Stringhost):獲取主機名獲取所有的IP對象

getLocalHost():獲取本地主機對應的IP地址(127.0.0.1)

示例代碼

//在Java中,使用InetAddress類描敘網絡地址

InetAddress inetAddr = null;

//創建InetAddress對象

//在互聯網上訪問服務器有兩種形式:1、ip地址?? 2、主機名(例如:http://www.baidu.com)

//?????????????? inetAddr =InetAddress.getByName("www.baidu.com");

//?????????????? inetAddr =InetAddress.getByName("192.168.35.1");

//?????????????? inetAddr =InetAddress.getByName("192.168.81.144");

//?????????????? inetAddr = InetAddress.getByName("localhost");

//獲取本機ip地址

inetAddr =InetAddress.getLocalHost();

//ip地址

String address =inetAddr.getHostAddress();

//主機名

String host =inetAddr.getHostName();

System.out.println(address+":"+host);

InetAddress[] inetAddresses=InetAddress.getAllByName("www.baidu.com");

for (InetAddress inet :inetAddresses) {

System.out.println(inet.getHostAddress());

}

1.1.2? 網絡編程三要素

IP地址:網絡中每臺主機都必須有一個唯一的IP地址(網絡中設備的標識)

端口:用于標識進程的邏輯地址,每個進程都有各自不同的標識, 有效端口0~65535,其中0-1024系統使用或保留端口

傳輸協議UDP---《將數據、源地址和目的地址封裝在數據報包中;每個數據報的大小被限制在64K以內;不需要建立連接;是不可靠協議,速度快》

TCP----《建立連接,形成傳輸數據的通道;在連接中進行大數據傳輸;通過三次握手完成連接;必須建立連接;是可靠協議,效率較低》

通過三次握手完成連接:

【1. 客戶端向服務器發送包含初始序列值的數據段,開啟通信會話

2.????? 服務器發送包含確認值的數據段,其值等于收到的序列值加1,并加上其自身的同步序列值

3.????? 發送帶確認值的客戶端響應,其值等于接受的序列值加1.這便完成了整個建立連接的過程】

1.1.3? Socket(套接字)

1、Socket是為了網絡服務而提供的一種機制;

2、套接字是兩臺機器間通信的端點;

3、網絡通信其實就是Socket間的通信(所以網絡編程又稱為Socket編程);

4、Socket之間通過IO流來進行數據的傳輸(TCP);

5、Socket = IP地址 + 端口

TCP? Transmit Control Protocol傳輸控制協議

可以將IP報文進行包裝、組織,有序可靠地傳輸到網絡另一端

是基于連接的,兩個主機在進行通信前必須先建立連接(三次握手)

(UDPUser Datagram protocol用戶數據報協議,不需要連接,信息傳輸會發生丟失)

協議都是跨語言、跨平臺的

1.2????Java實現Tcp通信

如何用Java來進行TCP通信:

ServerSocket服務器套接字,用來監聽客戶端發送來的連接請求,一旦有客戶端請求連接,就可以生成一個連接,并獲取服務端這頭的Socket

構造方法:ServerSocket(int port)在端口port上建立服務端套接字

Socketaccept()監聽客戶端過來的連接請求,是一個阻塞方法,連接請求過來了,它就會返回建立的連接的服務端這頭的套接字,這個套接字可以用來向客戶端寫或者從客戶端讀信息

Socket套接字,就是網絡上兩臺主機之間建立的連接的兩個端點,可以通過它寫信息,也可以讀信息(套接字可以用于兩臺連接的主機之間進行通信,讀寫信息。)

1.2.1? 服務端

一:服務端

getOutputStream()獲取套接字輸出流

write系列方法,使用和文件IO中差不多

getInputStream()獲取套接字輸入流

read系列方法

1.3????客戶端

二:客戶端

構造方法:Socket(String address,int port)參數為服務端的地址以及端口號,這樣構建時就能發送一個連接請求到服務端,接下來這個創建出來的Socket對象就能用來和服務端通信

getOutputStream()獲取套接字輸出流

write系列方法,使用和文件IO中差不多

getInputStream()獲取套接字輸入流

read系列方法

getPort()獲取端口號

getInetAddress()獲取英特網地址對象(可以調用這個對象的getHostAddress()獲取地址字符串)

另有一個4參構造方法Socket(String address,int port,InetAddress addr,int p)可以用第四個參數指定客戶端的端口(2參構造方法的客戶端端口隨機分配)

1.4????實現及理論

Socket類:此類實現客戶端套接字

ServerSocket:《此類實現服務器套接字。服務器套接字等待請求通過網絡傳入。它基于該請求執行某些操作,然后可能向請求者返回結果。

PS:在創建Socket對象時,底層會自動創建一個客戶端與服務端之間的通道,這個通道就是Socket流(網絡IO流),Socket流既包含輸入流,又包含輸出流。》

使用步驟:

客戶端:【《

1、 創建套接字對象(需要綁定指定的服務器ip地址和端口)

2、 通過IO流和服務端傳輸數據

3、 關閉Socket,釋放資源》

服務端:【《

1、 創建服務端套接字對象(需要綁定端口,以便客戶端連接)

2、 等待接收來自客戶端的連接請求

3、 通過IO流與客戶端傳輸數據

4、 關閉資源》

代碼:

Client.java客戶端

publicclassClient {

publicstaticvoidmain(String[]args)throwsUnknownHostException, IOException {

//tcp的客戶端

System.out.println("tcp客戶端開啟...");

/*

*創建Socket對象,當執行這行代碼的時候底層會自動和服務端建立連接(三次握手)

*如果連接建立不成功,就會拋出異常

*/

//Socket socket = newSocket("127.0.0.1", 9999);

Socketsocket=newSocket("192.168.81.143", 9999);

//獲取IO流對象,通過IO流對象可以實現與服務端的數據傳輸

// socket.getInputStream();

OutputStreamos=socket.getOutputStream();

os.write("來自tcp客戶端的數據".getBytes());

//釋放資源,斷開與服務端的連接

socket.close();

System.out.println("tcp客戶端關閉...");

}

}

服務端:Server.java

publicclass Server {

public static void main(String[] args)throws IOException {

// tcp的服務端

System.out.println("tcp服務端開啟...");

// 創建服務端的套接字對象,用于響應來自客戶端的連接請求

ServerSocket serverSocket =new ServerSocket(9999);

// 等待接收來自客戶端的連接請求,連接成功后會返回與客戶端對應的Socket對象

Socket socket =serverSocket.accept(); // 阻塞式方法

// 獲取客戶端的ip地址

String ip =socket.getInetAddress().getHostAddress();

System.out.println("與" + ip + "建立連接");

InputStream is =socket.getInputStream();

// socket.getOutputStream();

byte[] buf = new byte[1024];

int length = is.read(buf);

System.out.println(ip +":" + new String(buf, 0, length));

// socket.close();

// 釋放資源,關閉服務端的套接字,會斷開所有的客戶端連接

serverSocket.close();

System.out.println("tcp服務端關閉");

}

}

1.5????不間斷發送消息到服務器

publicclass Client {

public static void main(String[] args)throws UnknownHostException,

IOException {

// tcp的客戶端

System.out.println("tcp客戶端開啟...");

Socket socket = newSocket("192.168.81.143", 9999);

Scanner scanner = newScanner(System.in);

/*BufferedReader br = newBufferedReader(new InputStreamReader(

socket.getInputStream()));*/

BufferedWriter bw = newBufferedWriter(new OutputStreamWriter(

socket.getOutputStream()));

for(;;){

String line =scanner.nextLine();

bw.write(line);

bw.newLine();

bw.flush();

}

//?????????????? socket.close();

//?????????????? System.out.println("tcp客戶端關閉...");

}

}

publicclass Server {

public static void main(String[] args)throws IOException {

// TODO Auto-generated methodstub

// tcp服務端

System.out.println("TCP服務端開啟.....");

ServerSocket serverSocket =new ServerSocket(9999);

Socket socket =serverSocket.accept(); // 阻塞式方法

String ip =socket.getInetAddress().getHostAddress();

System.out.println("與" + ip + "建立連接");

BufferedReader br = newBufferedReader(new InputStreamReader(

socket.getInputStream()));

String line = null;

while((line =br.readLine())!=null){

System.out.println(ip+"發送來:"+line);

}

serverSocket.close();

System.out.println("TCP服務端關閉.....");

}

}

1.6????TCP上傳文件到服務器

publicclass Client {

// TCP的客戶端

public static void main(String[] args)throws UnknownHostException,

IOException {

// TODO Auto-generated methodstub

System.out.println("TCP客戶端開啟.......");

Socket socket = newSocket("192.168.81.143", 9999);

// 將指定的文件上傳到服務器

// 一邊讀取文件數據,一邊向服務器端寫出數據

BufferedInputStream bis = newBufferedInputStream(new FileInputStream(

"g:\\extras下文件.rar"));

BufferedOutputStream bos =new BufferedOutputStream(socket.getOutputStream());

int b=0;

while((b=bis.read())!=-1){

bos.write(b);

}

bos.close();

bis.close();

socket.close();

System.out.println("TCP客戶端關閉.......");

}

}

publicclass Server {

public static void main(String[] args)throws IOException {

// TODO Auto-generated methodstub

System.out.println("tcp服務端開啟....");

ServerSocket serverSocket =new ServerSocket(9999);

Socket socket =serverSocket.accept();

String clientName =socket.getInetAddress().getHostName();

BufferedInputStream bis = newBufferedInputStream(

socket.getInputStream());

BufferedOutputStream bos =new BufferedOutputStream(

newFileOutputStream("g:\\" + clientName + ".rar"));

int b = 0;

while((b =bis.read()) !=-1){

bos.write(b);

}

bos.close();

bis.close();

System.out.println("tcp服務端關閉...");

}

}

1.7????多用戶連接與數據發送

publicclass Client {

public static void main(String[] args)throws UnknownHostException,

IOException {

// TODO Auto-generated methodstub

System.out.println("客戶端開啟./...");

Socket socket = newSocket("192.168.81.144", 6001);

System.out.println("成功與服務器建立連接....");

// 將鍵盤錄入的數據傳輸到服務器

BufferedReader br = newBufferedReader(new InputStreamReader(System.in));

BufferedWriter bw = newBufferedWriter(new OutputStreamWriter(

socket.getOutputStream()));

//讀一行寫一行

String line = null;?? //接收從鍵盤錄入的數據

while((line=br.readLine())!=null){

bw.write(line);

bw.newLine();

bw.flush();

}

bw.close();

br.close();

socket.close();

System.out.println("客戶端關閉.....");

}

}

//客戶端響應線程

publicclass ClientEchoThread extends Thread {

//客戶端對應的Socket對象(每個客戶端都有自己所對應的Socket對象)

private Socket socket;

private String ip;

public ClientEchoThread(Socket socket){

this.socket = socket;

ip =socket.getInetAddress().getHostAddress();

}

//在線程中執行客戶端的響應

@Override

public void run() {

System.out.println("建立與"+ip+"的連接");

BufferedReader br =null;

try {

br =newBufferedReader(new InputStreamReader(socket.getInputStream()));

//讀取來自客戶端的數據

String line = null;

while((line =br.readLine())!= null){

System.out.println(ip+":"+line);

}

} catch (IOException e) {

// TODOAuto-generated catch block

e.printStackTrace();

}finally{

if(br != null){

try {

br.close();

br= null;

} catch(IOException e) {

//TODO Auto-generated catch block

e.printStackTrace();

}

}

if(socket != null){

try {

socket.close();

socket= null;

} catch(IOException e) {

//TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

}

/**

*開啟幾個線程?

*???? 有幾個客戶端就有幾個線程

*什么時候開線程?

*???? 一旦有了新的客戶端,就需要開啟一個新的線程

*線程中應該包含哪些代碼?

*???? 響應客戶端的請求

*/

publicclass Server {

public static void main(String[] args)throws IOException {

// TODO Auto-generated methodstub

System.out.println("服務端開啟....");

ServerSocket serverSocket = new ServerSocket(6001);

//接收來自客戶端的連接請求

//阻塞式方法,一旦有新的客戶端連接,就會返回一個客戶端對應的Socket對象

//作為客戶端,應該不停地去接受客戶端的請求

while(true){

Socket socket =serverSocket.accept();

newClientEchoThread(socket).start();

}

//???? ???serverSocket.close();

//???? ???System.out.println("服務端關閉....");

}

}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容