網絡通訊協議java
tcp/ip協議:包括TCP協議和IP協議,UDP協議和其它一些協議的協議組安全
層次結構:應用層---傳輸層---網絡層---鏈路層服務器
ip地址:惟一標識一臺計算機 網絡
ipv4版本:4個字節的二進制數表示(一共4個字節,一個字節有8位,用0和1表示),轉換成十進制後就是常見的形式,127.0.0.1多線程
端口:經過ip地址找到 計算機,而後經過端口號來找到指定的應用程序oracle
inetaddress類:封裝一個ip地址,包含主機名dom
構造方法socket
getbyname():靜態方法,須要傳一個字符串表示的ip地址,返回一個inetaddress對象tcp
getlocalhost():靜態方法,空參,返回本地主機的inetaddress對象ide
方法
gethostname():空參,返回表示此ip地址的主機名的字符串
gethostaddress():空參,返回表示ip地址的字符串
InetAddress inet = InetAddress.getLocalHost(); //System.out.println(inet); // String[] str = inet.toString().split("/"); // for(String s:str){ // System.out.println(s); // } //System.out.println(inet.getHostName()); //System.out.println(inet.getHostAddress()); InetAddress inet1 = InetAddress.getByName("123-pc"); System.out.println(inet1);
udp協議:無鏈接通訊協議,數據傳輸時,數據的發送端和接收端不創建邏輯鏈接
佔用資源小,通訊效率高,視頻、音頻和普通數據的傳輸,丟包不會對結果產生太多影響
傳輸重要數據不適用udp
數據大小被限制在64k之內
tcp協議:面向鏈接的通訊協議,傳輸數據前先在發送端和接收端創建邏輯鏈接,而後再傳輸數據,提供了兩臺計算機之間可靠無差錯的數據傳輸
面向鏈接的特效,保證了數據傳輸的安全性(完整性),下載文件時採用tcp協議
udp的使用
datagrampocket類:用來打包用戶的數據,至關於集裝箱
getaddress():返回一個inetaddress對象
getport():返回端口號
getlength():用來獲取數據的大小
datagramsocket類:用來傳輸集裝箱,至關於碼頭
send():發送數據
receive():接收數據
發送端:使用datagrampocket類四個參數的構造方法;使用datagramsocket類的空參構造(不須要指定端口號,系統自動分配一個沒被佔用的端口號)
接收端:使用datagrampocket類兩個參數的構造方法;使用datagramsocket類的有參構造(指定端口號,能夠監聽指定的端口號)
byte[] bytes = "你好".getBytes(); InetAddress inet = InetAddress.getLocalHost(); DatagramPacket dp = new DatagramPacket(bytes, bytes.length, inet, 8000); DatagramSocket ds = new DatagramSocket(); ds.send(dp); ds.close();
DatagramSocket ds = new DatagramSocket(8000); byte[] bytes = new byte[1024]; DatagramPacket dp = new DatagramPacket(bytes, bytes.length); ds.receive(dp); int len = dp.getLength(); String ip = dp.getAddress().getHostAddress(); int port = dp.getPort(); System.out.println(ip+"..."+port+"..."+new String(bytes,0,len)); ds.close();
tcp的使用
客戶端:scocket
構造方法:有參構造,傳入一個表示服務器端ip地址的字符串和端口號
方法:getinputstream()得到輸入流;getoutputstream()得到輸出流
不須要本身去建立流,用方法調用
服務器端:serversocket
構造方法:有參構造,傳入端口號
方法:accept()得到一個socket對象,調用其方法
Socket socket = new Socket("127.0.0.1", 8888); OutputStream out = socket.getOutputStream(); FileInputStream fis = new FileInputStream("d:\\12\\123.jpg"); int len =0; byte[] bytes = new byte[1024]; while((len=fis.read(bytes))!=-1){ out.write(bytes, 0, len); } socket.shutdownOutput(); InputStream in = socket.getInputStream(); len = in.read(bytes); System.out.println(new String(bytes,0,len)); fis.close(); socket.close();
ServerSocket server = new ServerSocket(8888); Socket socket = server.accept(); InputStream in = socket.getInputStream(); File upload = new File("d:\\12\\upload"); if(!upload.exists()){ upload.mkdirs(); } String filename = "oracle"+System.currentTimeMillis()+new Random().nextInt(9999)+".png"; FileOutputStream fos = new FileOutputStream(upload+File.separator+filename); byte[] bytes = new byte[1024]; int len =0; while((len=in.read(bytes))!=-1){ fos.write(bytes, 0, len); } OutputStream out = socket.getOutputStream(); out.write("上傳成功".getBytes()); fos.close(); socket.close(); server.close();
服務器端多線程:
public class Upload implements Runnable { private Socket socket; private FileOutputStream fos; public Upload(Socket socket){ this.socket = socket; } @Override public void run() { // TODO Auto-generated method stub try{ InputStream in = socket.getInputStream(); File upload = new File("d:\\12\\upload"); if(!upload.exists()){ upload.mkdirs(); } String filename = "oracle"+System.currentTimeMillis()+new Random().nextInt(9999)+".png"; fos = new FileOutputStream(upload+File.separator+filename); byte[] bytes = new byte[1024]; int len =0; while((len=in.read(bytes))!=-1){ fos.write(bytes, 0, len); } OutputStream out = socket.getOutputStream(); out.write("上傳成功".getBytes()); }catch(Exception e){ e.printStackTrace(); }finally{ try { fos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { socket.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
ServerSocket server = new ServerSocket(8888); while (true) { Socket socket = server.accept(); Upload upload = new Upload(socket); Thread thread = new Thread(upload); thread.start(); }
類加載
類未被加載到內存中,系統經過加載,鏈接,初始化三步對此類進行初始化
加載:把class文件加載到內存中,並生成一個class文件
鏈接:一、驗證,驗證類的內部結構,並與其它類協調;二、準備,爲靜態成員分配內存,並賦值;三、解析,將二進制的符號引用變成直接引用
初始化:學過的
類初始化時機:一、建立類的對象;二、給靜態成員變量賦值;三、使用靜態方法;四、反射;五、初始化某個類的對象;六、直接java.exe來運行某個類
類的加載器:根類加載器 擴展類加載器 系統類加載器
反射
在java中,動態獲取信息及動態調用對象方法的功能叫作反射機制
class類
構造方法:沒有,只能經過方法得到對象
一、某類的對象調用getclass()方法
二、類名直接調用class靜態成員變量
三、class.forname(),傳入一個字符串,能夠和properties文件一塊兒使用
Person p = new Person(); // Class c = p.getClass(); // System.out.println(c); // Class c1 = Person.class; // System.out.println(c1); // System.out.println(c==c1); // System.out.println(c.equals(c1)); // Class c2 = Class.forName("com.oracle.demo02.Person"); // System.out.println(c2);
方法:
constructor:表示構造方法
field:表示成員變量
method:表示成員方法
declared:能夠得到私有和公有的全部方法
setAccessible():容許對私有化的成員進行修改,暴力反射中的
constructor中的newinstance()方法,返回的是一個obj類型的對象,若是須要使用本類的方法,須要強轉
//反射獲取空參構造 Class c = Class.forName("com.oracle.demo02.Person"); //獲取全部的公共構造方法 // Constructor[] con = c.getConstructors(); // for(Constructor c1:con){ // System.out.println(c1); // } Constructor con = c.getConstructor(); //Object obj = con.newInstance(); Person p = (Person)con.newInstance(); p.work("zhangsan"); //System.out.println(obj);
//獲取有參構造 Class c = Class.forName("com.oracle.demo02.Person"); Constructor con = c.getConstructor(String.class,int.class); System.out.println(con); Object obj = con.newInstance("zhangsan",18); System.out.println(obj);
//快速獲取空參構造方法並建立對象 // Class c = Class.forName("com.oracle.demo02.Person"); // Object obj = c.newInstance(); // System.out.println(obj); //獲取私有的構造方法 //暴力反射,破壞了程序的封裝性和安全性 Class c = Class.forName("com.oracle.demo02.Person"); // Constructor[] con = c.getDeclaredConstructors(); // for(Constructor cc:con){ // System.out.println(cc); // } Constructor con = c.getDeclaredConstructor(int.class,String.class); //System.out.println(con); con.setAccessible(true); Object obj = con.newInstance(18,"zhangsan"); System.out.println(obj); }
//經過反射獲取成員變量並改值 Class c = Class.forName("com.oracle.demo02.Person"); Object obj = c.newInstance(); // Field[] fields = c.getFields(); // for(Field f:fields){ // System.out.println(f); // } Field field = c.getField("name"); Field field1 = c.getDeclaredField("age"); //System.out.println(field); field.set(obj, "zhangsan"); field1.setAccessible(true); field1.set(obj, 25); System.out.println(obj); }
//獲取全部公共的方法,包括繼承來的 // Method[] m = c.getMethods(); // for(Method mm:m){ // System.out.println(mm); // } Method method = c.getMethod("eat"); System.out.println(method); method.invoke(c.newInstance());
//獲取有參方法並運行 Class c = Class.forName("com.oracle.demo02.Person"); Method method = c.getMethod("work", String.class); method.invoke(c.newInstance(), "zhangsan");
泛型擦除
有泛型的類,在程序進行編譯後生成的class文件中,沒有泛型約束,這叫作泛型擦除
//有一個ArrayList<String> list //而後往裏面添加int類型數據 //泛型擦除,字節碼文件中沒有泛型 ArrayList<String> arr = new ArrayList<String>(); arr.add("abc"); Class c = arr.getClass(); Method addd = c.getMethod("add", Object.class); addd.invoke(arr, 1); for(Object o:arr){ System.out.println(o); }
反射配置文件
//類不清楚,方法也不清楚 //經過配置文件去實現,運行類名和方法名已鍵值對的形式 //保存到properties中,具體運行哪一個類裏面的方法經過改配置文件去設置 //1.準備配置文件,寫好鍵值對 //2.IO讀取配置文件reader //3.文件中的鍵值對存儲到集合中,集合中保存的鍵值對就是類名和方法名 //4.反射獲取指定類的class文件對象 //5.class文件對象獲取指定方法 //6.運行方法 //Person p = new Person(); //p.eat(); FileReader fr = new FileReader("config.properties"); Properties pro = new Properties(); pro.load(fr); fr.close(); String className = pro.getProperty("className"); String methodName = pro.getProperty("method"); Class c = Class.forName(className); Object obj = c.newInstance(); Method method = c.getMethod(methodName); method.invoke(obj);