Java順序設計學習筆記(六) — 網絡編程。本站提示廣大學習愛好者:(Java順序設計學習筆記(六) — 網絡編程)文章只能為提供參考,不一定能成為您想要的結果。以下是Java順序設計學習筆記(六) — 網絡編程正文
時間:2016-5-8 02:03
——網絡編程
網絡傳輸實踐上就是停止數據傳輸。
一、傳輸的步驟:
1、對對方IP地址停止定位。
2、將數據打包發送到對方指定的使用順序上,為了無效的標識這些使用順序,就給這些網絡使用順序運用數字停止標識。
這些數字就叫做端口(號),該端口並不是物理上的端口,而是邏輯上的端口。
端口號范圍:0 ~ 65535,通常狀況下,0 ~ 1024號端口被零碎所保存了。
Web端口:80 Tomcat服務器:8080 MySQL:3306
3、定義通訊規則,這個通訊規則稱為協議。
為了標准規范,國際規范化組織就定義了一個通訊協議:TCP/IP協議。
還有常用協議:UDP協議。
127.0.0.1:本地回環地址,假如電腦沒有配置任何IP地址的狀況下,默許就是該地址,可以用來測試網卡。
二、網絡模型
OSI參考模型
開放零碎互連參考模型 (Open System Interconnect 簡稱OSI),為開放式互連信息零碎提供了一種功用構造的框架。
它從低到高辨別是:物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層和使用層。
網絡編程操作的就是網絡層和傳輸層。
網絡層和傳輸層的協議是TCP/IP協議。
Web開發操作的是使用層。
使用層協議是HTTP協議,還有FTP協議。
TCP/IP參考模型
三、網絡通訊要素
IP地址
網絡中設備的標識。
不易記憶,可用於主機名。
本地回環地址:127.0.0.1 主機名:localhost
播送地址:192.168.1.255 當發送數據時沒有找到指定IP地址,就會將數據發送到播送地址。
net包中用於描繪IP地址的類是:InetAddress類,該類無結構辦法,但是卻有非靜態辦法,可以猜想該類運用了單例設計形式。
InetAddress可以經過getLocalHost()來獲取本類對象。
四、端口號
用於標識進程的邏輯地址,不同進程的標識不同。
無效端口:0 ~ 65535,其中0 ~ 1024 由零碎運用或是保存端口。
五、傳輸協議
通訊的規則。
罕見的傳輸協議:TCP/IP協議,UDP協議。
——Socket(網絡使用順序)
網絡編程其實就是Socket編程。
Socket就是為網絡服務提供的一種機制。
通訊的兩端都有Socket。
網絡通訊其實就是Socket間的通訊。
數據在兩個Socket之間經過IO傳輸。
——TCP
TCP(Transmission Control Protocol 傳輸控制協議)是一種面向銜接的、牢靠的、基於字節流的傳輸層通訊協議。
樹立銜接,構成傳輸數據的通道。
在銜接中停止大數據量傳輸。
經過三次握手完成銜接,是牢靠協議。
必需樹立銜接,效率會稍低。
——UDP
UDP 是User Datagram Protocol的簡稱, 中文名是用戶數據報協議。
是一種無銜接的傳輸層協議,提供面向事務的復雜不牢靠信息傳送服務,也就是不論對方能不能接納,只擔任發送數據。
將數據及源和目的封裝在數據包中,不需求樹立銜接。
每個數據包的大小限制在64KB內。
由於無銜接,所以是不牢靠協議。
不需求樹立銜接,速度快。
UDP傳輸:
UDP傳輸特有對象:
DatagramSocket和DatagramPacket
樹立發送端和接納端
樹立數據包
調用Socket的發送接納辦法
封閉Socket
發送端與接納端是兩個獨立運轉的順序。
——留意
每個協議有自己特有的傳輸方式,所以傳輸的對象也不同。
——DatagramSocket
此類表示用來發送和接納數據報包的套接字(Socket、插座)
結構辦法:
DatagramSocket()
結構數據報套接字並將其綁定到本地主機上任何可用端口,也就是隨機指定端口。
DatagramSocket(int port)
創立數據報套接字並將其綁定到本地主機上的指定端口。
DatagramSocket(int port, InetAddress addr)
創立數據報套接字,將其綁定到指定的本地地址。
辦法摘要:
void bind(SocketAddress addr)
將此DatagramSocket綁定到指定的地址和端口。
void close()
封閉銜接。
由於占用端口,所以需求封閉銜接。
void disconnect()
斷開套接字的銜接。
InetAddress getInetAddress()
前往此套接字銜接的地址。
InetAddress getLocalAddress()
前往此套接字綁定的本地地址。
int getLocalPort()
前往此套接字綁定的本地主機上的端口號。
int getPort()
前往此套接字的端口號。
void send(DatagramPacket p)
從此套接字發送數據報包。
由於需求發送的數據十分復雜,所以把數據包封裝成對象。
void receive(DatagramPacket p)
從此套接字接納數據報包。
boolean isBound()
前往此套接字的綁定形態。
boolean isClosed()
前往能否封閉套接字。
boolean isConnectied()
前往套接字的銜接形態。
——DatagramPacket
此類表示數據報包,用來完成無銜接包投遞服務。
每條報文僅依據包中包括的信息從一台機器路由到另一台機器。
結構辦法:
但凡結構辦法參數中帶地址(InetAddress)和端口(port)的,都是用來發送數據的。
DatagramPacket(byte[] buf, int length)
結構DatagramPacket,用來接納長度為length的數據包。
只要這一個結構辦法是用來接納數據的。
DatagramPacket(byte[] buf, int lengt, InetAddress address, int port)
結構DatagramPacket,用來將長度為length的包發送到指定主機上的指定端口號。
辦法摘要:
InetAddress getAddress()
前往某台機器的IP地址。
前往的是將要發送的機器或許是曾經發送到的機器的IP地址。
byte[] getData()
前往緩沖區數據。
int getLength()
前往將要發送或許接納到的數據的長度。
int getPort()
前往某台近程主機的端口號。
void setData(byte[] buf)
為此數據包設置數據緩沖區。
void setLength(int length)
為此數據包設置長度。
void setPort(int port)
為此數據包設置將要發送的近程主機的端口號。
——InetAddress
辦法摘要:
static InetAddress getByName(String host)
在給定主機名的狀況下確定主機的IP地址並取得該地址對象。
假如運用取得的對象來獲取主機名,假如主機名與IP地址在網絡上沒有映射關系的話,無法經過該對象獲取對應IP地址的主機名。
static InetAddress[] getAllByName(String host)
當面對集群式服務器的時分,一個主機名能夠對應多個IP,所以以數組方式接納前往對象。
String getHostAddress()
前往IP地址字符串。(以文本方式表現)
String getHostName()
獲取此IP地址的主機名。
static InetAddress getLocalHost()
前往本地主機。
int hashCode()
前往此IP地址的哈希值。
String toString()
將此IP地址轉換為String。
boolean isReachable(int timeout)
測試能否可以到達該地址。
=============================================================================
模仿一次通訊
發送數據UDPSend
package day01;
import java.io.IOException;
import java.net.*;
/**
* 需求:
* 經過udp傳輸方式,將沒一段文字數據發送出去
* 步驟:
* 1、樹立UDPSocket服務
* 2、提供數據,並將數據封裝到數據包中
* 3、經過Socket服務的發送功用,將數據包發送出去
* 4、封閉資源(網卡)
* @author WYC
*
*/
public class UdpSend {
public static void main(String[] args)
{
try {
//1、創立udp服務,經過DatagramSocket發送數據,假如不指定端口,則零碎會隨機分配一個端口號
DatagramSocket ds = new DatagramSocket(12345);
//2、確定數據,並封裝成數據包
//DatagramPacket(byte[] buf,int length,InetAddress address,int port)
byte[] buf = "udp send...".getBytes();
DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("localhost"),10000);
//3、經過Socket服務,將已有的數據包發送出去,經過send辦法
ds.send(dp);
//4、封閉資源
ds.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
---------------------------------------------------------------------------------------------------------------------------------------------------
接納數據 UDPReceive
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* 需求:定義一個使用順序(Socket),用於接納UDP協議傳輸的數據並處置
*
* 思緒:
* 1、定義UDPSocket服務,在定義服務的同時,通常會監聽一個端口,其實就是給這個專門用於接納數據的網絡使用順序定義一個數字標識,也就是端口號,假如不定義,零碎會分配一個隨機端口號,方便於明白該使用順序可以處置哪些數據。
* 2、定義一個空數據包,用於存儲接納到的數據包,
* 由於數據包對象中有特有功用可以提取數據包中的不同數據信息
* 辦法:void receive(DatagramPacket)
* 為什麼receive需求接納數據包參數呢?
* 由於需求操作原地址、目的地址、源端口、目的端口、數據
* 所以為了方便起見,將一切數據封裝成對象停止接納
* 3、經過Socket服務的receive辦法將接納到的數據存入已定義好的數據包中
* 4、經過數據包對象的特有功用,將這些不同的數據取出,打印到控制台
* 5、封閉資源。
* */
public class UdpRece {
public static void main(String[] args)
{
try {
//1、創立udp的socket服務並指定端口,樹立接納端點,該服務既可以發送又可以接納
DatagramSocket ds = new DatagramSocket(10000);
//2、定義數據包,用於存儲接納到的數據包
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
//3、經過服務的receive辦法將接納到的數據存入數據包中
ds.receive(dp);
//4、經過數據包的辦法獲取其中的數據,包括地址、端口和數據
//由於getAddress()辦法前往的是一個對象,所以需求getHostAddress()來獲取IP地址
String ip = dp.getAddress().getHostAddress();
//由於接納到的數據是一個字節數組,並且不能確定接納到的字節數組長度,所以需求指定長度
String data = new String(dp.getData(),0,dp.getLength());
//獲取端口
int port = dp.getPort();
System.out.println("ip:"+ip+"\ndata:"+data+"\nport:"+port);
ds.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
---------------------------------------------------------------------------------------------------------------------------------------------------------
當開啟UDPReceive之後,執行UDPSend,控制台輸入如下
127.0.0.1...aaa...22222
================================================================================================
運用UDP監聽鍵盤錄入
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UdpSend2 {
public static void main(String[] args) throws Exception {
DatagramSocket ds = new DatagramSocket();
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while((line = bufr.readLine()) != null)
{
if("886".equals(line))
{
break;
}
byte[] buf = line.getBytes();
DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("localhost"),10001);
ds.send(dp);
}
ds.close();
}
}
----------------------------------------------------------------------------------------------------------------------------------------------------
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UdpReceive2 {
public static void main(String[] args) throws Exception
{
DatagramSocket ds = new DatagramSocket(10001);
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);
}
}
}
===========================================================================================
模仿聊天
import java.io.*;
import java.net.*;
/**
* 編寫一個聊天順序
* 需求有接納數據的局部和發送數據的局部
* 這兩局部需求同時執行,那麼就需求多線程技術
* 一個線程控制接納,一個線程控制發送
*
* 由於接納和發送舉措是不分歧的,所以要定義兩個run辦法,
* 而且這兩個辦法要封裝到不同的類中。
* @author WYC
*
*/
public class ChatDemo {
public static void main(String[] args) throws Exception
{
DatagramSocket sendSocket = new DatagramSocket();
DatagramSocket receSocket = new DatagramSocket(10000);
new Thread(new Send(sendSocket)).start();
new Thread(new Receive(receSocket)).start();
}
}
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("886".equals(line))
{
break;
}
byte[] buf = line.getBytes();
DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("localhost"),10000);
ds.send(dp);
}
}
catch (Exception e)
{
System.out.println("發送失敗!");
}
}
}
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);
//首先要知道IP地址,確定數據從哪來的
String ip = dp.getAddress().getHostAddress();
String data = new String(dp.getData(),0,dp.getData().length);
System.out.println(data);
}
}
catch(Exception e)
{
System.out.println("接納失敗!");
}
}
}
==============================================================================================
——TCP傳輸
Socket和ServerSocket
UDP分為發送端和接納端。
TCP分為客戶端和服務器端。
樹立銜接後,經過Socket中的IO流停止數據的傳輸。
異樣,客戶端與服務器端是兩個獨立的使用順序。
——Socket類
此類完成客戶端套接字,套接字是兩台機器間通訊的端點。
結構辦法:
Socket()
創立一個零碎默許類型的SocketImpl創立未綁定任何銜接的套接字。
可以經過Socket類的辦法來指定銜接。
void connect(SocketAddress endpoint)
將此套接字銜接到服務器。
Socket(InetAddress addr, int port)
創立一個流套接字並將其銜接到指定IP地址的指定端口號。
該辦法闡明了Socket一創立就要銜接到指定的服務端。
==========================================================================================
運用TCP樹立一次傳輸
TCP服務端
package tcp;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
*需求:定義端點接納數據並打印在控制台上
*服務端:
*1、樹立服務端的Socket服務,ServerSocket(int port),該對象一樹立就需求綁定端口。
* 或許運用ServerSocket()創立對象先手動指定一個監聽端口。
*2、獲取銜接過去的客戶端對象。
* 經過ServerSocket的Socket accept()完成
* 假如沒有銜接,則這個辦法就要等候銜接,所以這個辦法是阻塞式的辦法。
*3、假如客戶端發送數據,那麼服務端要運用對應的客戶端對象,並獲取到該客戶端對象的輸出流InputStream,
* 運用該輸出流來獲取發送過去的數據,並打印在控制台。
*4、封閉服務端
*
* @author WYC
*
*/
public class TcpServer {
public static void main(String[] args) throws Exception
{
//簡歷服務端的Socket服務,並監聽一個端口
ServerSocket ss = new ServerSocket(10002);
//經過accept辦法獲取銜接過去的客戶端對象。
Socket s = ss.accept();
//獲取IP地址
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip + "...connected");
//獲取客戶端發送過去的數據,那麼要運用客戶端對象的讀取流來讀取數據
//該輸出源不是鍵盤監聽,而是網絡流
InputStream in = s.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
System.out.println(new String(buf,0,len));
//封閉客戶端
s.close();
//封閉服務端
ss.close();
}
}
--------------------------------------------------------------------------------------------------------------------------------------------------
樹立客戶端
package tcp;
import java.io.*;
import java.io.OutputStream;
import java.net.*;
import java.net.UnknownHostException;
/**
* 演示TCP傳輸
*
* 1、TCP分為客戶端和服務端
* 2、客戶端對應的對象是Socket
* 服務端對應的對象是ServerSocket
* @author WYC
*
*/
/*
* 客戶端
* 經過查閱Socket類,發如今該對象樹立時,就可以去銜接指定主機
* 由於TCP是面向銜接的,所以在樹立Socket服務時,
* 就要有服務端存在並銜接成功,構成通路後再在該通道停止數據的傳輸
*
* 步驟:
* 1、創立Socket服務,並制定要銜接的主機和端口。
*/
public class TcpClient {
public static void main(String[] args) throws Exception{
//創立客戶端的Socket服務,制定目的主機和端口
Socket s = new Socket("localhost",10001);
//通路一旦簡歷完成,就會發生一個Socket流
//可以經過過Socket的辦法來獲取輸出流和輸入流
//為了發送數據,應該獲取Socket流中的輸入流
OutputStream out = s.getOutputStream();
//該辦法會將指定數據寫入到輸入流,並隨著網絡發送到對應的主機上。
out.write("tcp---".getBytes());
s.close();
}
}