java學習筆記之網絡編程
網絡編程
一.網絡通信協議
1.網絡協議
不同的操作系統,不同的硬件設備上都能夠聯網,是因為互聯網設計規定了一套標準,這套標準就被稱為網絡協議,網絡協議規定了網絡傳輸的格式,速率和方式;
2.TCP/IP協議
是一組協議:HTTP ,FTP,SMTP,DNS
TCP:傳輸控制協議
IP:互聯網協議
TCP/IP協議的分層:
應用層:上位機應用程序,比如說qq,用來產生數據和顯示數據
傳輸層:端口號 加入一些標誌位,保證數據傳輸的準確性
網絡層:ip地址 用來尋找對方電腦在哪裏
鏈路層:網卡驅動 用來發送或接收數據
3. IP地址:
在一個網絡中ip地址可以唯一標識一臺電腦。
ipv4:xxx.xxx.xxx.xxx 點分十進制 32個二進制位來描述ip:21個億
ipv6:128個二進制位來描述ip:無數個
4.端口號:
就是聯網的每一個應用程序制定一個編號,編號可以唯一標識一個應用程序
1-65535
1-1024:系統使用
1024-6000:系統保留
>6000自己使用
一臺電腦的應用程序想和另一臺電腦的一個程序通信 必須知道ip地址和端口號
二.UDP 和TCP協議
1.udp協議:用戶數據報協議
面向無連接的協議,兩臺電腦在通信之前不需要建立連接,發送端只管發送,不會關心接收端是否已經收到,或者接收端是否存在
優點:數據傳輸速度快,效率高
缺點:數據安全性不高,數據容易丟失;
應用場景:電話會議,視頻直播,網絡會議---->實時性
2.tcp協議:傳輸控制協議
兩臺電腦在通信之前必須建立連接(三次握手),每次發送完數據,都會有一個反饋信息。
優點:數據安全性高,可靠性強
缺點:傳輸數度慢,效率低
應用場景:密碼管理,金融支付,理財系統
三.InetAddress類
1 /* 2 * InetAddress類用來描述一臺電腦的信息:ip地址,計算機名和其他信息 3 * public static InetAddress getLocalHost();可以獲取本地電腦主機的信息4 * public static InetAddress getByName(String host);可以獲取任意電腦主機的信息 5 */ 6 public static void main(String[] args)throws Exception { 7 //獲取本地電腦主機的信息 8 InetAddress address=InetAddress.getLocalHost(); 9 //使用getHostAddress()方法獲取本地的ip地址 10 String ip=address.getHostAddress(); 11 //使用getHostName()方法獲取本地主機名 12 String hostName=address.getHostName(); 13 //-------------------------getByName()方法的使用--------------------------------- 14 //獲取指定指定主機的電腦信息 15 InetAddress bdAddress=InetAddress.getByName("www.baidu.com");//這裏參數可以是網址,ip地址,和主機名 16 //獲取百度的ip地址 17 String baiDuIp=bdAddress.getHostAddress(); 18 System.out.println("百度的IP地址是:"+baiDuIp); 19 //獲取百度的主機名 20 String baiDuHostName=bdAddress.getHostName(); 21 System.out.println("百度的主機名是:"+baiDuHostName); 22 }
四.UDP編程
1.使用udp實現發送端的編寫:
1 public class SendDemo { 2 3 public static void main(String[] args) throws IOException { 4 //1:建立一個碼頭,該程序有一個對外連接的窗口 5 /* 6 * 套接字 7 */ 8 DatagramSocket ds = new DatagramSocket(); 9 //2:準備要發送的貨物:數據 10 byte[] bytes = "hello udp!!!!".getBytes(); 11 12 //3:準備一個集裝箱,將貨物取裝入集裝箱 13 /* 14 * 參1:你要發送的數據 15 * 參2:你要發送的字節長度 16 * 參3: 表示接收端的ip地址 17 * 參4: 表示接收端的端口號 18 */ 19 //"192.168.65.103" --->InetAddress 20 InetAddress address = InetAddress.getByName("192.168.65.255"); 21 DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, 8888); 22 //4: 發送集裝箱 23 ds.send(dp); 24 //5:關流 25 ds.close(); 26 } 27 28 }
2.使用udp協議實現接收端編寫:
1 public class ReceiveDemo { 2 3 public static void main(String[] args) throws IOException { 4 //1:建立一個碼頭,並綁定端口 5 DatagramSocket ds = new DatagramSocket(8888); 6 //2:準備一個空的集裝箱,用來接收數據 7 /* 8 * 參1:表示要接收的數據存放在哪個字節數組 9 * 參2:表示要接收的數據長度 10 */ 11 byte[] bytes = new byte[1024]; //"hello" ip 和端口 12 DatagramPacket dp = new DatagramPacket(bytes, bytes.length); 13 //3:接收數據 14 ds.receive(dp); //如果沒有接收到數據,則該方法阻塞 15 //4:從集裝箱中獲取數據 16 byte[] data = dp.getData(); //"hello" 17 int length = dp.getLength(); 18 //獲取發送端的ip 19 InetAddress address = dp.getAddress(); 20 String ip = address.getHostAddress(); 21 //5:打印接收到的數據 22 System.out.println(ip+":"+new String(data,0,length)); 23 } 24 25 }
五.TCP編程
交互流程圖:
圖片上傳案例:
客戶端的編寫:
1 public class ClientDemo { 2 public static void main(String[] args) throws IOException { 3 //1:獲取文件的輸入流(讀) 4 FileInputStream fis = new FileInputStream("a.jpg"); 5 6 // BufferedInputStream bufis = new BufferedInputStream(fis); 7 8 //2:獲取套接字的輸出流 9 InetAddress address = InetAddress.getLocalHost(); 10 Socket socket = new Socket(address, 9999); 11 OutputStream os = socket.getOutputStream(); 12 // BufferedOutputStream bufos = new BufferedOutputStream(os); 13 14 //3:將從文件輸入流讀取的數據寫到套接字的輸出流 15 byte[] bytes = new byte[1024]; 16 int len = 0; 17 while((len = fis.read(bytes)) != -1){ 18 os.write(bytes,0,len); 19 } 20 //關閉輸出流 21 // socket.close(); //輸入流和輸出流都關閉 22 socket.shutdownOutput(); //值關閉輸出流 23 //--接收反饋信息 24 //3.1獲取套接字的輸入流 25 InputStream is = socket.getInputStream(); 26 //3.2 讀取數據 27 len = is.read(bytes); 28 System.out.println(new String(bytes,0,len)); 29 //4:關流 30 socket.close(); 31 fis.close(); 32 } 33 34 }
服務器端的編寫:
1 public class ServerDemo { 2 public static void main(String[] args) throws IOException { 3 //1:獲取套接字的輸入流 4 ServerSocket sSocket = new ServerSocket(9999); 5 Socket cSocket = sSocket.accept(); 6 InputStream is = cSocket.getInputStream(); 7 8 //2:獲取文件的輸出流 9 FileOutputStream fos = new FileOutputStream("D:\\Server\\a.jpg"); 10 /* 11 * while循環要想結束必須read方法讀取-1,在普通文件的讀取中,讀取到文件末尾就能-1 12 * 但是套接字沒有文件末尾,所以不能返回-1 13 * 14 * 如何讓服務器讀取到-1? 15 * 只要讓客戶端把輸出流進行關閉 16 */ 17 //3:將從套接字輸入流讀取的數據寫入文件的輸出流 18 byte[] bytes = new byte[1024]; 19 int len = 0; 20 while((len = is.read(bytes)) != -1){ 21 fos.write(bytes, 0, len); 22 } 23 //--在這裏給客戶端反饋 24 //3.1 獲取套接字的輸出流 25 OutputStream os = cSocket.getOutputStream(); 26 //3.2 發送反饋信息 27 os.write("上傳成功啦!".getBytes()); 28 //4:關流 29 fos.close(); 30 cSocket.close(); 31 sSocket.close(); 32 } 33 }
多圖片上傳案例:
客戶端:
1 public class ClientDemo { 2 3 public static void main(String[] args) throws IOException { 4 //1:獲取文件的輸入流(讀) 5 FileInputStream fis = new FileInputStream("a.jpg"); 6 7 // BufferedInputStream bufis = new BufferedInputStream(fis); 8 9 //2:獲取套接字的輸出流 10 InetAddress address = InetAddress.getLocalHost(); 11 Socket socket = new Socket(address, 10086); 12 OutputStream os = socket.getOutputStream(); 13 // BufferedOutputStream bufos = new BufferedOutputStream(os); 14 15 //3:將從文件輸入流讀取的數據寫到套接字的輸出流 16 byte[] bytes = new byte[1024]; 17 int len = 0; 18 while((len = fis.read(bytes)) != -1){ 19 os.write(bytes,0,len); 20 } 21 //關閉輸出流 22 // socket.close(); //輸入流和輸出流都關閉 23 socket.shutdownOutput(); //值關閉輸出流 24 //--接收反饋信息 25 //3.1獲取套接字的輸入流 26 InputStream is = socket.getInputStream(); 27 //3.2 讀取數據 28 len = is.read(bytes); 29 System.out.println(new String(bytes,0,len)); 30 //4:關流 31 socket.close(); 32 fis.close(); 33 } 34 35 }
服務器端:
1 public class ServerDemo { 2 public static void main(String[] args) throws IOException { 3 ServerSocket sSocket = new ServerSocket(10086); 4 //有多少個請求,accept就執行多少次 5 while(true){ 6 Socket cSocket = sSocket.accept(); 7 //每來一個請求,就創建一個線程,去處理請求 8 Thread t = new Thread(new MyRunnable(cSocket)); 9 t.start(); 10 } 11 } 12 }
多線程:
1 public class MyRunnable implements Runnable { 2 private Socket cSocket; 3 4 public MyRunnable(Socket cSocket) { 5 this.cSocket = cSocket; 6 } 7 8 public MyRunnable() { 9 } 10 //a.txt --->a(2).txt 11 @Override 12 public void run() { 13 try { 14 //1: 獲取套接字的輸入流 15 InputStream is = cSocket.getInputStream(); 16 long time = System.currentTimeMillis(); 17 18 //2:獲取文件的輸出流 19 FileOutputStream fos = new FileOutputStream("D:\\Server\\"+time+".jpg"); 20 21 //3:將從套接字輸入流讀取的數據寫入文件的輸出流 22 byte[] bytes = new byte[1024]; 23 int len = 0; 24 while((len = is.read(bytes)) != -1){ 25 fos.write(bytes, 0, len); 26 } 27 System.out.println("while之後"); 28 29 //--在這裏給客戶端反饋 30 //3.1 獲取套接字的輸出流 31 OutputStream os = cSocket.getOutputStream(); 32 //3.2 發送反饋信息 33 os.write("上傳成功啦!".getBytes()); 34 35 //4:關流 36 fos.close(); 37 cSocket.close(); 38 } catch (Exception e) { 39 } 40 } 41 42 }
java學習筆記之網絡編程