Java學習筆記(21)——網路程式設計(套接字)、TCP、UDP、簡易聊天程式
阿新 • • 發佈:2020-12-29
技術標籤:Java學習欄目網路socketjava網路通訊網路協議
網路程式設計(套接字)
跟網路相關的操作實質都是資料傳輸。
通過IO流在網路上實現資料傳輸。
網路模型---物理層---資料鏈路層---網路層---傳輸層(TCP/UDP)---會話層---表示層---應用層
IP地址---確定主機在網路世界中的位置。
分類 IPV4 四位0-255來組成
IPV6四位16進位制的數
埠---用於和計算機外界進行資料互動的媒介。
埠號---埠的標記 0-65535來表示。
域名---域名可以和IP地址進行一一對映。
IP和埠
package com.hst.netio;
import java.net.InetSocketAddress;
/**
* InetSocketAddress
* 1代表IP
* 1地址和埠號的類
* @author Administrator
*
*/
public class InetSocketAddressDemo {
public static void main(String[] args) {
//建立代表IP和埠號的類的物件
InetSocketAddress is = new InetSocketAddress("www.baidu.com",8090);
System.out.println( is.getAddress().toString());//IP地址
System.out.println(is.getHostName().toString());//主機名
System.out.println(is.getPort());//埠號
}
}
UDP和TCP
UDP和TCP兩者過程不一樣
UDP:過程類似於寄送快遞 需要有自己的快遞點(套接字物件)再有包裹(資料包物件)包裹還要有自己的標記(埠標記包裹本身,IP地址,寄送的物件)所有的包裹打包及寄送的過程都由快遞點(套接字物件)來完成。
UDP
資料接收端
package com.hst.netio;
import java.io. IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
/**
* 1接收發送端傳送的內容
* 1接收端要監聽資料包的埠號
* 1建立接收資料的資料包
* 1埠是接收資料的連結
* 1資料傳輸先發送
* @author Administrator
*
*/
public class UDPjieshouDemo {
public static void main(String[] args) throws IOException {
//建立套接字物件 相當於建立一個快遞點 來接收寄送的快遞 要接收寄送的快遞 就要知道快遞的編號 即監聽埠號
DatagramSocket ds = new DatagramSocket(9090);
//建立接收資料的資料包
//接收端要有位元組來接收資料
DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
ds.receive(dp);//接收資料
ds.close();//關流
//解析資料包
System.out.println(dp.getAddress());
System.out.println(dp.getPort());
System.out.println(new String(dp.getData(),0,dp.getLength()));
}
}
資料傳送端
package com.hst.netio;
import java.io.IOException;
/**
* 1基於IO流
* 1傳輸資料時不會建立連結
* 1不可靠的傳輸方式 不可靠 不安全
* 1傳輸速度快
* 1底層根據資料包進行資料的傳輸 資料包的最大值不能超過 64KB
* 1適合傳輸的場景 直播 語音 視訊等
* 1DatagramSocket DatagramPacket
* 1用於UDP
* 0步驟
* 1建立套接字物件 相當於是成立一個快遞寄送點
* 2建立資料包 相當於是打包一個包裹 要求有包裹的內容 包裹的寄送目的地 和寄送點 埠號可以作為包裹的標記 地址名是寄送地點
* 3傳送資料包 相當於是從快遞點寄送包裹
* 4關流
* @author Administrator
*
*/
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
public class UDPfasongDemo {
public static void main(String[] args) throws SocketException {
//建立套接字物件
DatagramSocket ds = new DatagramSocket();
//建立資料包
//第一個引數要傳送的資料
//轉換為位元組陣列 預設為位元組流
//可以傳輸的資料的位元組個數
//制定地址和埠號
DatagramPacket dp = new DatagramPacket("hello".getBytes(),"hello".length(),new InetSocketAddress("localhost",9090));
//傳送資料包
try {
ds.send(dp);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ds.close();//關流
}
//
}
基於UDP的簡易聊天程式
package com.hst.netio;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.util.Scanner;
/**
* 1用來建立一個微型的資料傳輸的聊天室
* 1需要結合線程來實現
* 1一直髮送 一直接收
* 1知道傳送者和接收端
* @author Administrator
*
*/
public class MiniChatDemo {
public static void main(String[] args) {
new Thread(new ChatSentDemo(),"傳送者").start();
new Thread(new Receiv(),"接收者").start();
}
}
//用來代表執行緒傳送的類
class ChatSentDemo implements Runnable{
//
public synchronized void run() {
//
try {
//建立套接字物件
DatagramSocket ds = new DatagramSocket();
Scanner sc = new Scanner(System.in);
//
while(true) {//一直髮送的狀態;
byte[] data = sc.next().getBytes();
//建立資料包
DatagramPacket dp = new DatagramPacket(data,data.length,new InetSocketAddress("127.0.0.1",9091));
ds.send(dp);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//
}
}
//代表執行緒接收的類
class Receiv implements Runnable {
public synchronized void run() {
//建立套接字物件
try {
DatagramSocket ds = new DatagramSocket(9091);
while(true) {
DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
ds.receive(dp);
System.out.println("收到來自"+dp.getAddress()+"的訊息"+new String(dp.getData(),0,dp.getLength()));
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
TCP:過程類似於打有線電話 首先我們需要建立電話線路 (套接字物件)電話線路的連結需要兩個條件 對方的位置(IP)唯一獨特的線路(埠)通過電話線路給對方傳送訊息(套接字物件自帶的IO流)當我們打通電話的時候 需要通知對方 即電話響鈴。
package com.hst.netio;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import org.omg.CORBA.portable.OutputStream;
public class TCPServerDemo {
public static void main(String[] args) throws IOException{
//建立伺服器端物件---監聽埠
//建立伺服器端物件---監聽埠
ServerSocket ss= new ServerSocket(9092);//這是一個寄送站
//接受連線
Socket s=ss.accept(); //阻塞
//while(true);
System. out .println(1);
//接受客戶端傳送資料
//獲取自帶的位元組輸入流
InputStream is=s.getInputStream();
//自建緩衝區
byte[]bs= new byte[10];
//
int len=-1;
while((len=is.read(bs))!=-1){ //阻塞
//輸出每次讀到的內容
System. out .println( new String(bs,0,len));
}
//通知客戶端資料已經接受完畢
s.shutdownInput();
//獲取自帶的位元組輸出流給客戶端傳送資料
java.io.OutputStream os = s.getOutputStream();
os.write( "你也好".getBytes());
//通知客戶端資料已經發生完畢
s.shutdownOutput();
//關流
ss.close();
}
}
package com.hst.netio;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import org.omg.CORBA.portable.OutputStream;
/**
* 1基於io
* 1可靠安全
* 1傳輸速度慢
* 1不根據資料包傳輸資料 沒有大小限制
* 1使用場景 聊天 檔案
* @author Administrator
*
*/
public class TCPClientDemo {
public static void main(String[]args) throws IOException{
//建立客戶端物件
Socket s = new Socket();//建立一個電話裝置
//建立連線---阻塞
s.connect( new InetSocketAddress( "127.0.0.1",9092));//建立一條專屬的線路 並連結特定使用者的標記
//while(true);
//往伺服器端傳送資料
//獲取自帶的位元組輸出流 預設往伺服器端寫資料
java.io.OutputStream os = s.getOutputStream();//
//通過自帶的輸出流寫出資料
os.write( "您好".getBytes()); //阻塞
/*for(inti=0;i<=100000;i++){
os.write("a".getBytes());
System.out.println(i);
}*/
//通知伺服器端資料已經寫完
s.shutdownOutput();//將信件內容傳送出去
//接受伺服器端傳送的資料
InputStream is=s.getInputStream();
byte[] bs= new byte[10];
int len=-1;
while((len=is.read(bs))!=-1){
System. out .println( new String(bs,0,len));
}
//通知伺服器端資料已經接受完畢
s.shutdownInput();//告訴伺服器 收到回信
//關流
s.close();
}
}