------- 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("服務端失敗");
}
}
}