久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長(zhǎng)資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      JAVA進(jìn)階學(xué)習(xí)之Socket編程

      本篇文章給大家?guī)?lái)了關(guān)于java的相關(guān)知識(shí),其中主要介紹了關(guān)于socket編程的相關(guān)內(nèi)容,Socket是網(wǎng)絡(luò)驅(qū)動(dòng)層提供給應(yīng)用程序的一個(gè)接口或者說(shuō)一種機(jī)制,下面一起來(lái)看一下,希望對(duì)大家有幫助。

      JAVA進(jìn)階學(xué)習(xí)之Socket編程

      程序員必備接口測(cè)試調(diào)試工具:立即使用
      Apipost = Postman + Swagger + Mock + Jmeter
      Api設(shè)計(jì)、調(diào)試、文檔、自動(dòng)化測(cè)試工具
      后端、前端、測(cè)試,同時(shí)在線(xiàn)協(xié)作,內(nèi)容實(shí)時(shí)同步

      推薦學(xué)習(xí):《java視頻教程》

      一、Socket知識(shí)

      1. Socket概述

      (1)Java最初是作為網(wǎng)絡(luò)編程語(yǔ)言出現(xiàn)的,它對(duì)網(wǎng)絡(luò)的高度支持,使得客戶(hù)端和服務(wù)器端流暢的溝通成為現(xiàn)實(shí)。

      (2)在網(wǎng)絡(luò)編程中,使用最多的就是Socket,每一個(gè)實(shí)用的網(wǎng)絡(luò)程序都少不了它的參與。

      (3)在計(jì)算機(jī)網(wǎng)絡(luò)編程技術(shù)中,兩個(gè)進(jìn)程或者說(shuō)兩臺(tái)計(jì)算機(jī)可以通過(guò)一個(gè)網(wǎng)絡(luò)通信連接實(shí)現(xiàn)數(shù)據(jù)的交換,這種通信鏈路的端點(diǎn)就被稱(chēng)為“套接字”(英文名稱(chēng)也就是Socket)。

      (4)Socket是網(wǎng)絡(luò)驅(qū)動(dòng)層提供給應(yīng)用程序的一個(gè)接口或者說(shuō)一種機(jī)制。

      (5)使用物流送快遞的例子來(lái)說(shuō)明Socket:

      –>發(fā)件人將有收貨人地址信息的貨物送到快遞站,發(fā)件人不用關(guān)心物流是如何進(jìn)行的,貨物被送到收貨人所在地區(qū)的快遞站點(diǎn),進(jìn)行配送,收貨人等待收貨就可以了。

      –>這個(gè)過(guò)程很形象地說(shuō)明了信息在網(wǎng)絡(luò)中傳遞的過(guò)程。其中,貨物就是數(shù)據(jù)信息,2個(gè)快遞站點(diǎn)就是2個(gè)端點(diǎn)Socket。

      JAVA進(jìn)階學(xué)習(xí)之Socket編程

      (6)信息如何在網(wǎng)絡(luò)中尋址傳遞,應(yīng)用程序并不用關(guān)心,只負(fù)責(zé)準(zhǔn)備發(fā)送數(shù)據(jù)和接收數(shù)據(jù)即可。

      2. Socket通信原理

      (1)對(duì)于編程人員來(lái)說(shuō),無(wú)須了解Socket底層機(jī)制是如何傳送數(shù)據(jù)的,而是直接將數(shù)據(jù)提交給Socket,Socket會(huì)根據(jù)應(yīng)用程序提供的相關(guān)信息,通過(guò)一系列計(jì)算,綁定IP及信息數(shù)據(jù),將數(shù)據(jù)交給驅(qū)動(dòng)程序向網(wǎng)絡(luò)上發(fā)送。

      (2)Socket的底層機(jī)制非常復(fù)雜,Java平臺(tái)提供了一些簡(jiǎn)單但是強(qiáng)大的類(lèi),可以簡(jiǎn)單有效地使用Socket開(kāi)發(fā)通信程序而無(wú)須了解底層機(jī)制。

      3. java.net包

      (1)java.net包提供了若干支持基于套接字的客戶(hù)端/服務(wù)器通信的類(lèi)。

      (2)java.net包中常用的類(lèi)有Socket、ServerSocket、DatagramPacket、DatagramSocket、InetAddress、URL、URLConnection和URLEncoder等。

      (3)為了監(jiān)聽(tīng)客戶(hù)端的連接請(qǐng)求,可以使用ServerSocket類(lèi)。

      (4)Socket類(lèi)實(shí)現(xiàn)用于網(wǎng)絡(luò)上進(jìn)程間通信的套接字。

      (5)DatagramSocket類(lèi)使用UDP協(xié)議實(shí)現(xiàn)客戶(hù)端和服務(wù)器套接字。

      (6)DatagramPacket類(lèi)使用DatagramSocket類(lèi)的對(duì)象封裝設(shè)置和收到的數(shù)據(jù)報(bào)。

      (7)InetAddress類(lèi)表示Internet地址。

      (8)在創(chuàng)建數(shù)據(jù)報(bào)報(bào)文和Socket對(duì)象時(shí),可以使用InetAddress類(lèi)

      二、基于TCP協(xié)議的Socket編程

      1.Socket類(lèi)和ServerSocket類(lèi)

      (1)java.net包的兩個(gè)類(lèi)Socket和ServerSocket,分別用來(lái)實(shí)現(xiàn)雙向安全連接的客戶(hù)端和服務(wù)器端,它們是基于TCP協(xié)議進(jìn)行工作的,工作過(guò)程如同打電話(huà)的過(guò)程,只有雙方都接通了,才能開(kāi)始通話(huà)。

      (2)進(jìn)行網(wǎng)絡(luò)通信時(shí),Socket需要借助數(shù)據(jù)流來(lái)完成數(shù)據(jù)的傳遞工作。

      (3)一個(gè)應(yīng)用程序要通過(guò)網(wǎng)絡(luò)向另一個(gè)應(yīng)用程序發(fā)送數(shù)據(jù),只要簡(jiǎn)單地創(chuàng)建Socket,然后將數(shù)據(jù)寫(xiě)入到與該Socket關(guān)聯(lián)的輸出流即可。對(duì)應(yīng)的,接收方的應(yīng)用程序創(chuàng)建Socket,從相關(guān)聯(lián)的輸入流讀取數(shù)據(jù)即可。

      (4)注意:2個(gè)端點(diǎn)在基于TCP協(xié)議的Socket編程中,經(jīng)常一個(gè)作為客戶(hù)端,一個(gè)作為服務(wù)器端,也就是遵循client-server模型。

      ● Socket類(lèi)

      Socket對(duì)象在客戶(hù)端和服務(wù)器之間建立連接。可用Socket類(lèi)的構(gòu)造方法創(chuàng)建套接字,并將此套接字連接至指定的主機(jī)和端口。

      (1)構(gòu)造方法

      –>第一種構(gòu)造方法以主機(jī)名和端口號(hào)作為參數(shù)來(lái)創(chuàng)建一個(gè)Socket對(duì)象。創(chuàng)建對(duì)象時(shí)可能拋出UnknownHostException或IOException異常,必須捕獲它們。

      Socket s = new Socket(hostName,port);

      –>第二種構(gòu)造方法以InetAddress對(duì)象和端口號(hào)作為參數(shù)來(lái)創(chuàng)建一個(gè)Socket對(duì)象。構(gòu)造方法可能拋出IOException或UnknownHostException異常,必須捕獲并處理它們。

      Socket s = new Socket(address,port);

      (2)常用方法
      JAVA進(jìn)階學(xué)習(xí)之Socket編程

      ● ServerSocket類(lèi)

      ServerSocket對(duì)象等待客戶(hù)端建立連接,連接建立以后進(jìn)行通信。

      (1)構(gòu)造方法

      –>第一種構(gòu)造方法接受端口號(hào)作為參數(shù)創(chuàng)建ServerSocket對(duì)象,創(chuàng)建此對(duì)象時(shí)可能拋出IOException異常,必須捕獲和處理它。

      ServerSocket ss = new ServerSocket(port);

      –>第二種構(gòu)造方法接受端口號(hào)和最大隊(duì)列長(zhǎng)度作為參數(shù),隊(duì)列長(zhǎng)度表示系統(tǒng)在拒絕連接前可以擁有的最大客戶(hù)端連接數(shù)。

      ServerSocket ss = new ServerSocket(port,maxqu);

      (2)常用方法

      –>Socket類(lèi)中列出的方法也適用于ServerSocket類(lèi)。

      –>ServerSocket類(lèi)具有accept()方法,此方法用于等待客戶(hù)端發(fā)起通信,這樣Socket對(duì)象就可用于進(jìn)一步的數(shù)據(jù)傳輸。

      2.使用Socket編程實(shí)現(xiàn)登錄功能

      JAVA進(jìn)階學(xué)習(xí)之Socket編程

      ● 實(shí)現(xiàn)單用戶(hù)登錄

      –>Socket網(wǎng)絡(luò)編程一般分成如下4個(gè)步驟進(jìn)行:

      (1)建立連接。

      (2)打開(kāi)Socket關(guān)聯(lián)的輸入/輸出流。

      (3)從數(shù)據(jù)流中寫(xiě)入信息和讀取信息。

      (4)關(guān)閉所有的數(shù)據(jù)流和Socket。

      –>使用兩個(gè)類(lèi)模擬實(shí)現(xiàn)用戶(hù)登錄的功能,實(shí)現(xiàn)客戶(hù)端向服務(wù)器端發(fā)送用戶(hù)登錄信息,服務(wù)器端顯示這些信息。

      客戶(hù)端實(shí)現(xiàn)步驟:

      1)建立連接,連接指向服務(wù)器及端口。

      2)打開(kāi)Socket關(guān)聯(lián)的輸入/輸出流。

      3)向輸出流中寫(xiě)入信息。

      4)從輸入流中讀取響應(yīng)信息。

      5)關(guān)閉所有的數(shù)據(jù)流和Socket。

      服務(wù)器端實(shí)現(xiàn)步驟:

      1)建立連接,監(jiān)聽(tīng)端口。

      2)使用accept()方法等待客戶(hù)端發(fā)起通信

      3)打開(kāi)Socket關(guān)聯(lián)的輸入/輸出流。

      4)從輸入流中讀取請(qǐng)求信息。

      5)向輸出流中寫(xiě)入信息。

      6)關(guān)閉所有的數(shù)據(jù)流和Socket。

      –>客戶(hù)端和服務(wù)器端的交互,采用一問(wèn)一答的模式,先啟動(dòng)服務(wù)器進(jìn)入監(jiān)聽(tīng)狀態(tài),等待客戶(hù)端的連接請(qǐng)求,連接成功以后,客戶(hù)端先“發(fā)言”,服務(wù)器給予“回應(yīng)”。

      示例01:實(shí)現(xiàn)傳遞對(duì)象信息。

      ♥ user類(lèi)

      package cn.bdqn.demo02;  import java.io.Serializable;  public class User implements Serializable {  	private static final long serialVersionUID = 1L; 	/** 用戶(hù)名 */ 	private String loginName; 	/** 用戶(hù)密碼 */ 	private String pwd;  	public User() { 		super(); 	}  	public User(String loginName, String pwd) { 		super(); 		this.loginName = loginName; 		this.pwd = pwd; 	}  	public String getLoginName() { 		return loginName; 	}  	public void setLoginName(String loginName) { 		this.loginName = loginName; 	}  	public String getPwd() { 		return pwd; 	}  	public void setPwd(String pwd) { 		this.pwd = pwd; 	}  }
      登錄后復(fù)制

      ♥ LoginServer類(lèi)

      package cn.bdqn.demo02;  import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket;  public class LoginServer {  	public static void main(String[] args) { 		ServerSocket serverSocket = null; 		Socket socket = null; 		InputStream is = null; 		ObjectInputStream ois = null; 		OutputStream os = null; 		try { 			// 建立一個(gè)服務(wù)器Socket(ServerSocket),指定端口8800并開(kāi)始監(jiān)聽(tīng) 			serverSocket = new ServerSocket(8800); 			// 使用accept()方法等待客戶(hù)端發(fā)起通信 			socket = serverSocket.accept(); 			// 打開(kāi)輸入流 			is = socket.getInputStream(); 			// 反序列化 			ois = new ObjectInputStream(is); 			// 獲取客戶(hù)端信息,即從輸入流讀取信息 			User user = (User) ois.readObject(); 			if (user != null) { 				System.out.println("我是服務(wù)器,客戶(hù)登錄信息為:" + user.getLoginName() + "," 						+ user.getPwd()); 			}  			// 給客戶(hù)端一個(gè)響應(yīng),即向輸出流中寫(xiě)入信息 			String reply = "歡迎你,登錄成功"; 			os = socket.getOutputStream(); 			os.write(reply.getBytes()); 		} catch (IOException e) { 			e.printStackTrace(); 		} catch (ClassNotFoundException e) { 			e.printStackTrace(); 		} finally { 			// 關(guān)閉資源 			try { 				os.close(); 				ois.close(); 				is.close(); 				socket.close(); 				serverSocket.close(); 			} catch (IOException e) { 				e.printStackTrace(); 			} 		} 	} }
      登錄后復(fù)制

      LoginClient類(lèi)

      package cn.bdqn.demo02;  import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException;  public class LoginClient {  	/* 	 * 示例02:升級(jí)演示示例01,實(shí)現(xiàn)傳遞對(duì)象信息。 	 */ 	 	public static void main(String[] args) { 		Socket socket = null; 		OutputStream os = null; 		ObjectOutputStream oos = null; 		InputStream is = null; 		BufferedReader br = null; 		try { 			// 建立客戶(hù)端Socket連接,指定服務(wù)器的位置為本機(jī)以及端口為8800 			socket = new Socket("localhost", 8800); 			// 打開(kāi)輸出流 			os = socket.getOutputStream(); 			// 對(duì)象序列化 			oos = new ObjectOutputStream(os); 			// 發(fā)送客戶(hù)端信息,即向輸出流中寫(xiě)入信息 			User user = new User("Tom", "123456"); 			oos.writeObject(user); 			socket.shutdownOutput();  			// 接收服務(wù)器端的響應(yīng),即從輸入流中讀取信息 			is = socket.getInputStream(); 			br = new BufferedReader(new InputStreamReader(is)); 			String reply; 			while ((reply = br.readLine()) != null) { 				System.out.println("我是客戶(hù)端,服務(wù)器的響應(yīng)為:" + reply); 			} 		} catch (UnknownHostException e) { 			e.printStackTrace(); 		} catch (IOException e) { 			e.printStackTrace(); 		} finally { 			try { 				br.close(); 				is.close(); 				oos.close(); 				os.close(); 				socket.close(); 			} catch (IOException e) { 				e.printStackTrace(); 			} 		} 	} }
      登錄后復(fù)制

      示例02:升級(jí)演示示例01,實(shí)現(xiàn)傳遞多個(gè)對(duì)象信息。

      user類(lèi)

      package cn.bdqn.demo03;  import java.io.Serializable;  public class User implements Serializable {  	private static final long serialVersionUID = 1L; 	/** 用戶(hù)名 */ 	private String loginName; 	/** 用戶(hù)密碼 */ 	private String pwd;  	public User() { 		super(); 	}  	public User(String loginName, String pwd) { 		super(); 		this.loginName = loginName; 		this.pwd = pwd; 	}  	public String getLoginName() { 		return loginName; 	}  	public void setLoginName(String loginName) { 		this.loginName = loginName; 	}  	public String getPwd() { 		return pwd; 	}  	public void setPwd(String pwd) { 		this.pwd = pwd; 	}  }
      登錄后復(fù)制

      LoginServer類(lèi)

      package cn.bdqn.demo03;  import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket;  public class LoginServer {  	public static void main(String[] args) { 		ServerSocket serverSocket = null; 		Socket socket = null; 		InputStream is = null; 		ObjectInputStream ois = null; 		OutputStream os = null; 		try { 			// 建立一個(gè)服務(wù)器Socket(ServerSocket),指定端口8800并開(kāi)始監(jiān)聽(tīng) 			serverSocket = new ServerSocket(8800); 			// 使用accept()方法等待客戶(hù)端發(fā)起通信 			socket = serverSocket.accept(); 			// 打開(kāi)輸入流 			is = socket.getInputStream(); 			// 反序列化 			ois = new ObjectInputStream(is); 			// 獲取客戶(hù)端信息,即從輸入流讀取信息 			User[] users = (User[]) ois.readObject(); 			for (int i = 0; i < users.length; i++) { 				System.out.println("我是服務(wù)器,客戶(hù)登錄信息為:" + users[i].getLoginName() 						+ "," + users[i].getPwd()); 			}  			// 給客戶(hù)端一個(gè)響應(yīng),即向輸出流中寫(xiě)入信息 			String reply = "歡迎你,登錄成功"; 			os = socket.getOutputStream(); 			os.write(reply.getBytes()); 		} catch (IOException e) { 			e.printStackTrace(); 		} catch (ClassNotFoundException e) { 			e.printStackTrace(); 		} finally { 			// 關(guān)閉資源 			try { 				os.close(); 				ois.close(); 				is.close(); 				socket.close(); 				serverSocket.close(); 			} catch (IOException e) { 				e.printStackTrace(); 			} 		} 	} }
      登錄后復(fù)制

      LoginClient類(lèi)

      package cn.bdqn.demo03;  import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException;  public class LoginClient {  	/* 	 * 示例02:升級(jí)演示示例01,實(shí)現(xiàn)傳遞對(duì)象信息。 	 */ 	 	public static void main(String[] args) { 		Socket socket = null; 		OutputStream os = null; 		ObjectOutputStream oos = null; 		InputStream is = null; 		BufferedReader br = null; 		try { 			// 建立客戶(hù)端Socket連接,指定服務(wù)器的位置為本機(jī)以及端口為8800 			socket = new Socket("localhost", 8800); 			// 打開(kāi)輸出流 			os = socket.getOutputStream(); 			// 對(duì)象序列化 			oos = new ObjectOutputStream(os); 			// 發(fā)送客戶(hù)端信息,即向輸出流中寫(xiě)入信息 			User user1 = new User("Tom", "123456"); 			User user2 = new User("bob", "123456"); 			User user3 = new User("lisa", "123456"); 			User[] users = {user1,user2,user3}; 			oos.writeObject(users); 			socket.shutdownOutput();  			// 接收服務(wù)器端的響應(yīng),即從輸入流中讀取信息 			is = socket.getInputStream(); 			br = new BufferedReader(new InputStreamReader(is)); 			String reply; 			while ((reply = br.readLine()) != null) { 				System.out.println("我是客戶(hù)端,服務(wù)器的響應(yīng)為:" + reply); 			} 		} catch (UnknownHostException e) { 			e.printStackTrace(); 		} catch (IOException e) { 			e.printStackTrace(); 		} finally { 			try { 				br.close(); 				is.close(); 				oos.close(); 				os.close(); 				socket.close(); 			} catch (IOException e) { 				e.printStackTrace(); 			} 		} 	} }
      登錄后復(fù)制

      ● 實(shí)現(xiàn)多客戶(hù)端用戶(hù)登錄

      JAVA進(jìn)階學(xué)習(xí)之Socket編程

      –>一問(wèn)一答的模式在現(xiàn)實(shí)中顯然不是人們想要的。一個(gè)服務(wù)器不可能只針對(duì)一個(gè)客戶(hù)端服務(wù),一般是面向很多的客戶(hù)端同時(shí)提供服務(wù)的,但是單線(xiàn)程實(shí)現(xiàn)必然是這樣的結(jié)果。

      –>解決這個(gè)問(wèn)題的辦法是采用多線(xiàn)程的方式,可以在服務(wù)器端創(chuàng)建一個(gè)專(zhuān)門(mén)負(fù)責(zé)監(jiān)聽(tīng)的應(yīng)用主服務(wù)程序、一個(gè)專(zhuān)門(mén)負(fù)責(zé)響應(yīng)的線(xiàn)程程序。這樣可以利用多線(xiàn)程處理多個(gè)請(qǐng)求。

      ->客戶(hù)端實(shí)現(xiàn)步驟:

      1)建立連接,連接指向服務(wù)器及端口。

      2)打開(kāi)Socket關(guān)聯(lián)的輸入/輸出流。

      3)向輸出流中寫(xiě)入信息。

      4)從輸入流中讀取響應(yīng)信息。

      5)關(guān)閉所有的數(shù)據(jù)流和Socket。

      –>服務(wù)器端實(shí)現(xiàn)步驟:

      1)創(chuàng)建服務(wù)器線(xiàn)程類(lèi),run()方法中實(shí)現(xiàn)對(duì)一個(gè)請(qǐng)求的響應(yīng)處理。

      2)修改服務(wù)器端代碼,讓服務(wù)器端Socket一直處于監(jiān)聽(tīng)狀態(tài)。

      3)服務(wù)器端每監(jiān)聽(tīng)到一個(gè)請(qǐng)求,創(chuàng)建一個(gè)線(xiàn)程對(duì)象并啟動(dòng)。

      示例03:升級(jí)演示示例02,實(shí)現(xiàn)多客戶(hù)端的響應(yīng)處理。

      user類(lèi)

      package cn.bdqn.demo04;  import java.io.Serializable;  public class User implements Serializable {  	private static final long serialVersionUID = 1L; 	/** 用戶(hù)名 */ 	private String loginName; 	/** 用戶(hù)密碼 */ 	private String pwd;  	public User() { 		super(); 	}  	public User(String loginName, String pwd) { 		super(); 		this.loginName = loginName; 		this.pwd = pwd; 	}  	public String getLoginName() { 		return loginName; 	}  	public void setLoginName(String loginName) { 		this.loginName = loginName; 	}  	public String getPwd() { 		return pwd; 	}  	public void setPwd(String pwd) { 		this.pwd = pwd; 	}  }
      登錄后復(fù)制

      LoginThread

      package cn.bdqn.demo04;  import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.OutputStream; import java.net.Socket;  public class LoginThread extends Thread { 	/* 	 * 示例03:升級(jí)示例02,實(shí)現(xiàn)多客戶(hù)端的響應(yīng)處理。 	 *  	 * 分析如下: 	 * 	(1)創(chuàng)建服務(wù)器端線(xiàn)程類(lèi),run()方法中實(shí)現(xiàn)對(duì)一個(gè)請(qǐng)求的響應(yīng)處理。 	 * 	(2)修改服務(wù)器端代碼,讓服務(wù)器端Socket一直處于監(jiān)聽(tīng)狀態(tài)。 	 * 	(3)服務(wù)器端每監(jiān)聽(tīng)到一個(gè)請(qǐng)求,創(chuàng)建一個(gè)線(xiàn)程對(duì)象并啟動(dòng) 	 */ 	 	Socket socket = null; 	//每啟動(dòng)一個(gè)線(xiàn)程,連接對(duì)應(yīng)的Socket  	public LoginThread(Socket socket) { 		this.socket = socket; 	} 	 	//啟動(dòng)線(xiàn)程,即響應(yīng)客戶(hù)請(qǐng)求 	public void run() { 		InputStream is = null; 		ObjectInputStream ois = null; 		OutputStream os = null; 		try { 			//打開(kāi)輸入流 			is = socket.getInputStream(); 			//反序列化 			ois = new ObjectInputStream(is); 			//獲取客戶(hù)端信息,即從輸入流讀取信息 			User user = (User)ois.readObject(); 			if(user!=null){ 				System.out.println("我是服務(wù)器,客戶(hù)登錄信息為:"+user.getLoginName()+","+user.getPwd()); 			} 			 			//給客戶(hù)端一個(gè)響應(yīng),即向輸出流中寫(xiě)入信息 			os = socket.getOutputStream(); 			String reply = "歡迎你,登錄成功"; 			os.write(reply.getBytes()); 		} catch (IOException e) { 			e.printStackTrace(); 		} catch (ClassNotFoundException e) { 			e.printStackTrace(); 		}finally{ 			try { 				os.close(); 				ois.close(); 				is.close(); 				socket.close(); 			} catch (IOException e) { 				e.printStackTrace(); 			}			 		}	 	}	 }
      登錄后復(fù)制

      LoginServer類(lèi)

      package cn.bdqn.demo04;  import java.io.IOException; import java.net.ServerSocket; import java.net.Socket;  public class LoginServer { 	 	public static void main(String[] args) { 		 		ServerSocket serverSocket = null; 		try { 			// 建立一個(gè)服務(wù)器Socket(ServerSocket)指定端口并開(kāi)始監(jiān)聽(tīng) 			serverSocket = new ServerSocket(8800);  			// 監(jiān)聽(tīng)一直進(jìn)行中 			while (true) { 				// 使用accept()方法等待客戶(hù)發(fā)起通信 				Socket socket = serverSocket.accept(); 				LoginThread loginThread = new LoginThread(socket); 				loginThread.start(); 			} 		} catch (IOException e) { 			e.printStackTrace(); 		} 	} }
      登錄后復(fù)制

      ♥ LoginClient1類(lèi)

      package cn.bdqn.demo04;  import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException;  public class LoginClient01 { 	/* 	 * 客戶(hù)端通過(guò)輸出流向服務(wù)器端發(fā)送請(qǐng)求信息 	 * 服務(wù)器偵聽(tīng)客戶(hù)端的請(qǐng)求得到一個(gè)Socket對(duì)象,將這個(gè)Socket對(duì)象傳遞給線(xiàn)程類(lèi) 	 * 線(xiàn)程類(lèi)通過(guò)輸入流獲取客戶(hù)端的請(qǐng)求并通過(guò)輸出流向客戶(hù)端發(fā)送響應(yīng)信息 	 * 客戶(hù)端通過(guò)輸入流讀取服務(wù)器發(fā)送的響應(yīng)信息 	 *  	 */  	/* 	 * 示例03:升級(jí)演示示例02,實(shí)現(xiàn)多客戶(hù)端的響應(yīng)處理 	 */ 	public static void main(String[] args) { 		 		Socket socket = null; 		OutputStream os = null; 		ObjectOutputStream oos = null; 		InputStream is = null; 		BufferedReader br = null; 		try { 			// 建立客戶(hù)端Socket連接,指定服務(wù)器的位置為本機(jī)以及端口為8800 			socket = new Socket("localhost", 8800); 			// 打開(kāi)輸出流 			os = socket.getOutputStream(); 			// 對(duì)象序列化 			oos = new ObjectOutputStream(os); 			// 發(fā)送客戶(hù)端信息,即向輸出流中寫(xiě)入信息 			User user = new User("Tom", "123456"); 			oos.writeObject(user); 			socket.shutdownOutput();  			// 接收服務(wù)器端的響應(yīng),即從輸入流中讀取信息 			is = socket.getInputStream(); 			br = new BufferedReader(new InputStreamReader(is)); 			String reply; 			while ((reply = br.readLine()) != null) { 				System.out.println("我是客戶(hù)端,服務(wù)器的響應(yīng)為:" + reply); 			} 		} catch (UnknownHostException e) { 			e.printStackTrace(); 		} catch (IOException e) { 			e.printStackTrace(); 		} finally { 			try { 				br.close(); 				is.close(); 				oos.close(); 				os.close(); 				socket.close(); 			} catch (IOException e) { 				e.printStackTrace(); 			} 		} 	} }
      登錄后復(fù)制

      ♥ LoginClient2類(lèi)和LoginClient3類(lèi)

      同LoginClient1類(lèi)一樣,創(chuàng)建不同的User對(duì)象即可

      –>java.net包中的InetAddress類(lèi)用于封裝IP地址和DNS。要?jiǎng)?chuàng)建InetAddress類(lèi)的實(shí)例,可以使用工廠(chǎng)方法,因?yàn)榇祟?lèi)沒(méi)有構(gòu)造方法。

      –>InetAddress類(lèi)中的工廠(chǎng)方法JAVA進(jìn)階學(xué)習(xí)之Socket編程

      –>如果找不到主機(jī),兩種方法都將拋出UnknownHostNameException異常。

      三、基于UDP協(xié)議的Socket編程

      TCP UDP
      是否連接 面向連接 面向非連接
      傳輸可靠性 可靠 不可靠
      速度

      1.DatagramPacket類(lèi)和DatagramSocket類(lèi)

      (1)基于TCP的網(wǎng)絡(luò)通信是安全的,是雙向的,如同打電話(huà),需要先有服務(wù)端,建立雙向連接后,才開(kāi)始數(shù)據(jù)通信。

      (2)基于UDP的網(wǎng)絡(luò)通信只需要指明對(duì)方地址,然后將數(shù)據(jù)送出去,并不會(huì)事先連接。這樣的網(wǎng)絡(luò)通信是不安全的,所以只應(yīng)用在如聊天系統(tǒng)、咨詢(xún)系統(tǒng)等場(chǎng)合下。

      (3)數(shù)據(jù)報(bào)是表示通信的一種報(bào)文類(lèi)型,使用數(shù)據(jù)報(bào)進(jìn)行通信時(shí)無(wú)須事先建立連接,它是基于UDP協(xié)議進(jìn)行的。

      (4)Java中有兩個(gè)可使用數(shù)據(jù)報(bào)實(shí)現(xiàn)通信的類(lèi),即DatagramPacketDatagramSocket。

      (5)DatagramPacket類(lèi)起到容器的作用,DatagramSocket類(lèi)用于發(fā)送或接收DatagramPacket。

      (6)DatagramPacket類(lèi)不提供發(fā)送或接收數(shù)據(jù)的方法,而DatagramSocket類(lèi)提供send()方法和receive()方法,用于通過(guò)套接字發(fā)送和接收數(shù)據(jù)報(bào)。

      ● DatagramPacket類(lèi)

      (1)構(gòu)造方法

      –>客戶(hù)端要向外發(fā)送數(shù)據(jù),必須首先創(chuàng)建一個(gè)DatagramPacket對(duì)象,再使用DatagramSocket對(duì)象發(fā)送。

      JAVA進(jìn)階學(xué)習(xí)之Socket編程

      (2)常用方法

      JAVA進(jìn)階學(xué)習(xí)之Socket編程

      ● DatagramSocket類(lèi)

      (1)構(gòu)造方法

      –>DatagramSocket類(lèi)不維護(hù)連接狀態(tài),不產(chǎn)生輸入/輸出數(shù)據(jù)流,它的唯一作用就是接收和發(fā)送DatagramPacket對(duì)象封裝好的數(shù)據(jù)報(bào)。

      JAVA進(jìn)階學(xué)習(xí)之Socket編程

      (2)常用方法

      JAVA進(jìn)階學(xué)習(xí)之Socket編程

      2.使用Socket編程實(shí)現(xiàn)客戶(hù)咨詢(xún)

      –>利用UDP通信的兩個(gè)端點(diǎn)是平等的,也就是說(shuō)通信的兩個(gè)程序關(guān)系是對(duì)等的,沒(méi)有主次之分,甚至它們的代碼都可以完全是一樣的,這一點(diǎn)要與基于TCP協(xié)議的Socket編程區(qū)分開(kāi)來(lái)。

      –>基于UDP協(xié)議的Socket網(wǎng)絡(luò)編程一般按照以下4個(gè)步驟進(jìn)行:

      (1)利用DatagramPacket對(duì)象封裝數(shù)據(jù)包。

      (2)利用DatagramSocket對(duì)象發(fā)送數(shù)據(jù)包。

      (3)利用DatagramSocket對(duì)象接收數(shù)據(jù)包。

      (4)利用DatagramPacket對(duì)象處理數(shù)據(jù)包。

      JAVA進(jìn)階學(xué)習(xí)之Socket編程

      –>模擬客戶(hù)咨詢(xún)功能,實(shí)現(xiàn)發(fā)送方發(fā)送咨詢(xún)問(wèn)題,接收方接收并顯示發(fā)送來(lái)的咨詢(xún)問(wèn)題。

      發(fā)送方實(shí)現(xiàn)步驟:

      1)獲取本地主機(jī)的InetAddress對(duì)象。

      2)創(chuàng)建DatagramPacket對(duì)象,封裝要發(fā)送的信息。

      3)利用DatagramSocket對(duì)象將DatagramPacket對(duì)象數(shù)據(jù)發(fā)送出去。

      接收方實(shí)現(xiàn)步驟:

      1)創(chuàng)建DatagramPacket對(duì)象,準(zhǔn)備接收封裝的數(shù)據(jù)。

      2)創(chuàng)建DatagramSocket對(duì)象,接收數(shù)據(jù)保存于DatagramPacket對(duì)象中。

      3)利用DatagramPacket對(duì)象處理數(shù)據(jù)。

      示例04:發(fā)送方發(fā)送咨詢(xún)問(wèn)題,接收方回應(yīng)咨詢(xún)。

      ♥ Receive類(lèi)

      package cn.bdqn.demo05;  import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketAddress; import java.net.SocketException;  public class Receive {  	public static void main(String[] args) { 		/* 		 * 示例06:發(fā)送方發(fā)送咨詢(xún)問(wèn)題,接收方回應(yīng)咨詢(xún)。 		 *  		 * 接收方實(shí)現(xiàn)步驟如下:  		 * (1)創(chuàng)建DatagramPacket對(duì)象,準(zhǔn)備接收封裝的數(shù)據(jù)。 		 * (2)創(chuàng)建DatagramSocket對(duì)象,接收數(shù)據(jù)保存于DatagramPacket對(duì)象中。 		 * (3)利用DatagramPacket對(duì)象處理數(shù)據(jù)。 		 */  		DatagramSocket ds = null; 		DatagramPacket dp = null; 		DatagramPacket dpto = null; 		// 創(chuàng)建DatagramPacket對(duì)象,用來(lái)準(zhǔn)備接收數(shù)據(jù) 		byte[] buf = new byte[1024]; 		dp = new DatagramPacket(buf, 1024); 		try { 			// 創(chuàng)建DatagramSocket對(duì)象,接收數(shù)據(jù) 			ds = new DatagramSocket(8800); 			ds.receive(dp); 			// 顯示接收到的信息 			String mess = new String(dp.getData(), 0, dp.getLength()); 			System.out.println(dp.getAddress().getHostAddress() + "說(shuō):" + mess);  			String reply = "你好,我在,請(qǐng)咨詢(xún)!"; 			// 顯示與本地對(duì)話(huà)框 			System.out.println("我  說(shuō):" + reply); 			// 創(chuàng)建DatagramPacket對(duì)象,封裝數(shù)據(jù) 			SocketAddress sa = dp.getSocketAddress(); 			dpto = new DatagramPacket(reply.getBytes(), 					reply.getBytes().length, sa); 			ds.send(dpto); 		} catch (SocketException e) { 			e.printStackTrace(); 		} catch (IOException e) { 			e.printStackTrace(); 		} finally { 			ds.close(); 		} 	} }
      登錄后復(fù)制

      ♥ Send類(lèi)

      package cn.bdqn.demo05;  import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.net.UnknownHostException;  public class Send { 	/* 	 * 示例06:升級(jí)示例05,發(fā)送方發(fā)送咨詢(xún)問(wèn)題,接收方回應(yīng)咨詢(xún)。 	 *  	 * 發(fā)送方實(shí)現(xiàn)步驟如下:  	 * (1)獲取本地主機(jī)的InetAddress對(duì)象。  	 * (2)創(chuàng)建DatagramPacket對(duì)象,封裝要發(fā)送的信息。 	 * (3)利用DatagramSocket對(duì)象將DatagramPacket對(duì)象數(shù)據(jù)發(fā)送出去。 	 */  	public static void main(String[] args) { 		DatagramSocket ds = null; 		InetAddress ia = null; 		String mess = "你好,我想咨詢(xún)一個(gè)問(wèn)題。"; 		System.out.println("我說(shuō):" + mess); 		try { 			// 獲取本地主機(jī)地址 			ia = InetAddress.getByName("localhost"); 			// 創(chuàng)建DatagramPacket對(duì)象,封裝數(shù)據(jù) 			DatagramPacket dp = new DatagramPacket(mess.getBytes(), 					mess.getBytes().length, ia, 8800); 			// 創(chuàng)建DatagramSocket對(duì)象,向服務(wù)器發(fā)送數(shù)據(jù) 			ds = new DatagramSocket(); 			ds.send(dp);  			byte[] buf = new byte[1024]; 			DatagramPacket dpre = new DatagramPacket(buf, buf.length); 			ds.receive(dpre); 			// 顯示接收到的信息 			String reply = new String(dpre.getData(), 0, dpre.getLength()); 			System.out.println(dpre.getAddress().getHostAddress() + "說(shuō):" 					+ reply); 		} catch (UnknownHostException e) { 			e.printStackTrace(); 		} catch (SocketException e) { 			e.printStackTrace(); 		} catch (IOException e) { 			e.printStackTrace(); 		} finally { 			ds.close(); 		} 	} }
      登錄后復(fù)制

      推薦學(xué)習(xí):《java視頻教程》

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)