本文是關于JAVA網(wǎng)絡編程筆試,希望對你有所幫助。
1、網(wǎng)絡編程概述
(1)網(wǎng)絡模型
OSI參考模型
TCP/IP參考模型
(2)網(wǎng)絡通訊要素
IP地址
端口號
傳輸協(xié)議
(3)網(wǎng)絡通訊前提:
**找到對方IP
**數(shù)據(jù)要發(fā)送到指定端口。為了標示不同的應用程序,所以給這些網(wǎng)絡應用程序都用數(shù)字進行標示 。這個表示就叫端口。
**定義通信規(guī)則。這個規(guī)則稱為通信協(xié)議,國際組織定義了通用協(xié)議TCP/IP
(4)計算機網(wǎng)絡:
是指將地理位置不同的具有獨立功能的多臺計算機及其外部設備,
通過通信線路連接起來,在網(wǎng)絡操作系統(tǒng),網(wǎng)絡管理軟件及網(wǎng)絡通信協(xié)議的管理和協(xié)調下,
實現(xiàn)資源共享和信息傳遞的計算機系統(tǒng)。
(5)IP地址:
IP地址 = 網(wǎng)絡號碼+主機地址
A類IP地址:第一段號碼為網(wǎng)絡號碼,剩下的三段號碼為本地計算機的號碼
B類IP地址:前二段號碼為網(wǎng)絡號碼,剩下的二段號碼為本地計算機的號碼
C類IP地址:前三段號碼為網(wǎng)絡號碼,剩下的一段號碼為本地計算機的號碼
特殊地址:
127.0.0.1 回環(huán)地址,可用于測試本機的網(wǎng)絡是否有問題. ping 127.0.0.1
ipconfig:查看本機IP地址
xxx.xxx.xxx.0 網(wǎng)絡地址
xxx.xxx.xxx.255 廣播地址
A類1.0.0.1---127.255.255.25410.X.X.X是私有地址(私有地址就是在互聯(lián)網(wǎng)上不使用,而被用在局域網(wǎng)絡中的地址)(2)127.X.X.X是保留地址,用做循環(huán)測試用的。
B類128.0.0.1---191.255.255.254172.16.0.0---172.31.255.255是私有地址。169.254.X.X是保留地址。
C類192.0.0.1---223.255.255.254192.168.X.X是私有地址
D類224.0.0.1---239.255.255.254
E類240.0.0.1---247.255.255.254
(6)各種網(wǎng)絡分類方式
A:按網(wǎng)絡覆蓋范圍劃分
局域網(wǎng)(幾米至10公里以內(nèi)) 城域網(wǎng)(10~100公里) 廣域網(wǎng)(幾百公里到幾千公里) 國際互聯(lián)網(wǎng)
B:按網(wǎng)絡拓撲結構劃分
總線型網(wǎng)絡 星形網(wǎng)絡 環(huán)型網(wǎng)絡 樹狀網(wǎng)絡 混合型網(wǎng)絡
C:按傳輸介質劃分
有線網(wǎng) 無線網(wǎng)
D:按網(wǎng)絡使用性質劃分
公用網(wǎng) 專用網(wǎng)
(7)虛擬專用網(wǎng)絡(Virtual Private Network ,簡稱VPN)指的是在公用網(wǎng)絡上建立專用網(wǎng)絡的技術。
其之所以稱為虛擬網(wǎng),主要是因為整個VPN網(wǎng)絡的任意兩個節(jié)點之間的連接并沒有傳統(tǒng)專網(wǎng)
所需的端到端的物理鏈路,而是架構在公用網(wǎng)絡服務商所提供的網(wǎng)絡平臺,如Internet、
ATM(異步傳輸模式〉、Frame Relay (幀中繼)等之上的邏輯網(wǎng)絡,
用戶數(shù)據(jù)在邏輯鏈路中傳輸。它涵蓋了跨共享網(wǎng)絡或公共網(wǎng)絡的封裝、
加密和身份驗證鏈接的專用網(wǎng)絡的擴展。VPN主要采用了隧道技術、加解密技術、
密鑰管理技術和使用者與設備身份認證技術。
(8)網(wǎng)絡模型:
****OSI模型
應用層
表示層
會話層
傳輸層
網(wǎng)絡層
數(shù)據(jù)連接層
物理層
****TCP/IP模型
應用層
傳輸層
網(wǎng)際層
主機至網(wǎng)絡層
2、TCP和UDP
(1)UDP和TCP的區(qū)別:
UDP
將數(shù)據(jù)及源和目的封裝成數(shù)據(jù)包中,不需要建立連接
每個數(shù)據(jù)報的大小在限制在64k內(nèi)
因無連接,是不可靠協(xié)議
不需要建立連接,速度快
TCP
建立連接,形成傳輸數(shù)據(jù)的通道。
在連接中進行大數(shù)據(jù)量傳輸
通過三次握手完成連接,是可靠協(xié)議
必須建立連接,效率會稍低
注:三次握手:
第一次:我問你在么?
第二次:你回答在。
第三次:我反饋哦我知道你在。
3、Socket(UDP傳輸)
**Socket就是為網(wǎng)絡服務提供的一種機制。
**通信的兩端都有Socket。
**網(wǎng)絡通信其實就是Socket間的通信。
**數(shù)據(jù)在兩個Socket間通過IO傳輸。
**玩Socket主要就是記住流程,代碼查文檔就行
(1)UDP傳輸:DatagramSocket與DatagramPacket
**發(fā)送端:
建立DatagramSocket服務;
提供數(shù)據(jù),并將數(shù)據(jù)封裝到字節(jié)數(shù)組中;
創(chuàng)建DatagramPacket數(shù)據(jù)包,并把數(shù)據(jù)封裝到包中,同時指定IP和接收端口
通過Socket服務,利用send方法將數(shù)據(jù)包發(fā)送出去;
關閉DatagramSocket和DatagramPacket服務。
**接收端:
建立DatagramSocket服務,并監(jiān)聽一個端口;
定義一個字節(jié)數(shù)組和一個數(shù)據(jù)包,同時將數(shù)組封裝進數(shù)據(jù)包;
通過DatagramPacket的receive方法,將接收的數(shù)據(jù)存入定義好的數(shù)據(jù)包;
通過DatagramPacke關閉t的方法,獲取發(fā)送數(shù)據(jù)包中的信息;
關閉DatagramSocket和DatagramPacket服務。
DatagramSocket與DatagramPacket方法摘要:
*****DatagramSocket
構造方法:
DatagramSocket()
構造數(shù)據(jù)報套接字并將其綁定到本地主機上任何可用的端口。
DatagramSocket(intport)
創(chuàng)建數(shù)據(jù)報套接字并將其綁定到本地主機上的指定端口。
DatagramSocket(intport, InetAddress laddr)
創(chuàng)建數(shù)據(jù)報套接字,將其綁定到指定的本地地址。
方法摘要:
voidclose()
關閉此數(shù)據(jù)報套接字。
InetAddressgetInetAddress()
返回此套接字連接的地址。
InetAddressgetLocalAddress()
獲取套接字綁定的本地地址。
intgetPort()
返回此套接字的端口。
voidreceive(DatagramPacket p)
從此套接字接收數(shù)據(jù)報包。
voidsend(DatagramPacket p)
從此套接字發(fā)送數(shù)據(jù)報包。
****DatagramPacket
構造方法:
DatagramPacket(byte[]buf, int length)
構造 DatagramPacket,用來接收長度為 length 的數(shù)據(jù)包。
DatagramPacket(byte[]buf, int length, InetAddress address, int port)
構造數(shù)據(jù)報包,用來將長度為 length 的包發(fā)送到指定主機上的指定端口號。
InetAddressgetAddress()
返回某臺機器的 IP 地址,此數(shù)據(jù)報將要發(fā)往該機器或者是從該機器接收到的。
byte[] getData()
返回數(shù)據(jù)緩沖區(qū)。
intgetLength()
返回將要發(fā)送或接收到的數(shù)據(jù)的長度。
intgetPort()
返回某臺遠程主機的端口號,此數(shù)據(jù)報將要發(fā)往該主機或者是從該主機接收到的。
代碼示例:
****發(fā)送端:
class UDPSend
{
public static void main(String[] args)throws Exception
{
DatagramSocket ds = new DatagramSocket();
byte[] buf = "這是UDP發(fā)送端".getBytes();
DatagramPacket dp = new DatagramPacket(
buf,buf.length,InetAddress.getByName("192.168.1.253"),10000);
ds.send(dp);
ds.close();
}
}
****接收端
class UDPRece
{
public static void main(String[] args)throws Exception
{
DatagramSocket ds = newDatagramSocket(10000);
byte[] buf = new byte[1024];
DatagramPacket dp = newDatagramPacket(buf,buf.length);
ds.receive(dp);//將發(fā)送端發(fā)送的數(shù)據(jù)包接收到接收端的數(shù)據(jù)包中
String ip =dp.getAddress().getHosyAddress();//獲取發(fā)送端的ip
String data = new String(dp.getData(),0,dp.getLength());//獲取數(shù)據(jù)
int port = dp.getPort();//獲取發(fā)送端的端口號
sop(ip+":"+data+":"+port);
ds.close();
}
}
需求1:UDP鍵盤錄入數(shù)據(jù),并發(fā)送給接收端
發(fā)送端:
class UDPSend
{
public static void main(String[] args)throws Exception
{
DatagramSocket ds = new DatagramSocket();
BufferedReader bufr = newBufferedReader(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("192.168.1.253"),10000);
ds.send(dp);
}
ds.close();
}
}
接收端:
class UDPRece
{
public static void main(String[] args)throws Exception
{
DatagramSocket ds = newDatagramSocket(10000);
while(true)
{
byte[] buf = new byte[1024];
DatagramPacket dp = newDatagramPacket(buf,buf.length);
ds.receive(dp);//將發(fā)送端發(fā)送的數(shù)據(jù)包接收到接收端的數(shù)據(jù)包中
String ip =dp.getAddress().getHosyAddress();//獲取發(fā)送端的ip
String data = newString(dp.getData(),0,dp.getLength());//獲取數(shù)據(jù)
int port = dp.getPort();//獲取發(fā)送端的端口號
sop(ip+":"+data+":"+port);
ds.close();
}
}
}
需求2:編寫簡單的聊天工具
思路:
使用多線程技術
發(fā)送端:
class UDPSend implements Runnable
{
private DatagramSocket ds;
public UDPSend(){}
public UDPSend(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[] buff = line.getBytes();
DatagramPacket dp = new DatagramPacket(
buf,buf.length,InetAddress.getByName("192.168.1.253"),10000);
ds.send(dp);
}
}
catch(Exception e)
{
throw new RuntimeException("發(fā)送失敗");
}
}
}
接收端:
class UDPRece implements Runnable
{
private DatagramSocket ds;
public UDPSend(){}
public UDPSend(DatagramSocket ds)
{
this.ds=ds;
}
public void run()
{
try
{
while(true)
{
byte[] buf = new byte[1024];
DatagramPacket dp = newDatagramPacket(buf,buf.length);
ds.receive(dp);//將發(fā)送端發(fā)送的數(shù)據(jù)包接收到接收端的數(shù)據(jù)包中
String ip =dp.getAddress().getHosyAddress();//獲取發(fā)送端的ip
String data = new String(dp.getData(),0,dp.getLength());//獲取數(shù)據(jù)
int port = dp.getPort();//獲取發(fā)送端的端口號
sop(ip+":"+data+":"+port);
}
}
catch(Exception e)
{
throw new RuntimeException("接收失敗");
}
}
}
測試類:
class UDPTest
{
public static void main(String[] args)
{
DatagramSocket sendSocket = new DatagramSocket();
DatagramSocket receSocket = newDatagramSocket(10000);
new Thread(newUDPSend(sendSocket)).start();
new Thread(newUDPRece(receSocket)).start();
}
}
(2)TCP傳輸
Socket和ServerSocket
建立客戶端和服務器端
建立連接后,通過Socket中的IO流進行數(shù)據(jù)的傳輸
關閉socket
同樣,客戶端與服務器端是兩個獨立的應用程序。
****Socket
**構造方法:
Socket()
通過系統(tǒng)默認類型的 SocketImpl 創(chuàng)建未連接套接字
Socket(InetAddressaddress, int port)
創(chuàng)建一個流套接字并將其連接到指定 IP 地址的指定端口號。
Socket(Stringhost, int port)
創(chuàng)建一個流套接字并將其連接到指定主機上的指定端口號。
**方法摘要:
voidclose()
關閉此套接字。
InetAddress getInetAddress()
返回套接字連接的地址。
InputStreamgetInputStream()
返回此套接字的輸入流。
OutputStreamgetOutputStream()
返回此套接字的輸出流。
intgetPort()
返回此套接字連接到的遠程端口。
voidshutdownInput()
此套接字的輸入流置于“流的末尾”。
voidshutdownOutput()
禁用此套接字的輸出流。
StringtoString()
將此套接字轉換為 String。
****ServerSocket
**構造方法:
ServerSocket()
創(chuàng)建非綁定服務器套接字。
ServerSocket(intport)
創(chuàng)建綁定到特定端口的服務器套接字。
方法摘要:
Socketaccept()
偵聽并接受到此套接字的連接。
voidclose()
關閉此套接字。
InetAddressgetInetAddress()
返回此服務器套接字的本地地址。
****TCP傳輸流程:
**客戶端:
建立Socket服務,并制定要連接的主機和端口;
獲取Socket流中的輸出流OutputStream,將數(shù)據(jù)寫入流中,通過網(wǎng)絡發(fā)送給服務端;
獲取Socket流中的輸出流InputStream,獲取服務端的反饋信息;
關閉資源。
**服務端:
建立ServerSocket服務,并監(jiān)聽一個端口;
通過ServerSocket服務的accept方法,獲取Socket服務對象;
使用客戶端對象的讀取流獲取客戶端發(fā)送過來的數(shù)據(jù);
通過客戶端對象的寫入流反饋信息給客戶端;
關閉資源;
****代碼示例:
客戶端:
class TCPClient
{
public static void main(String[] args)
{
Socket s = newSocket("192.168.1.253",10000);
OutputStream os = s.getOutputStream();
out.write("這是TCP發(fā)送的數(shù)據(jù)".getBytes());
s.close();
}
}
服務端:
class TCPServer
{
public static void main(String[] args)
{
ServerSocket ss = new ServerSocket(10000);
Socket s = ss.accept();
String ip =s.getInetAddress().getHostAddress();
sop(ip);
InputStream is = s.getInputStream();
byte[] buf = new byte[1024];
int len = is.read(buf);
sop(new String(buf,0,len));
s.close();
ss.close();
}
}
TCP需求1:客戶端給服務端發(fā)送數(shù)據(jù),服務端接收到后反饋信息給客戶端
客戶端:
class TCPClient
{
public static void main(String[] args)
{
Socket s = newSocket("192.168.1.253",10000);
OutputStream os = s.getOutputStream();
out.write("這是TCP發(fā)送的數(shù)據(jù)".getBytes());
InputStream is = s.getInputStream();
byte[] buf = new byte[1024];
int len = is.read(buf);
sop(new String(buf,0,len));
s.close();
}
}
服務端:
class TCPServer
{
public static void main(String[] args)
{
ServerSocket ss = new ServerSocket(10000);
Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress();
sop(ip);
InputStream is = s.getInputStream();
byte[] buf = new byte[1024];
int len = is.read(buf);
sop(new String(buf,0,len));
OutputStream os = s.getOutputStream();
out.write("這是TCP發(fā)送的數(shù)據(jù)".getBytes());
s.close();
ss.close();
}
}
TCP需求2:建立一個文本轉換服務端,客戶給服務端發(fā)送文本,服務端將數(shù)據(jù)轉換成大寫后返回給客戶端
當客戶端輸入over時,轉換結束
客戶端:
class TCPClient
{
public static void main(String[] args)
{
Socket s = newSocket("192.168.1.253",10000);
BufferedReader bufr = newBufferedReader(new InputStreamReader(System.in));
BufferedWriter bufOut = newBufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
BufferedReader bufIn = newBufferedReader(new InputStreamReader(
s.getInputStream()));
String line = null;
while((line = bufr.readLine())!=null)
{
if("over".equals(line))
break;
bufOut.write(line);
bufOut.newLine();
bufOut.flush();
String retVal = bufIn.readLine();
sop("server:"+retVal);
}
bufr.close();
s.close();
}
}
服務端:
class TCPServer
{
public static void main(String[] args)
{
ServerSocket ss = new ServerSocket(10000);
Socket s = ss.accept();
String ip =s.getInetAddress().getHostAddress();
sop(ip);
BufferedReader bufIn = newBufferedReader(new InputStreamReader(
s.getInputStream()));
BufferedWriter bufOut = newBufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
while((line = bufIn.readLine())!=null)
{
bufOut.write(line.toUpperCase());
bufOut.newLine();
bufOut.flush();
}
s.close();
ss.close();
}
}
**需求3:拷貝文件
客戶端:
class TCPClient
{
public static void main(String[] args)
{
Socket s = new Socket("192.168.1.253",10000);
BufferedReader bufr = newBufferedReader(new FileReader("g:\\demo.txt"));
PrintWriter pw = newPrintWriter(s.getOutputStream(),true);
String line = null;
while((line = bufr.readLine())!=null)
{
pw.println();
}
s.shutDownOutput();
BufferedReader bufIn = newBufferedReader(new InputStreamReader(
s.getInputStream()));
String retVal = bufIn.readLine();
sop(retVal);
bufr.close();
s.close();
}
}
服務端:
class TCPServer
{
public static void main(String[] args)
{
ServerSocket ss = new ServerSocket(10000);
Socket s = ss.accept();
String ip =s.getInetAddress().getHostAddress();
sop(ip);
BufferedReader bufIn = newBufferedReader(new InputStreamReader(
s.getInputStream()));
PrintWriter out = new PrintWriter(newFileWriter"copy.txt",true);
String line =null;
while((line = bufIn.readLine())!=null)
{
out.write(line);
}
PrintWriter pw = newPrintWriter(s.getOutputStream(),true);
pw.println("上傳成功");
out.close();
s.close();
ss.close();
}
}
需求4:上傳圖片
客戶端:
class TCPClient
{
public static void main(String[] args)
{
Socket s = newSocket("192.168.1.253",10000);
FileInputStream fis = newFileInputStream("g:\\1.bmp");
OutputStream out = s.getOutputStream();
byte[] buf = new byte[1024];
int len = 0;
while((len = bufr.read())!=-1)
{
out.write(buf,0,len);
}
s.shutDownOutput();
InputStream in = s.getInputStream();
byte[] bufIn = new byte[1024];
int lenIn = in.read(bufIn);
sop(new String(bufIn,0,lenIn);
fis.close();
s.close();
}
}
服務端:
class TCPServer
{
public static void main(String[] args)
{
ServerSocket ss = new ServerSocket(10000);
Socket s = ss.accept();
String ip =s.getInetAddress().getHostAddress();
sop(ip);
FileOutputStream fos = newFileOutputStream("g:\\copy.bmp");
InputStream in = s.getInputStream();
byte[] bufIn = new byte[1024];
int lenIn = 0;
while((lenIn=bufIn.read())!=-1)
{
fos.write(bufIn,0,lenIn)
}
OutputStream outIn = s.getOutputStream();
outIn.write("上傳成功".getBytes());
fos.close();
s.close();
ss.close();
}
}
需求5:客戶端并發(fā)登陸
客戶端通過鍵盤錄入用戶名,服務端對這個用戶名進行校驗
如果用戶存在,在服務端現(xiàn)實xxx已登錄,并在客戶端現(xiàn)實歡迎xxx
如果用戶不存在,在服務端現(xiàn)實xxx正在嘗試登陸,并在客戶端現(xiàn)實xxx用戶不存在
最多登陸三次。
校驗端:
class User implements Runnable
(
private Socket s;
public User(){}
public User(Socket s)
{
this.s=s;
}
public void run()
{
try
{
BufferedReader bufrIn = new BufferedReader(
new InputStream(s.getInputStream()))
String name = bufrIn.readLine();
if(name==null)
{
sop("用戶名為空");
break;
}
BufferedReader bufr = new BufferedReader(
new FileReader("user.txt"));
PrintWriter pw = newPrintWriter(s.getOutputStream(),true);
String line = null;
boolean flag = false;
while((line = bufr.reanLine())!=null)
{
if(line.equals(name))
{
flag = true;
break;
}
if(flag)
{
sop(name+"已登陸");
pw.println("歡迎"+name);
break;
}
else
{
sop(name+"正嘗試登陸");
pw.println(name+"用戶不存在");
}
}
s.close();
}
catch(Exception e)
{
throw new RuntimeException("用戶校驗失敗");
}
}
)
客戶端:
class LoginClient
{
public static void main(String[] args)
{
Socket s = newSocket("192.168.1.253",10000);
BufferedReader bufr = new BufferedReader(
new InputStreamReader(System.in)));
PrintWriter out = newPrintWriter(s.getOutputStream(),true);
BufferedReader bufIn = new BufferedReader(
new InputStreamReader(s.getInputStream()));
for(int i=0;i<3;i++)
{
String line = bufr.readLine();
if(line == null)
{
sop("用戶名不能為空!");
break;
}
out.write(line);
String retVal = bufIn.readLine();
sop(retVal);
}
bufr.close();
s.close();
}
}
服務端:
class LoginServer
{
public static void main(String[] args)
{
ServerSocket ss = new ServerSocket(10000);
while(true)
{
Socket s = ss.accept();
new Thread(new User()).start();
}
}
}