Socket 筆記

1、網絡基礎知識html

一、兩臺計算機要經過網絡進行通訊,必須具有:java

1)惟一的標識(IP地址);編程

2)須要共同的語言(協議);數組

3)辨別不一樣應用程序(端口號)。服務器

二、瞭解相關概念網絡

1)IP地址:多線程

每臺計算機的惟一標識,用來區分網絡中的不一樣主機,是兩臺主機進行網絡通訊必不可少的。2)協議:socket

(1)TCP/IP協議:目前世界上應用最爲普遍的協議。是以TCP和IP爲基礎的不一樣層次上多個協議的集合。也稱爲:TCP/IP協議族  或者  TCP/IP協議棧。(TCP: Transmission Control Protocol -- 傳輸控制協議;IP :Internet Protocol -- 互聯網協議)this

3)CP/IP模型(網絡分層):url

(1)物理層(如網線、網線槽)

(2)數據鏈路層

(3)網絡層

(4)傳輸層:TCP/IP協議

(5)應用層:HTTP超文本傳輸協議、FTP文件傳輸協議、SMTP簡單郵件傳送協議、Telnet遠程登陸服務。

4)端口號:

(1)用於區分不一樣的應用程序;

(2)端口號範圍爲0-65535,其中0-1023爲系統所保留;

(3)IP地址和端口號組成了所謂的Socket,Socket是網絡上運行的程序之間雙向通訊鏈路的終結點,是TCP和UDP的基礎。

(4)經常使用端口號-- http: 80;  ftp; 21;  telnet; 23。

5)JAVA中得網絡支持。針對網絡通訊的不一樣層次,Java提供的網絡功能有四大類:

(1)InetAddress:用於標識網絡上的硬件資源。(IP地址)

(2)URL:統一資源定位符---經過URL能夠直接讀取或寫入網絡上得數據。

(3)Sockets:使用TCP協議實現網絡通訊的Socket相關的類。

(4)Datagram:使用UDP協議,將數據保存在數據報中,經過網絡進行通訊。

 

2、Java網絡相關的API的應用

1InetAddress類

1)InetAddress類沒有構造方法,因此不能直接new出一個對象;但能夠經過InetAddress類的靜態方法得到InetAddress的對象:如

InetAddress.getLocalHost();

InetAddress.getByName();

2)類主要方法:

String - address.getHostName();

String - address.getHostAddress();

public static InetAddress getByName(String host) throws UnknownHostException

// 在給定主機名的狀況下肯定主機的 IP 地址。主機名能夠是機器名(如 "java.sun.com"),也能夠是其 IP 地址的文本表示形式

3)InetAddress使用示例代碼:

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;

/**
 * InetAddress類的基本使用
 */
public class InetAddressDemo {
	public static void main(String[] args) throws UnknownHostException {
		/*
		 * 獲取本地主機信息
		 */
		InetAddress address = InetAddress.getLocalHost();
		System.out.println("主機名稱" + address.getHostName());
		System.out.println("IP地址:" + address.getHostAddress());
		byte[] bytes = address.getAddress(); // 以獲取字節數組的形式獲取地址
		System.out.println("本身數組形式的ip: " + Arrays.toString(bytes));
		System.out.println(address);// 直接輸出InetAddress對象
		System.out.println();
		
		/*
		 *  根據機器名獲取InetAddresss實例
		 */
		InetAddress address2 = InetAddress.getByName("Moonlight");
		System.out.println("計算機名:" + address2.getHostName());
		System.out.println("IP地址:" + address2.getHostAddress());
		System.out.println();
		
		/*
		 * 根據IP獲取InetAddress實例
		 */
		InetAddress address3 = InetAddress.getByName("192.168.1.102");
		System.out.println("計算機名:" + address3.getHostName());
		System.out.println("IP地址:" + address3.getHostAddress());
		System.out.println();
		
		/*
		 * 獲取其它地址
		 */
		InetAddress address4 = InetAddress.getByName("baidu.com");
		System.out.println("計算機名:" + address4.getHostName());
		System.out.println("IP地址:" + address4.getHostAddress());
		System.out.println();
	}
}

二、URL類

1)簡介:

(1)URL(Uniform Resource Locator)統一資源定位符,表示Internet上某一資源的地址

(2)URL由兩部分組成:協議名稱和資源名稱,中間用冒號隔開

(3)在java.net包中,提供了URL類來表示URL

2)使用URL讀取網頁內容

(1)經過URL對象的openStream()方法能夠獲得指定資源的輸入流

(2)經過輸入流能夠讀取、訪問網絡上的數據

3)URL類使用示例代碼:

import java.net.MalformedURLException;
import java.net.URL;

/**
 * URL經常使用方法
 */
public class URLDemo {
	public static void main(String[] args) throws MalformedURLException {
		// 建立URL實例
		URL url = new URL("http://www.baidu.com");
		URL url2 = new URL(url, "/index.html?uname=1#test"); // 在原有的URL資源上再建立URL實例,#後面表示錨點
		System.out.println("協議" + url2.getProtocol());
		System.out.println("主機" + url2.getHost());
		// 若是未指定端口號,則使用默認的端口號,此時getPort()返回-1
		System.out.println("端口" + url2.getPort());
		System.out.println("文件路徑" + url2.getPath());
		System.out.println("文件名稱:" + url2.getFile());
		System.out.println("相對路徑" + url2.getRef());
		System.out.println("查詢字符串" + url2.getQuery());
	}
}

 

3、Socket實現TCP編程

一、Socket通訊模型

 

1)上圖的通訊模型的順序爲:

(1)先創建服務端監聽Soket,等待客戶端請求。

(2)客戶端建立socket,向服務端發送請求。

(3)服務端接收請求,並建立鏈接socket到此步驟時,服務端與客戶端創建了鏈接。

(4)服務端和客戶端開始通訊(InputStream、OutputStream)。

(5)最後關閉socket與相關資源。

二、Socket實現TCP編程通訊的實現步驟

1)服務端:

(1)建立ServerSocket對象,綁定監聽端口

(2)經過accept()方法監聽客戶端的請求

(3)創建鏈接後,經過輸入流讀取客戶端發送的請求信息

(4)經過輸出流向客戶端發送相應信息

(5)關閉相關資源

代碼示例:

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 服務端
 * 基於TCP協議的Socket通訊 -- 單線程
 */
public class TCPServer {
	
	public static void main(String[] args) {
		try {
			// 1.建立一個服務器端Socket,即ServerSocket,指定綁定的端口,並監聽
			ServerSocket serverSocket = new ServerSocket(8888);
			// 2.調用accept()方法開始監聽,等待客戶端的鏈接
			System.out.println("服務器即將啓動,等待客戶端的鏈接***");
			Socket socket = serverSocket.accept();
			// 3.獲取輸入流,並讀取客戶端信息
			InputStream is = socket.getInputStream();
			InputStreamReader irs = new InputStreamReader(is);
			BufferedReader br = new BufferedReader(irs);
			String info = null;
			while((info=br.readLine()) != null){
				System.out.println("服務器接收到消息:" + info);
			}
			socket.shutdownInput();//關閉輸入流
			// 4.獲取輸出流,響應客戶端請求
		    OutputStream os = socket.getOutputStream();
			PrintWriter pw = new PrintWriter(os);// 包裝爲打印流
			pw.write("終於等到你!");
			pw.flush();
			
			// 5.關閉資源
			pw.close();
			os.close();
			br.close();
			irs.close();
			is.close();
			socket.close();
			serverSocket.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

2)客戶端:

(1)建立Socket對象,指明須要鏈接的服務器的地址和端口號

(2)鏈接創建後,經過輸出流向服務器端發送請求信息

(3)經過輸入流獲取服務器相應的信息

(4)關閉相關資源

代碼示例:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;

/**
 * 客戶端
 * 基於TCP協議的Socket通訊
 */
public class TCPClient {
	public static void main(String[] args) {
		try {
			// 1.建立客戶端Socket,指定服務器地址和端口
			Socket socket = new Socket("localhost", 8888);
			
			// 2.獲取輸出流,向服務器端發送信息
			OutputStream os = socket.getOutputStream();//字節輸出流
			PrintWriter pw = new PrintWriter(os);
			pw.write("客戶端發信息來啦~~");
			pw.flush();
			socket.shutdownOutput();// 關閉輸出流
			
			// 3.獲取輸入流,並讀取服務器端的響應信息
			InputStream is =  socket.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			String info = null;
			while((info=br.readLine()) != null){
				System.out.println("客戶端接收到信息:" + info);
			}
			
			// 4.關閉資源
			br.close();
			is.close();
			pw.close();
			os.close();
			socket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

三、應用多線程來實現服務器與多客戶端之間的通訊的基本基本步驟

(1)服務器端建立ServerSocket,循環調用accept()等待客戶端鏈接

(2)客戶端建立一個socket並請求和服務器端鏈接

(3)服務器端接收客戶端請求,建立socket與該客戶創建專線鏈接

(4)創建鏈接的兩個socket在一個單獨的線程上對話

(5)服務器端繼續等待新的鏈接

代碼示例:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 服務端
 * 基於TCP協議的Socket通訊 -- 多線程實現多客戶的通訊
 */
public class TCPServerMulConnection {
	public static void main(String[] args) {
		try {
			// 建立一個服務器端Socket,即ServerSocket,指定綁定的端口,並監聽
			ServerSocket serverSocket = new ServerSocket(8888);
			// 調用accept()方法開始監聽,等待客戶端的鏈接
			System.out.println("服務器即將啓動,等待客戶端的鏈接***");
			Socket socket = null;
			int count = 0; // 記錄客戶端的鏈接
			// 循環監聽等待客戶端的鏈接
			while (true) {
				// 調用accept()方法開始監聽,等待客戶端的鏈接
				socket = serverSocket.accept();
				// 建立一個新的線程
				ServerThreadHelper serverThread = new ServerThreadHelper(socket);
				//serverThread.setPriority(4); //可設置線程優先級(優先級默認爲5,數字越小,優先級越低;未設置優先級可能致使運行時速度很是慢,可適當下降)
				// 啓動線程
				serverThread.start();
				count++; // 統計客戶端的數量
				InetAddress address = socket.getInetAddress();
				System.out.println("第 " + count + " 個客戶端鏈接成功!此客戶端的ip爲:" + address.getHostAddress());
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}


/**
 * 服務器端線程處理類
 */
class ServerThreadHelper extends Thread{
	// 和本線程相關的socket
	Socket socket = null;
	
	public ServerThreadHelper(Socket socket){
		this.socket = socket;
	}
	
	// 線程執行的操做,響應客戶端請求
	public void run(){
		
		InputStream is = null;
		InputStreamReader irs = null;
		BufferedReader br = null;
		OutputStream os = null;
		PrintWriter pw = null;
		try {
			// 1.獲取輸入流,並讀取客戶端信息
			is = socket.getInputStream();
			irs = new InputStreamReader(is);
			br = new BufferedReader(irs);
			String info = null;
			while((info=br.readLine()) != null){
				System.out.println("服務器接收到消息:" + info);
			}
			socket.shutdownInput();//關閉輸入流
			// 2.獲取輸出流,響應客戶端請求
			os = socket.getOutputStream();
			pw = new PrintWriter(os);
			pw.write("終於等到你!");
			pw.flush();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 3.關閉資源
			try {
				if (pw!=null) {
					pw.close();
				}
				if (os!=null) {
					os.close();
				}
				if (br!=null) {
					br.close();
				}
				if (irs!=null) {
					irs.close();
				}
				if (is!=null) {
					is.close();
				}
				if (socket!=null) {
					socket.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}
}

 

4、Socket實現UDP編程

一、UDP編程簡介

(1)UDP協議(用戶數據報協議)是無鏈接、不可靠、無序的,特色是速度比較快

(2)進行數據傳輸時,首先要將要傳輸的數據定義成數據報(Datagram),在數據報中指明數據所要達到的Socket(主機地址和端口號),而後再將數據報發送出去

(3)相關的操做類:DatagramPacket:表示數據報包 DatagramSocket:進行端到端通訊的類

二、Socket實現UDP編程

1)服務器端實現步驟

(1)建立DatagramSocket,指定端口號

(2)建立DatagramPacket,用於接收客戶端請求

(3)接收客戶端發送的數據信息

(4)讀取數據

(5)關閉資源

示例代碼:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

/**
 * 服務端
 * 基於UDP實現Socket通訊
 */
public class UDPServer {

	public static void main(String[] args) throws IOException {
		/*
		 * 接收客戶發送的數據
		 */
		// 1.建立服務器端DatagramSocket,指定端口
		DatagramSocket socket = new DatagramSocket(8800);
		// 2.建立數據報,用於接收客戶端發送的數據
		byte[] data = new byte[1024];
		DatagramPacket packet = new DatagramPacket(data, data.length);
		// 3.接收客戶端發送的數據
		System.out.println("服務器已啓動,等待接收數據報中……");
		socket.receive(packet); // 此方法在接收到數據報以前會一直阻塞
		// 4.讀取數據
		String info = new String(data, 0, packet.getLength());
		System.out.println("服務器接收到了新信息:" + info);
		
		/*
		 * 向客戶端響應數據
		 */
		// 1.定義
		InetAddress address = packet.getAddress();
		int port = packet.getPort();
		byte[] data2 = "服務器已經收到信息啦~".getBytes();
		// 2.建立數據報,包含響應的數據信息
		DatagramPacket packet2 = new DatagramPacket(data2, data2.length, address, port);
		// 3.發送數據,返回給客戶端
		socket.send(packet2);
		// 4.關閉資源
		socket.close();
	}

}

2)客戶端實現步驟

(1)定義發送信息

(2)建立DatagramPacket,包含將要發送的信息

(3)建立DatagramSocket

(4)發送數據(經過DatagramSocket發送)

(5)關閉資源

示例代碼:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * 客戶端
 * 基於UDP實現Socket通訊
 */
public class UDPClient {

	public static void main(String[] args) throws IOException {
		/*
		 * 發送消息給服務端
		 */
		// 1.定義服務器的地址、端口號、數據報
		InetAddress address = InetAddress.getByName("localhost");
		int port = 8800;
		byte[] data = "你好!我是客戶端。".getBytes();
		// 2.建立數據報,包含發送的數據信息
		DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
		// 3.建立DatagramSocket對象
		DatagramSocket socket = new DatagramSocket();
		// 4.向服務器端發送數據報
		socket.send(packet);
		
		/*
		 * 接收服務端響應
		 */
		// 1.建立數據報,用於接收服務器端響應的數據
		byte[] data2 = new byte[1024];
		DatagramPacket packet2 = new DatagramPacket(data2, data2.length);
		// 2.接收服務器響應的數據
		socket.receive(packet2);
		// 3.讀取數據
		String reply = new String(data2, 0, packet2.getLength());
		System.out.println("客戶端接收到新信息:" + reply);
		// 4.關閉資源
		
	}

}

 

5、Socket實現UDP編程

一、使用多線程編寫網絡程序時,能夠將線程的優先級下降,線程的優先級默認是五,數字越小,優先級越低;未設置優先級可能致使運行時速度很是慢,可適當下降。

二、對於同一個socket,若是關閉了輸出流,則與該輸出流相關的socket也會被關閉,因此通常不用關閉流,直接關閉socet便可。

三、能夠將一個對象序列化以後,經過流的方式在網絡上傳輸

ObjectOutputStream oos = new ObjectOutputStream(os);

oos.writeObject(User);

四、網絡上傳輸文件,也是將文件轉換爲流,經過流的方式在網絡上傳輸

BufferedOutputStream  fos = new  BufferedOutputStream(new FileOutputStream(new File("d://")));
相關文章
相關標籤/搜索