1. 程式人生 > >初學socket程式設計(網路程式設計)

初學socket程式設計(網路程式設計)

socket程式設計可以理解為是一種二進位制+IP+埠的一種通訊模式,在任何語言中,都有socket程式設計,因此幾乎所有語言的socket都可以互通。只要是涉及到通訊方面的如QQ,微信等都是涉及到socket,只是他們自己進行了封裝。socket的本質是對tcp/ip的封裝。

網路通訊:

UDP:是面向無連線的,所以效率較高,不會建立連線,不安全。不管有沒有接收方,只管向指定地址傳送東西。(但要求大小在64k以內)底層使用UDP協議。

TCP:是面向連線的,三次握手成功之後才能通訊,位元組流傳輸,效率低於UDP,但是安全性高(因為採用了三次握手和四次揮手協議)。雙方需要建立連線才能通訊(傳送資料)。底層使用TCP協議,TCP底層是用HTTP協議。

TCP三次握手四次揮手示意圖:

TCP通訊實現:

先建立伺服器端:

//TCP協議服務端
public class Server {

	public static void main(String[] args) throws IOException {
		System.out.println("TCP服務端啟動了");
		//啟動服務端
		ServerSocket serverSocket = new ServerSocket(8080);//傳入埠號
		//等待客戶端連線(如果客戶端不連線進來,程式一直阻塞在這裡等待)
		Socket accept = serverSocket.accept();
		//模擬客戶端給服務端傳送訊息的場景
		//生成輸入流
		InputStream is = accept.getInputStream();
		//定義位元組
		byte [] bytes = new byte[1024];
		//讀取
		int length = is.read(bytes);
		//將byte陣列轉為String
		String result = new String(bytes, 0, length);
		System.out.println("伺服器端已經接收到客戶端傳送的訊息:"+result);
	}
}

TCP客戶端:

//TCP客戶端
public class TCPClient {

	public static void main(String[] args) throws Exception, IOException {
		//建立socket
		Socket socket = new Socket("127.0.0.1", 8080);//傳入IP和埠號
		//建立輸出流
		OutputStream os = socket.getOutputStream();
		//先定義一段話
		String mes = "hello";
		//傳送
		os.write(mes.getBytes());
		System.out.println("客戶端傳送訊息完畢");
		
	}
}

先執行伺服器端:

執行客戶端:

訊息傳送完成後,我們再看服務端列印的內容:

下面我們繼續寫一下伺服器接收到訊息後的反饋,伺服器端:

//TCP協議服務端
public class Server {

	public static void main(String[] args) throws IOException {
		//啟動服務端
		ServerSocket serverSocket = new ServerSocket(8080);
		try {
			System.out.println("TCP服務端啟動了");
			//等待客戶端連線(如果客戶端不連線進來,程式一直阻塞在這裡等待)
			Socket accept = serverSocket.accept();
			//模擬客戶端給服務端傳送訊息的場景
			//生成輸入流
			InputStream is = accept.getInputStream();
			//定義位元組
			byte [] bytes = new byte[1024];
			//讀取
			int length = is.read(bytes);
			//將byte陣列轉為String
			String result = new String(bytes, 0, length);
			System.out.println("伺服器端已經接收到客戶端傳送的訊息:"+result);
			
			//返回訊息
			//得到一個OutputStream 
			OutputStream outputStream = accept.getOutputStream();
			//將輸出流轉為列印流
			PrintWriter pw = new PrintWriter(outputStream);
			pw.print("我是伺服器,已經收到訊息");
			pw.flush();
			accept.shutdownOutput();
		} catch (Exception e) {
			// TODO: handle exception
		}finally {
			//使用try,萬一程式碼出現異常,我們就在finally中關閉連線
			serverSocket.close();
		}
		
	}
}

客戶端:

//TCP客戶端
public class TCPClient {

	public static void main(String[] args) throws Exception, IOException {
		//建立socket
		Socket socket = new Socket("127.0.0.1", 8080);//傳入IP和埠號
		try {
			//建立輸出流
			OutputStream os = socket.getOutputStream();
			//先定義一段話
			String mes = "hello";
			//傳送
			os.write(mes.getBytes());
			System.out.println("客戶端傳送訊息完畢");
			//獲取服務端傳送的訊息
			//獲取InputStream
			InputStream is = socket.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			//讀
			String result = br.readLine();
			System.out.println("客戶端===》》伺服器返回的結果:"+result);
		} catch (Exception e) {
			
		}finally {
			socket.close();
		}
		
	}
}

先執行服務端:

再執行客戶端:

此時再看服務端:

UDP實現:

先建立UDP服務端:

//UDP服務端
public class UdpServer {

	public static void main(String[] args) throws IOException {
		System.out.println("udp服務啟動了");
		//定義DatagramSocket
		DatagramSocket ds = new DatagramSocket(8080);//不傳地址,預設本級
		//建立接收的陣列
		byte [] buf = new byte[1024];
		//獲取客戶端傳送的資料
		DatagramPacket dp = new DatagramPacket(buf, buf.length);
		//直到有客戶端連線起來,程式才會執行下去,否則一直阻塞在這裡
		ds.receive(dp);
		String string = dp.getAddress().toString();
		String data = new String(dp.getData(),0,dp.getLength());
		System.out.println("伺服器接收從IP:"+string+"傳輸的資料"+data);
	}
}

建立UDP客戶端:

//udp客戶端
public class UdpClient {

	public static void main(String[] args) throws IOException {
		DatagramSocket ds = new DatagramSocket();//此處不用傳引數
		//定義傳送的資料
		String mes = "hello";
		byte[] bytes = mes.getBytes();
		DatagramPacket dp = new DatagramPacket(bytes, bytes.length,new InetSocketAddress("127.0.0.1",8080));
		//傳送資料
		ds.send(dp);
		ds.close();
		System.out.println("客戶端傳送資訊完畢");
	}
}

先啟動服務端:

再啟動客戶端:

再看服務端:

下面我們來驗證一下UDP是無連線的,傳送訊息時不會關心服務端是否在。我們關掉服務端,啟動客戶端,此時不會出現異常錯誤,即驗證上述。然後我們關掉服務端和客戶端,再重新啟動服務端和客戶端時,剛才在服務端沒有啟動時傳送的資料已經被覆蓋掉了,所以服務端接收到的是它啟動之後的資料。