黑馬程序員_網絡編程

  ------- android培訓java培訓、期待與您交流! ----------


一 網絡編程

1 網絡模型:傳輸方式
(1)OSI參考模型,共7層。應用層、表示層、會話層、傳輸層、網絡層、數據鏈路層、物理層。每一層都有自己特有的數據信息。
(2)TCP/IP參考模型,共5層。應用層、傳輸層、網際層、主機至網絡層。

2 網絡通信要素
(1)IP地址。IP地址用於標識網絡設備,可起個主機名字。本地迴環地址,默認127.0.0.1
(2)端口號。應用程序的一個數字標識,對方指定的應用程序。端口限定在0-65535。而0-1024被系統保留。
常見端口:
Tomcat 8080、Web服務80

(3)傳輸協議。傳輸協議可以理解爲通信規則。國際通用協議TCP/IP。常見的傳輸方式有UDP和TCP。

3 IP地址
(1)java將IP地址封裝成對象。InetAddress類

(2)此類中沒有定義構造方法
方法摘要:
getLocalHost()//獲取本地主機InetAddress對象
getByName(String host)//獲取任意主機InetAddress對象
getHostAddress()//獲取主機地址
getHostName()//獲取主機名字


4 傳輸協議:通信規則
(1)常見的協議:UDP和TCP
UDP:將數據和目的封裝成包,每個包限制在64K以內,面向無連接,是不可靠協議,速度快。 例如:聊天工具、網絡視頻會議、桌面共享
TCP:進行大數據傳輸,面向連接,是可靠協議,速度稍慢。例如:下載工具

(2)Socket是爲網絡服務提供的一種機制,網絡兩端要進行通信必須先有Socket,網絡通信其實就是Socket間的通信,數據在兩個Socket間通過io傳輸

5 UDP傳輸
(1)UDP分爲發送端和接收端
(2)UDP發送端編程思想
1、定義一個Socket服務,用DatagramSocket
2、將數據(數據包括數據,數據大小,地址以及端口)封包,用DatagramPacket
3、通過端點將包發送出去,用send(DatagramPacket)方法
4、關閉資源
代碼如下:

代碼如下:
import java.net.*;
//發送端
class  SendDemo
{
	public static void main(String[] args) throws Exception
	{
		//定義Socket服務
		DatagramSocket ds=new DatagramSocket();
		//將數據封包
		byte[] buf="發送端發送數據".getBytes();
		DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.100"),10086);
		//通過Socket服務發送數據包
		ds.send(dp);
		//關閉資源
		ds.close();
	}
}

(3)UDP接收端編程思想
1、定義一個Socket服務,並監聽一個端口(如果沒有,系統會分配一個,但可能接收不到數據),用DatagramSocket類
2、定義一個數據包用於存儲接收到的數據包,用DatagramPacket類
3、用Socket服務的receive(DatagramSocket)方法將接收到的數據包存到定義的數據包中
4、通過數據包特有的方法對數據進行解析
5、關閉資源
代碼如下:

import java.net.*;
//接收端
class ReceiveDemo
{
	public static void main(String[] args)throws Exception
	{
		//定義一個Socket服務,並監聽一個端口
		DatagramSocket ds=new DatagramSocket(10086);
		//定義一個數據包存儲接收到的數據包
		byte[] buf=new byte[1024];
		DatagramPacket dp=new DatagramPacket(buf,buf.length);
		//接收數據並存到數據包中
		ds.receive(dp);
		//解析數據
		String ip=dp.getAddress().getHostAddress();
		int port=dp.getPort();
		String data=new String(dp.getData(),0,dp.getLength());
		System.out.println(ip+"::"+port+"::"+data);
		//關閉資源
		ds.close();
	}
}

(4)練習:編寫一個聊天工具,運用多線程一個負責發一個負責收。
代碼:

import java.io.*;
import java.net.*;
//定義一個線程負責發送端
class Send implements Runnable
{
	private DatagramSocket ds;
	Send(DatagramSocket ds)
	{
		this.ds=ds;
	}
	public void run()
	{
		try
		{
			//獲取鍵盤錄入
			BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
			String line=null;
			//讀取鍵盤錄入
			while ((line=bufr.readLine())!=null)
			{
				//判斷鍵盤錄入結束標誌
				if("over".equals(line))
					break;
				byte[] buf=line.getBytes();
				//將數據封包併發送
				DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.100"),10081);
				ds.send(dp);
			}
			bufr.close();
			ds.close();
		}
		catch (Exception e)
		{
			throw new RuntimeException("發送失敗");
		}
	}
}
//定義一個線程負責接收端
class Receive implements Runnable
{
	private DatagramSocket ds;
	Receive(DatagramSocket ds)
	{
		this.ds=ds;
	}
	public void run()
	{
		try
		{
			while(true)
			{
				//定義一個數據包用於存儲發送端發送的數據
				byte[] buf=new byte[1024];
				DatagramPacket dp=new DatagramPacket(buf,buf.length);
				//接收數據
				ds.receive(dp);
				//通過數據包獲取發送端主機和數據
				String ip=dp.getAddress().getHostAddress();
				String data=new String(dp.getData(),0,dp.getLength());
				System.out.println(ip+":"+data);
			}
		}
		catch (Exception e)
		{
			throw new RuntimeException("接收失敗");
		}
	}
}

class  UdpDemo
{
	public static void main(String[] args) throws Exception
	{
		//創建發送端線程和接收端線程並執行
		new Thread(new Send(new DatagramSocket())).start();
		new Thread(new Receive(new DatagramSocket(10081))).start();
	}
}

6 TCP傳輸
(1)TCP分爲客戶端和服務端
(2)客戶端編程思想(客戶端定義的是Socket對象)
1、定義Socket服務,並指定服務端地址和端口,通過Socket類
2、通過getOutputStream()方法獲取Socket對象的輸出流發送數據
3、通過getInputStream()方法獲取Socket對象的輸入流讀取服務端發送的數據
4、關閉資源
代碼:

import java.io.*;
import java.net.*;
//客戶端
class TcpClient 
{
	public static void main(String[] args) throws Exception
	{
		//定義Socket服務,並指定發送的主機和端口。通過Socket對象
		Socket s=new Socket("192.168.1.100",10009);
		//獲取輸出流向服務端發送數據
		OutputStream out=s.getOutputStream();
		out.write("服務端,收到回覆".getBytes());
		//獲取輸入流讀取服務端發送的數據
		InputStream in=s.getInputStream();
		byte[] buf=new byte[1024];
		int len=in.read(buf);
		System.out.println(new String(buf,0,len));
		//關閉資源
		s.close();
	}
}

(3)服務端編程思想
1、定義服務端的Socket服務,並監聽一個端口,通過ServerSocket類
2、通過accept()方法獲取客戶端Socket對象
3、通過客戶端Socket對象的getInputStream()方法獲取輸入流讀取客戶端發送的數據
4、通過客戶端Socket對象的getOutputStream()方法獲取輸出流向客戶端發送數據
5、關閉資源(可以不關)
代碼:

import java.io.*;
import java.net.*;
//服務端
class TcpServer
{
	public static void main(String[] args)throws Exception
	{
		//定義Socket服務並監聽一個端口。通過ServerSocket對象
		ServerSocket ss=new ServerSocket(10009);
		//接收客戶端Socket對象
		Socket s=ss.accept();
		String ip=s.getInetAddress().getHostAddress();
		System.out.println(ip+"...連接");
		//通過Socket對象獲取輸入流讀取客戶端發送的數據
		InputStream in=s.getInputStream();
		byte[] buf=new byte[1024];
		int len=in.read(buf);
		System.out.println(new String(buf,0,len));
		//通過Socket對象獲取輸出流向客戶端發送數據
		OutputStream out=s.getOutputStream();
		out.write("服務端收到".getBytes());
		//關閉資源
		s.close();
		ss.close();
	}
}

(4)練習:客戶端併發登陸服務端。客戶端最多隻能輸入三次,如果都沒登陸成功則程序結束。
代碼:

import java.io.*;
import java.net.*;
//客戶端
class Client1 
{
	public static void main(String[] args) throws Exception
	{
		//創建Socket服務,並指定主機和端口
		Socket s=new Socket("192.168.1.100",10000);
		//獲取鍵盤錄入
		BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
		//獲取Socket對象輸出流將數據發送給服務端
		PrintWriter out=new PrintWriter(s.getOutputStream(),true);
		//獲取Socket對象輸入流讀取服務端發送的數據
		BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream()));
		//只能輸入3次
		for (int x=0;x<3;x++)
		{
			//讀取鍵盤錄入的數據併發送到服務端去
			String line=bufr.readLine();
			if(line==null)
				break;
			out.println(line);
			//讀取服務端發送的數據
			String info=in.readLine();
			System.out.println(info);
			//如果提示信息包含歡迎兩字就不校驗了
			if(info.contains("歡迎"))
				break;
		}
		s.close();
	}
}
//服務端
class Server1
{
	public static void main(String[] args)throws Exception
	{
		//創建服務端Socket服務
		ServerSocket ss=new ServerSocket(10000);
		while (true)
		{
			//獲取客戶端Socket對象
			Socket s=ss.accept();
			//客戶端創建線程並執行
			new Thread(new ClientThread(s)).start();
		}
		
	}
}
//客戶端線程
class ClientThread implements Runnable
{
	private Socket s;
	ClientThread(Socket s)
	{
		this.s=s;
	}
	public void run()
	{
		try
		{
			//獲取Socket對象的輸入流讀取客戶端發送的數據
			BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream()));
			//獲取字符輸入流讀取文本數據
			BufferedReader bufr=new BufferedReader(new FileReader("User.txt"));
			//獲取Socket對象的輸出流向客戶端發送數據
			PrintWriter out=new PrintWriter(s.getOutputStream(),true);
			//只校驗三次
			for (int x=0;x<3;x++)
			{
				//讀取客戶端發送的數據
				String str=in.readLine();
				if(str==null)
					break;
				//讀取文本數據
				String line=null;
				boolean flag=false;//定義一個標記
				while ((line=bufr.readLine())!=null)
				{
					//判斷客戶端發送的數據是否跟文件中讀取到的數據一樣
					if (line.equals(str))
					{
						//相同的話就改變標記
						flag=true;
						break;
					}
				}
				//判斷標記給客戶端提示
				if(flag)
				{
					System.out.println("用戶已登錄");
					out.println("歡迎光臨");
					break;
				}
				else
				{
					System.out.println("用戶嘗試登陸");
					out.println("用戶不存在,請重新輸入");
				}
					
			}
			s.close();
			bufr.close();
		}
		catch (Exception e)
		{
			throw new RuntimeException("服務端失敗");
		}
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章