一、網絡模型
OSI模型(七層):物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層、應用層。
TCP/IP模型(四層):物理層、網際層(IP)、傳輸層(TCP、UDP協議)、應用層(HTTP、FTP協議)。
二、網絡通訊三要素
1、IP地址:網絡中設備的唯一標識,java中描述IP的類是:InetAddreess。獲取本機的主機:InetAddress i = InetAddress.getLoclHost();獲取任一主機:InetAddress i = InetAddress.getByName(“192.168.2.56”);
2、端口:端口是用4爲數字表示的。常用的端口:SVN-3690,Tomacat-8080,Apache-80,mySQL-3306。
3、傳輸協議:常用的是TCP和UDP。
三、TCP、UDP
(一)、UDP
1、UDP的特點:面向無連接,數據要封包,且不能大於64k,因爲無連接,所以不可靠,但是效率快。使用UDP協議傳輸的應用程序:QQ、桌面共享、網絡會議等。
2、UDP傳輸:建立發送端、接收端,將數據打包,從發送端用send方法將數據包發送出去,接收端通過reveive方法將數據包接收到已定義好的數據包中,並用數據包的方法解析數據。關閉Socket服務。發送端和接收端是兩個獨立的運行程序。相關的類:DatagramSocket、DatagramPacket。
3、建立UDP發送端服務的步驟:
(1)、用DatagramSocket建立發送端Socket服務;
(2)、確定要發送的數據,並用DatagramPacket將數據打包;
(3)、用DatagramSocket裏的send方法將數據包發送出去;
(4)、關閉Socket服務。
4、建立UDP接收端服務的步驟:
(1)、用DatagramSocket建立接收端的Socket服務;
(2)、用DatagramPacket創建一個數據包;
(3)、用DatagramSocket中的receive方法接收數據包,並將數據包存放在已定義好的數據包中。
(4)、用DatagramPacket方法解析數據;
(5)、關閉接收端Socket服務。
5、模擬聊天功能
/*
聊天功能模擬。
分析:
聊天,既能發送信息,也能接收信息,兩者同時進行,所以該用兩個線程來實現;
步驟:
1、描述發送端,並實現Runnable接口;
2、複寫run方法。
3、用Thread建立線程;
4、將Runnable的子類對象傳遞給Thread的構造函數;
其他說明:
接收端沒接收端消息,先看看消息是否發送出去了。
*/
import java.net.*;
import java.io.*;
//建立發送端
class ChatSend implements Runnable
{
private DatagramSocket ds;
ChatSend(DatagramSocket ds)
{
this.ds = ds;
}
public void run()
{
BufferedReader bufr = null;
DatagramPacket dp = null;
try
{
//獲取鍵盤錄入對象
bufr = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while((line = bufr.readLine()) != null)
{
//信息是以字節形式發送,所以需要將字符轉字節
byte[] buf = line.getBytes();
//將數據打包
dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.75.1"),8887);
//將數據包發送出去
ds.send(dp);
//判斷聊天結束標誌
if(line.equals("goodbye"))
{
//System.out.println(line+"聊天結束!");
break;
}
}
}
catch (IOException e)
{
throw new RuntimeException("發送數據失敗!");
}
finally
{
if(bufr != null)
{
try
{
bufr.close();
}
catch (IOException ie)
{
}
}
}
}
}
//建立接收端
class ChatReceive implements Runnable
{
private DatagramSocket ds;
ChatReceive(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());
//判斷髮送端是否結束聊天
if(data.equals("goodbye"))
{
System.out.println("發送端結束聊天!");
break;
}
System.out.println(ip+"---"+data);
}
}
catch (IOException e)
{
throw new RuntimeException("數據接收失敗!");
}
}
}
class ChatTest
{
public static void main(String[] args)
{
try
{
//用Tread建立線程,開啓並執行進程
new Thread(new ChatSend(new DatagramSocket())).start();
new Thread(new ChatReceive(new DatagramSocket(8887))).start();
}
catch (IOException e)
{
throw new RuntimeException("建立聊天失敗!");
}
}
}
(二)、TCP
1、TCP的特點:面向連接,兩者之間建立通訊通道,可在通道中進行大數據傳輸,安全可靠,但效率稍低。比如:下載。
2、TCP傳輸:建立客戶端,並與服務器端建立連接,獲取客戶端的輸出流將數據發生到服務器端,服務器端通過獲取連接到該服務器上的客戶端的讀取流,獲取客戶端發送過來的信息,並用獲取到的客戶端的輸出流將客戶端需要的數據反饋給客戶端。涉及的類:客戶端:Socket,服務器端:ServerSocket。
3、建立客戶端的步驟:
(1)、通過Socket建立客戶端服務,並指定要連接的主機和端口;
(2)、獲取輸出流;
(3)、用輸出流將數據傳送到服務器;
(4)、關閉Socket服務;
4、建立服務器端的步驟:
(1)、通過ServerSocket建立服務端服務;
(2)、獲取連接到服務器的客戶端;
(3)、通過獲取到的客戶端的讀取流,讀取客戶端發送過來的信息;
(4)、關閉Socket服務(可選)。
5、模擬併發圖片上傳
/*
客戶端併發上傳照片。
分析:客戶端併發上傳照片,要求服務端可以處理多個客戶端的請求。
主義事項:客戶端端將圖片信息發送結束,需要告訴服務端,數據已經發送結束,
不然服務端在讀取數據時讀取不到結束標誌。
*/
import java.net.*;
import java.io.*;
class TcpPic
{
public static void main(String[] args)
{
Socket s = null;
FileInputStream ips = null;
OutputStream out = null;
InputStream in = null;
try
{
//建立客戶端Socket服務,並指定要連接的主機
s = new Socket("192.168.75.1",10000);
//指定要上傳的圖片
ips = new FileInputStream("ibeacon-01_05.png");
//獲取網絡流中的輸出流,用於向服務端發送數據
out = s.getOutputStream();
byte[] buf = new byte[1024];
int len = 0;
//讀一次硬盤的圖片信息,想服務端發送一次
while((len = ips.read(buf)) != -1)
{
out.write(buf,0,len);
}
//告訴服務端已經上傳完
s.shutdownOutput();
//獲取服務端返回的數據
in = s.getInputStream();
byte[] bt = new byte[1024];
int lenth = in.read(bt);
System.out.println(new String(bt,0,lenth));
s.close();
}
catch (IOException e)
{
throw new RuntimeException("數據發送失敗!");
}
finally
{
if(ips != null)
{
try
{
ips.close();
}
catch (IOException ie)
{
}
}
}
}
}
//定義服務端
class ServerPic implements Runnable
{
private Socket s;
ServerPic(Socket s)
{
this.s = s;
}
public void run()
{
InputStream in = null;
FileOutputStream ops = null;
OutputStream out = null;
try
{
//通過連接到服務端的客戶端對象獲取輸入流
in = s.getInputStream();
//獲取該客戶機的IP
String path = s.getInetAddress().getHostAddress();
int count = 0;
File f = new File(path+"("+count+").png");
//將文件名封裝成File對象,以便判斷文件名是否重複
while(f.exists())
f = new File(path+"("+(count++)+").png");
//獲取將圖片信息寫到硬盤的輸出流
ops = new FileOutputStream(f);
//獲取將信息返回給客戶端的輸出流
out = s.getOutputStream();
byte[] buf = new byte[1024];
int len = 0;
//一邊讀取客戶端發送過來的數據,一邊將數據寫到硬盤中
while((len = in.read(buf)) != -1)
{
ops.write(buf,0,len);
}
//給客戶端返回信息
out.write("上傳成功!".getBytes());
//System.out.println("商城成功");
s.close();
}
catch (IOException e)
{
System.out.println(e.toString());
throw new RuntimeException("圖片接收失敗!");
}
finally
{
if(ops != null)
{
try
{
ops.close();
}
catch (IOException ie)
{
}
}
}
}
}
class TcpPicTest
{
public static void main(String[] args)
{
ServerSocket ss = null;
Socket s = null;
try
{
//建立服務端Socket服務
ss = new ServerSocket(10000);
//獲取連接到該服務端的客戶端,並將其封裝到一個線程中。
while(true)
{
s = ss.accept();
//創建線程,開啓並執行線程代碼
new Thread(new ServerPic(s)).start();
}
}
catch (IOException e)
{
throw new RuntimeException("服務端Socket建立失敗!");
}
}
}