IP地址劃分網段
網絡模型
OSI參考模型
TCP/IP參考模型
URL與URI的區別
網絡通訊要素
IP地址: InetAddress
以計算機名稱爲參數得到InetAddress,需要一個解析的過程。
端口號:有效端口0~65535,其中0~1024系統使用或保留端口
傳輸協議:TCP、UDP
UDP傳輸:
面向無連接的,發數據前不需要建立連接,是不可靠的協議,每個數據包的大小限制在64k以內。速度快
用途:聊天軟件,網絡視頻。類似生活中的郵局郵寄信件;
TCP傳輸:
面向連接的可靠協議,通過三次握手建立連接,在連接中進行大數據量傳輸
缺點:建立連接耗時
應用:下載軟件。類似生活中的打電話
Socket通信
網絡通信兩端都有Socket,網絡通信就是Socket之間的通信
- UDP的Socket服務:廣播,同一個網段?
發送端和接收端都是DatagramSocket對象
/*發送端*/
public class UdpSend
{
public static void main(String[]
args) throws Exception
{
// 1. 創建udp服務
DatagramSocket ds = new DatagramSocket();
BufferedReader bufr = new BufferedReader(new InputStreamReader(
System. in));
// 2. 確定數據,並封裝成數據報
String line = null;
while ((line
= bufr.readLine()) != null)
{
if (line.equals("88" ))
break;
byte[]
buf = line.getBytes();
DatagramPacket dp = new DatagramPacket(buf,
buf.length, InetAddress
. getByName("192.168.1.255"),
10000); // 255是廣播
// 3.通過socket服務,將已有的數據包發送出去
ds.send(dp);
}
// 4.關閉資源
ds.close();
}
}
/* 接收端
* 1. 創建一個UDP Socket服務,定義一個端口,其實就是給這個接收網絡應用程序定義一個數字標識,
* 方便明確哪些數據過來該應用程序可以處理
* 2. 定義一個數據包,因爲要存儲接收到的字節數據,因爲數據包對象中有更多的功能可以提取字節數據中的不同數據信息
* 3. 通過socket服務的receive方法將受到的數據存入已定義好的數據包中
* 4. 通過數據包對象的特有功能,將這些不同的數據取出,打印到控制檯上
* 5. 關閉資源
* */
public class UdpReceive
{
public static void main(String[]
args) throws Exception
{
// 1. 創建UDP Socket
DatagramSocket ds = new DatagramSocket(10000);
// 2. 定義數據包,用於存儲數據
while (true )
{
byte[]
buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,
buf.length);
// 3.通過Socket服務的receive方法將受到的數據存入數據包中
ds.receive(dp);//
注意:這是一個阻塞方法
// 4. 通過數據包的方法獲取其中的數據
String ip = dp.getAddress().getHostAddress();
String data = new String(dp.getData(),
0, dp.getLength());
int port
= dp.getPort();
System. out.println(ip
+ ":" + data + ":" +
port);
}
// 5. 關閉資源
//ds.close();
}
}
- TCP的Socket服務
客戶端是Socket,服務端是ServerSocket
ServerSocket(int port , int backlog) backlog表示允許連接的最大客戶端數
----------------------------------------------------------------------------------------
例1:鍵盤輸入信息發送到服務端
----------------------------------------------------------------------------------------
/*
* 客戶端
* 功能:鍵盤輸入發送信息到服務端
* 1. IO流使用BufferedReader/PrintWriter
* 2. PrintWriter構造函數的第二個參數是true時,對象的pintln()方法自動flush緩存
* 3. 如果使用BufferedWriter作爲輸出流,則必須額外加上newLine()和flush()操作
* */
public class TCPClient1
{
public static void main(String[]
args) throws Exception
{
Socket client = new Socket("localhost" ,
10001);
// 鍵盤輸入流
BufferedReader bufr = new BufferedReader(new InputStreamReader(
System. in));
// socket 輸出流 方式1
BufferedWriter bufOut = new BufferedWriter( new OutputStreamWriter(
client.getOutputStream()));
// socket 輸入流
BufferedReader bufin = new BufferedReader(new InputStreamReader(client
.getInputStream()));
// socket 輸出流 方式2
PrintWriter out = new PrintWriter(client.getOutputStream(), true);//true表示調用 println()方法時會自動flush
String line = null;
while ((line
= bufr.readLine()) != null)
{
if ("88" .equals(line))
break;
// bufOut.write(line);
// 服務器端用readLine()方法讀取數據時是以回車換行爲結尾的,所以這裏發送數據時,需要發一個回車換行
// bufOut.newLine();
// bufOut.flush();
out.println(line);
String serverReturn = bufin.readLine();
System. out.println(serverReturn);
}
bufr.close();
client.close();
}
}
/*
* 服務端
* */
public class TCPServer1
{
public static void main(String[]
args) throws Exception
{
ServerSocket ss = new ServerSocket(10001);
Socket client = ss.accept();
// socket 輸入流
BufferedReader bufIn = new BufferedReader(new InputStreamReader(client
.getInputStream()));
// socket 輸出流 方式1
BufferedWriter bufOut = new BufferedWriter( new OutputStreamWriter(
client.getOutputStream()));
// socket 輸出流 方式2
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
String line = null;
while ((line
= bufIn.readLine()) != null)
{
// 注意:readLine方法接收到回車換行纔會返回,所以,客戶端發送數據時需要out.newLine()
System. out.println(line);
// bufOut.write(line.toUpperCase());
// bufOut.newLine();
// bufOut.flush();
out.println(line.toUpperCase());
}
client.close();
ss.close();
}
}
-----------------------------------------------------------------------------------------------
例2 文本文件傳輸
-----------------------------------------------------------------------------------------------
/*
* 客戶端
* 功能: 文本文件傳輸
* 1. 文本文件傳輸用BufferedReader/PrintWriter
* 2. 文件傳送結束後,要顯示告知服務端傳遞結束,即s.shutdownOutput()
* */
public class FileClient
{
public static void main(String[]
args) throws Exception,
IOException {
Socket s = new Socket("localhost" ,
10001);
BufferedReader bufr = new BufferedReader(new FileReader(
"FileServer.java"));
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
String line = null;
while ((line
= bufr.readLine()) != null)
{
out.println(line);
}
s.shutdownOutput(); //
關閉客戶端輸出流,相當於在流中加入結束標記 -1
BufferedReader bufIn = new BufferedReader(new InputStreamReader(s
.getInputStream()));
String serverResult = bufIn.readLine();
System. out.println(serverResult);
s.close();
}
}
* 1. 文本文件的IO操作使用BufferedReader/PrintWriter
public class FileServer
{
public static void main(String[]
args) throws Exception
{
ServerSocket ss = new ServerSocket(10001);
Socket client = ss.accept();
BufferedReader bufIn = new BufferedReader(new InputStreamReader(client
.getInputStream()));
System. out.println("ip:" +client.getInetAddress().getHostAddress());
PrintWriter pw = new PrintWriter(new FileWriter("save.txt"), true);
String line = null;
while ((line
= bufIn.readLine()) != null)
{
System. out.println(line);
pw.println(line);
}
PrintWriter out = new PrintWriter(client.getOutputStream());
out.println( "上傳成功" );
out.close();
pw.close();
client.close();
ss.close();
}
}
-------------------------------------------------
例3 服務端併發接收圖片文件上傳
-------------------------------------------------
public class ConcurrentPicClient
{
public static void main(String[]
args) throws Exception
{
Socket s = new Socket("localhost" ,
10001);
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
//讀文件
FileInputStream is = new FileInputStream(new File("test.gif" ));
byte[]
buf = new byte[1024];
int len
= 0;
while ((len
= is.read(buf)) != -1) {
out.write(buf, 0, len);
}
s.shutdownOutput(); //
標記文件傳遞結束
len = in.read(buf);
System. out.println(new String(buf,
0, len));
is.close();
s.close();
}
}
/*
* 服務端
* 功能:併發接收圖片上傳
* 圖片文件使用Stream進行讀寫,不適用Reader/Writer
* */
public class ConcurrentServer
{
public static void main(String[]
args) throws Exception
{
ServerSocket ss = new ServerSocket(10001);
while (true )
{
new Thread(new ServerThread(ss.accept())).start();
}
}
}
class ServerThread implements Runnable
{
private Socket s ;
public ServerThread(Socket
s) {
this.s =
s;
}
public void run()
{
int count
= 1;
String ip = s.getInetAddress().getHostAddress();
System. out.println(ip
+ "...connected" );
try {
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
// 保證file不重名
File file = new File(ip
+ "(" + count + ").jpg");
while (file.exists())
{
count++;
file = new File(ip
+ "(" + count + ").jpg");
}
// 寫文件
FileOutputStream fo = new FileOutputStream(file);
byte[]
buf = new byte[1024];
int len
= 0;
while ((len
= in.read(buf)) != -1) {
fo.write(buf, 0, len);
}
out.write( "上傳成功" .getBytes());
fo.close();
s.close();
} catch (Exception
e) {
}
}
}