黑馬程序員----JAVA基礎之GUI可視化編程與枚舉&網絡編程



                                                            ------ android培訓java培訓、期待與您交流! ----------


一、GUI可視化編程

1. GUI可視化編程是什麼?

就是讓界面可視,點擊觸發事件

2. GUI可視化編程有什麼用?

java程序用一個窗口界面直觀的表示所操作的動作和結果,操作更方便

3. GUI的佈局

A:流式佈局
B:邊界佈局
C:網格佈局
D:網格包佈局
E:卡片佈局管

4. GUI的事件處理機制

       三個重要的概念:

            A:事件: 用戶對組件的一個操作,稱之爲一個事件。

             B:事件源: 發生事件的組件就是事件源

             C:事件處理器:某個java類中的負責處理時間的成員方法

 一般,我們把某個組件添加一個事件監聽.當他產生了某個事件的時候,就會按照對應的處理去執行.


    事件分類:

            MouseEvent   WindowEvent  ActionEvent

 

    處理髮生在某個GUI組件上的XxxEvent時間的某個情況,其事件處理的通用編寫流程:

     1.       編寫一個實現了XxxListenener接口的時間監聽類

      2.       XxxListener類中的用於處理該事件情況的方法中,編寫處理代碼

      3.       調用組建的AddXxxListener方法,將類Xxxlistener創建的實力註冊到GUI組建上


5. GUI可視化編程怎麼用?

格式:步驟

建立窗口---建立各種組件(菜單,文本框,文本域)-----添加各種組件----給各種組件添加監聽器-----給組件添加事件處理

private Frame f;
private TextField tf;
private Button bt, bt1;
private TextArea ta;
private MenuBar mb;
private Menu m, m1;
private MenuItem mi,mi1,mi2,mi3,mi4;
public MyFormat() {
init();
}
private void init() {
// 建立一個窗口
f = new Frame();
//設置窗口名稱
f.setTitle("不會回來");
// 設大小位置
f.setBounds(400, 300, 400, 300);
// 設制佈局--流式佈局
f.setLayout(new FlowLayout());
//建立一個文本框
tf = new TextField(20);
//建立一個按鍵
bt = new Button("輸入");
//再建立一個按鍵
bt1 = new Button("打印");
//建立一個文本域
ta = new TextArea(10, 40);
//建立一個菜單欄
mb = new MenuBar();
//建立一個菜單
m = new Menu("文件");
//再建立一個菜單
m1 = new Menu("更改標題");
//建立菜單項
mi = new MenuItem("退出系統");
mi1 = new MenuItem("記事本");
mi2 = new MenuItem("好好學習");
mi3 = new MenuItem("天天向上");
mi4 = new MenuItem("恢復標題");
//將菜單欄添加到窗口上
f.setMenuBar(mb);
//將菜單添加至菜單欄
mb.add(m);
//再將菜單項添加至菜單m
m.add(m1);
m.add(mi);
m.add(mi1);
//再給m1添加菜單項
m1.add(mi2);
m1.add(mi3);
m1.add(mi4);
//給窗口添加文本框
f.add(tf);
//給窗口添加按鈕
f.add(bt);
f.add(bt1);
//給窗口添加文本域
f.add(ta);
//建立監聽方法
myEvent();
//讓窗口可見
f.setVisible(true);
}
private void myEvent(){
//給窗口添加關閉事件
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
//給菜單項mi添加事件
mi.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
//給菜單項添加事件
mi1.addActionListener(new ActionListener() {
//給mi2建立事件
public void actionPerformed(ActionEvent e) {
Runtime r =Runtime.getRuntime();
try {
r.exec("notepad");
f.setVisible(false);
System.exit(0);
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
//給文本框添加事件
bt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//讓文本框寫入到文件中
PrintWriter pw =null;
try {
 pw = new PrintWriter(new FileWriter("Frame.txt",true),true);
pw.println(tf.getText());
} catch (IOException e1) {
e1.printStackTrace();
}finally{
if (pw!=null) {
pw.close();
//寫完之後清空文本框
tf.setText("");
}
}
}
});
//設立文本域事件
bt1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
//讓文本域據接收數據
//寫前之清空文本框
ta.setText("");
BufferedReader br=null;
try {
 br= new BufferedReader(new FileReader("Frame.txt"));
try {
String s=null;
System.out.println(s);
while ((s=br.readLine())!=null) {
ta.append(s+"\t\n");
}
} catch (IOException e1) {
e1.printStackTrace();
}
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}finally{
if (br!=null) {
try {
br.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
});
}
}



二、枚舉


1. 什麼是枚舉?

枚舉是一個特殊的java,用關鍵字enum表示,不用class,其構造函數私有化,裏面提供固定的對象也就是枚舉.聲名多少個枚舉,就有多少個對象.也就是在外部無法再創建這個類的對象,只能用其提供的對象.

底層就是私用化構造方法,並定義幾個 public static final 修飾的對象,外部直接用類名打點調對象名獲取對象,對象名就是枚舉.

2. 枚舉有什麼用?

枚舉可以限定外部能使用的類的對象,從而提高了程序的安全性.並簡化代碼

3. 枚舉怎麼用?

外部直接用類名打點調獲取對象,並調用類成員:Print.A.print()

1. 聲名不帶構造方法的枚舉

enum Print{

 A,B,C;

}

1.聲名帶構造的枚舉

enum Print{

 A("a"),B("a"),C("a");

String s;

private Test(String s){

this.s=s;

}

}

2.定義帶抽象方法的枚舉,多用於讓枚舉實現不同的返回值.

enum Print {

A {

String print() {

return "A";

}

},B {

String print() {

return "B";

}

};

abstract String print();

}

2. 枚舉常用特有方法:

 String name() 返回此枚舉常量的名稱,在其枚舉聲明中對其進行聲明。 如:Print.A.name()=="A";

int ordinal() 返回枚舉常量的索引(它在枚舉聲明中的位置,其中初始常量序數爲零)。 

public static <T extends Enum<T>> T valueOf(Class<T> enumType,String name)

返回帶指定名稱的指定枚舉類型的枚舉常量。名稱必須與在此類型中聲明枚舉常量所用的標識符完全匹配。(不允許使用額外的空白字符。) 

參數:

enumType - 要從中返回常量的枚舉類型的 Class 對象

name - 要返回的常量名稱 

返回:帶指定名稱的指定枚舉類型的枚舉常量 (枚舉類和其)

例如String s = "B";

//下面兩種都可以.

Print a = Print.valueOf(Print.class, s);

 a = Print.valueOf(s);

4. 枚舉什麼時候用?

當需要讓一個類只提供固定的對象的時候.

5. 枚舉有什麼特點?

1.枚舉構造方法必須私有

2.聲名枚舉,必須在類裏的首行,枚舉間用逗號隔開,如果還有其它代碼則最後一個枚舉後必須加分號

3.枚舉有類的特性,可以聲名屬性和方法,也可以實現接口和繼承抽象類.

4.JDK1.5後,swith可以接收枚舉類型

5.如果枚舉只有一個值時,可以當單例用.



其實在 java 的枚舉實現,這些枚舉值還是與某個整形常量值對應的


//枚舉類DownloadStatus代碼
public enum DownloadStatus {
Remote_File_Noexist, //遠程文件不存在
Local_Bigger_Remote, //本地文件大於遠程文件
Download_From_Break_Success, //斷點下載文件成功
Download_From_Break_Failed, //斷點下載文件失敗
Download_New_Success, //全新下載文件成功
Download_New_Failed; //全新下載文件失敗
} 比如這代碼


 三 . 網絡編程

1. 什麼是網絡編程?

就是用來實現網絡互連的不同計算機上運行的程序間可以進行數據交換。

2. 網絡編程有什麼作用?

可以計算機之間相互通信,並進行數據傳輸

3. 網絡編程怎麼用?

InetAddress類的使用:

沒有構造方法,但可以通過getLocalHost etByName 獲取對象

要掌握的功能

獲取本地主機:getLocalHost

InetAddress address =InetAddress.getLocalHost();

獲取任意指定主機:getByName

InetAddress address = InetAddress.getByName("fada-PC");

主機Ip地址:getHostAddress

String ip = address.getHostAddress();

主機名:getHostName

String name = address.getHostName();

UDP傳輸:

格式步驟:

DatagramSocket與DatagramPacket

建立發送端,接收端。

建立數據包。

調用Socket的發送接收方法。

關閉Socket

發送端與接收端是兩個獨立的運行程序。

做一個發送端:

//建立發送端
DatagramSocket ds = new DatagramSocket();
//建立字節輸入流並用轉換流轉換成一個字符緩衝
BufferedReaderbr = new BufferedReader(new InputStreamReader(System.in));
//把字符流中的數據讀出 
String s =null;
while((s=br.readLine())!=null){
if("886".equals(s)){
byte[] bye = s.getBytes();
//把字符流讀出的數據存在數據包中 建立數據包
break;
}
byte[] bye = s.getBytes();
//把字符流讀出的數據存在數據包中建立數據包
DatagramPacket dp = new DatagramPacket(bye,bye.length,InetAddress.getByName("fada-pc"),11118);
//把數據包發送出去
ds.send(dp);
}
//關閉資源
ds.close();
br.close(); 
接收端:
//給定建立接收端
DatagramSocket ds = new DatagramSocket(11118);
//建立一個給定容量的數據包
while(true){
byte[] bye =new byte[1024];
DatagramPacket dp = new DatagramPacket(bye,bye.length);
//將數據包加載到緩存中
ds.receive(dp);
//解析數據包中的IP
String ip = dp.getAddress().getHostAddress();
//解析數據包中的數組接收的內容
String text = new String(bye,0,dp.getLength());
System.out.println(ip+"***"+text);
}


TCP傳輸

①使用Socket和ServerSocket,

②建立客戶端和服務器端,

③建立連接後,通過Socket中的IO流進行數據的傳輸

④關閉socket

客戶端與服務器端也是兩個獨立的應用程序。

a.TCP協議的客戶端

思路:

1:建立客戶端的Socket服務,並明確要連接的服務器。

2:如果連接建立成功,就表明,已經建立了數據傳輸的通道.就可以在該通道通過IO進行數據的讀取和寫入.

  該通道稱爲Socket流,Socket流中既有讀取流,也有寫入流.

3:通過Socket對象的方法,可以獲取這兩個流

4:通過流的對象可以對數據進行傳輸

5:如果傳輸數據完畢,關閉資源

代碼:

Socket s = new Socket("192.168.1.34", 10010);
OutputStream os = s.getOutputStream();
os.write("Hello,Tcp,I am coming".getBytes());
s.close();


b.TCP協議的服務器端

思路:

1:建立服務器端的socket服務,需要一個端口

2:服務端沒有直接流的操作,而是通過accept方法獲取客戶端對象,在通過獲取到的客戶端對象的流和客戶端進行通信

3:通過客戶端的獲取流對象的方法,讀取數據或者寫入數據

4:如果服務完成,需要關閉客戶端,然後關閉服務器,但是,一般會關閉客戶端,不會關閉服務器,因爲服務端是一直提供服務的

代碼:

ServerSocket ss = new ServerSocket(10010);
Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress();
System.out.println("客戶端的ip:"+ip + "*連接上");
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys);
String text = new String(bys, 0, len);
System.out.println(text);
ss.close();


c.TCP協議的程序服務器給客戶端一個反饋

客戶端和服務器端在原有的基礎上添加反饋,接收端的部分寫到客戶端下邊,客戶端的部分寫到接收端下邊

d.一個大寫的轉換服務器

客戶端代碼:

Socket s = new Socket("192.168.1.34", 10086);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
BufferedReader brServer = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
if ("over".equals(line)) {
break;
}
bw.write(line+"\r\n");
bw.flush();
String serverText = brServer.readLine();
System.out.println("server:" + serverText);
}
br.close();
s.close();


注意:

1.字符流是有緩衝區的,每次數據寫入後,需要刷新緩衝區。

2.這樣操作後發現還是不行,那麼還有什麼原因呢?

3.考慮readLine的特點。一次讀取一行。但是不要忽略它的結束條件是:\r\n

服務器代碼:

ServerSocket ss = new ServerSocket(10086);
Socket s = ss.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
bw.write(line.toUpperCase()+"\r\n");
bw.flush();
}
ss.close();


e.用PrintWriter改寫轉換服務器

注意println和true的使用

4. 網絡編程什麼時候用?

計算機間需要進行數據傳輸時

5. 網絡編程有什麼特點?

網絡通信三要素

IP地址:InetAddress :網絡中設備的標識,不易記憶,可用主機名

端口號 :用於標識進程的邏輯地址,不同進程的標識

物理端口 網卡口

邏輯端口 我們指的就是邏輯端口

A:每個網絡程序都會至少有一個邏輯端口

B:用於標識進程的邏輯地址,不同進程的標識

C:有效端口:0~65535,其中0~1024系統使用或保留端口。自已定義一般在1萬以上

通過360可以查看端口號

傳輸協議:通訊的規則 ---常見協議:TCPUDP

UDP

將數據源和目的封裝成數據包中,不需要建立連接;每個數據報的大小在限制在64k;因無連接,是不可靠協議;不需要建立連接,速度快

TCP

建立連接,形成傳輸數據的通道;在連接中進行大數據量傳輸;通過三次握手完成連接,是可靠協議;必須建立連接,效率會稍低

Socket

用於描述IP地址和端口,是一個通信鏈的句柄。在Internet上的主機一般運行了多個服務軟件,同時提供幾種服務。每種服務都打開一個Socket,並綁定到一個端口上,不同的端口對應於不同的服務。

Socket就是爲網絡編程提供的一種機制;通信的兩端都有Socket;網絡通信其實就是Socket間的通信;數據在兩個Socket間通過IO傳輸。


                                                              ------ android培訓java培訓、期待與您交流! ----------




                                                            ------ android培訓java培訓、期待與您交流! ----------


一、GUI可視化編程

1. GUI可視化編程是什麼?

就是讓界面可視,點擊觸發事件

2. GUI可視化編程有什麼用?

java程序用一個窗口界面直觀的表示所操作的動作和結果,操作更方便

3. GUI的佈局

A:流式佈局
B:邊界佈局
C:網格佈局
D:網格包佈局
E:卡片佈局管

4. GUI的事件處理機制

       三個重要的概念:

            A:事件: 用戶對組件的一個操作,稱之爲一個事件。

             B:事件源: 發生事件的組件就是事件源

             C:事件處理器:某個java類中的負責處理時間的成員方法

 一般,我們把某個組件添加一個事件監聽.當他產生了某個事件的時候,就會按照對應的處理去執行.


    事件分類:

            MouseEvent   WindowEvent  ActionEvent

 

    處理髮生在某個GUI組件上的XxxEvent時間的某個情況,其事件處理的通用編寫流程:

     1.       編寫一個實現了XxxListenener接口的時間監聽類

      2.       XxxListener類中的用於處理該事件情況的方法中,編寫處理代碼

      3.       調用組建的AddXxxListener方法,將類Xxxlistener創建的實力註冊到GUI組建上


5. GUI可視化編程怎麼用?

格式:步驟

建立窗口---建立各種組件(菜單,文本框,文本域)-----添加各種組件----給各種組件添加監聽器-----給組件添加事件處理

private Frame f;
private TextField tf;
private Button bt, bt1;
private TextArea ta;
private MenuBar mb;
private Menu m, m1;
private MenuItem mi,mi1,mi2,mi3,mi4;
public MyFormat() {
init();
}
private void init() {
// 建立一個窗口
f = new Frame();
//設置窗口名稱
f.setTitle("不會回來");
// 設大小位置
f.setBounds(400, 300, 400, 300);
// 設制佈局--流式佈局
f.setLayout(new FlowLayout());
//建立一個文本框
tf = new TextField(20);
//建立一個按鍵
bt = new Button("輸入");
//再建立一個按鍵
bt1 = new Button("打印");
//建立一個文本域
ta = new TextArea(10, 40);
//建立一個菜單欄
mb = new MenuBar();
//建立一個菜單
m = new Menu("文件");
//再建立一個菜單
m1 = new Menu("更改標題");
//建立菜單項
mi = new MenuItem("退出系統");
mi1 = new MenuItem("記事本");
mi2 = new MenuItem("好好學習");
mi3 = new MenuItem("天天向上");
mi4 = new MenuItem("恢復標題");
//將菜單欄添加到窗口上
f.setMenuBar(mb);
//將菜單添加至菜單欄
mb.add(m);
//再將菜單項添加至菜單m
m.add(m1);
m.add(mi);
m.add(mi1);
//再給m1添加菜單項
m1.add(mi2);
m1.add(mi3);
m1.add(mi4);
//給窗口添加文本框
f.add(tf);
//給窗口添加按鈕
f.add(bt);
f.add(bt1);
//給窗口添加文本域
f.add(ta);
//建立監聽方法
myEvent();
//讓窗口可見
f.setVisible(true);
}
private void myEvent(){
//給窗口添加關閉事件
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
//給菜單項mi添加事件
mi.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
//給菜單項添加事件
mi1.addActionListener(new ActionListener() {
//給mi2建立事件
public void actionPerformed(ActionEvent e) {
Runtime r =Runtime.getRuntime();
try {
r.exec("notepad");
f.setVisible(false);
System.exit(0);
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
//給文本框添加事件
bt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//讓文本框寫入到文件中
PrintWriter pw =null;
try {
 pw = new PrintWriter(new FileWriter("Frame.txt",true),true);
pw.println(tf.getText());
} catch (IOException e1) {
e1.printStackTrace();
}finally{
if (pw!=null) {
pw.close();
//寫完之後清空文本框
tf.setText("");
}
}
}
});
//設立文本域事件
bt1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
//讓文本域據接收數據
//寫前之清空文本框
ta.setText("");
BufferedReader br=null;
try {
 br= new BufferedReader(new FileReader("Frame.txt"));
try {
String s=null;
System.out.println(s);
while ((s=br.readLine())!=null) {
ta.append(s+"\t\n");
}
} catch (IOException e1) {
e1.printStackTrace();
}
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}finally{
if (br!=null) {
try {
br.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
});
}
}



二、枚舉


1. 什麼是枚舉?

枚舉是一個特殊的java,用關鍵字enum表示,不用class,其構造函數私有化,裏面提供固定的對象也就是枚舉.聲名多少個枚舉,就有多少個對象.也就是在外部無法再創建這個類的對象,只能用其提供的對象.

底層就是私用化構造方法,並定義幾個 public static final 修飾的對象,外部直接用類名打點調對象名獲取對象,對象名就是枚舉.

2. 枚舉有什麼用?

枚舉可以限定外部能使用的類的對象,從而提高了程序的安全性.並簡化代碼

3. 枚舉怎麼用?

外部直接用類名打點調獲取對象,並調用類成員:Print.A.print()

1. 聲名不帶構造方法的枚舉

enum Print{

 A,B,C;

}

1.聲名帶構造的枚舉

enum Print{

 A("a"),B("a"),C("a");

String s;

private Test(String s){

this.s=s;

}

}

2.定義帶抽象方法的枚舉,多用於讓枚舉實現不同的返回值.

enum Print {

A {

String print() {

return "A";

}

},B {

String print() {

return "B";

}

};

abstract String print();

}

2. 枚舉常用特有方法:

 String name() 返回此枚舉常量的名稱,在其枚舉聲明中對其進行聲明。 如:Print.A.name()=="A";

int ordinal() 返回枚舉常量的索引(它在枚舉聲明中的位置,其中初始常量序數爲零)。 

public static <T extends Enum<T>> T valueOf(Class<T> enumType,String name)

返回帶指定名稱的指定枚舉類型的枚舉常量。名稱必須與在此類型中聲明枚舉常量所用的標識符完全匹配。(不允許使用額外的空白字符。) 

參數:

enumType - 要從中返回常量的枚舉類型的 Class 對象

name - 要返回的常量名稱 

返回:帶指定名稱的指定枚舉類型的枚舉常量 (枚舉類和其)

例如String s = "B";

//下面兩種都可以.

Print a = Print.valueOf(Print.class, s);

 a = Print.valueOf(s);

4. 枚舉什麼時候用?

當需要讓一個類只提供固定的對象的時候.

5. 枚舉有什麼特點?

1.枚舉構造方法必須私有

2.聲名枚舉,必須在類裏的首行,枚舉間用逗號隔開,如果還有其它代碼則最後一個枚舉後必須加分號

3.枚舉有類的特性,可以聲名屬性和方法,也可以實現接口和繼承抽象類.

4.JDK1.5後,swith可以接收枚舉類型

5.如果枚舉只有一個值時,可以當單例用.



其實在 java 的枚舉實現,這些枚舉值還是與某個整形常量值對應的


//枚舉類DownloadStatus代碼
public enum DownloadStatus {
Remote_File_Noexist, //遠程文件不存在
Local_Bigger_Remote, //本地文件大於遠程文件
Download_From_Break_Success, //斷點下載文件成功
Download_From_Break_Failed, //斷點下載文件失敗
Download_New_Success, //全新下載文件成功
Download_New_Failed; //全新下載文件失敗
} 比如這代碼


 三 . 網絡編程

1. 什麼是網絡編程?

就是用來實現網絡互連的不同計算機上運行的程序間可以進行數據交換。

2. 網絡編程有什麼作用?

可以計算機之間相互通信,並進行數據傳輸

3. 網絡編程怎麼用?

InetAddress類的使用:

沒有構造方法,但可以通過getLocalHost etByName 獲取對象

要掌握的功能

獲取本地主機:getLocalHost

InetAddress address =InetAddress.getLocalHost();

獲取任意指定主機:getByName

InetAddress address = InetAddress.getByName("fada-PC");

主機Ip地址:getHostAddress

String ip = address.getHostAddress();

主機名:getHostName

String name = address.getHostName();

UDP傳輸:

格式步驟:

DatagramSocket與DatagramPacket

建立發送端,接收端。

建立數據包。

調用Socket的發送接收方法。

關閉Socket

發送端與接收端是兩個獨立的運行程序。

做一個發送端:

//建立發送端
DatagramSocket ds = new DatagramSocket();
//建立字節輸入流並用轉換流轉換成一個字符緩衝
BufferedReaderbr = new BufferedReader(new InputStreamReader(System.in));
//把字符流中的數據讀出 
String s =null;
while((s=br.readLine())!=null){
if("886".equals(s)){
byte[] bye = s.getBytes();
//把字符流讀出的數據存在數據包中 建立數據包
break;
}
byte[] bye = s.getBytes();
//把字符流讀出的數據存在數據包中建立數據包
DatagramPacket dp = new DatagramPacket(bye,bye.length,InetAddress.getByName("fada-pc"),11118);
//把數據包發送出去
ds.send(dp);
}
//關閉資源
ds.close();
br.close(); 
接收端:
//給定建立接收端
DatagramSocket ds = new DatagramSocket(11118);
//建立一個給定容量的數據包
while(true){
byte[] bye =new byte[1024];
DatagramPacket dp = new DatagramPacket(bye,bye.length);
//將數據包加載到緩存中
ds.receive(dp);
//解析數據包中的IP
String ip = dp.getAddress().getHostAddress();
//解析數據包中的數組接收的內容
String text = new String(bye,0,dp.getLength());
System.out.println(ip+"***"+text);
}


TCP傳輸

①使用Socket和ServerSocket,

②建立客戶端和服務器端,

③建立連接後,通過Socket中的IO流進行數據的傳輸

④關閉socket

客戶端與服務器端也是兩個獨立的應用程序。

a.TCP協議的客戶端

思路:

1:建立客戶端的Socket服務,並明確要連接的服務器。

2:如果連接建立成功,就表明,已經建立了數據傳輸的通道.就可以在該通道通過IO進行數據的讀取和寫入.

  該通道稱爲Socket流,Socket流中既有讀取流,也有寫入流.

3:通過Socket對象的方法,可以獲取這兩個流

4:通過流的對象可以對數據進行傳輸

5:如果傳輸數據完畢,關閉資源

代碼:

Socket s = new Socket("192.168.1.34", 10010);
OutputStream os = s.getOutputStream();
os.write("Hello,Tcp,I am coming".getBytes());
s.close();


b.TCP協議的服務器端

思路:

1:建立服務器端的socket服務,需要一個端口

2:服務端沒有直接流的操作,而是通過accept方法獲取客戶端對象,在通過獲取到的客戶端對象的流和客戶端進行通信

3:通過客戶端的獲取流對象的方法,讀取數據或者寫入數據

4:如果服務完成,需要關閉客戶端,然後關閉服務器,但是,一般會關閉客戶端,不會關閉服務器,因爲服務端是一直提供服務的

代碼:

ServerSocket ss = new ServerSocket(10010);
Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress();
System.out.println("客戶端的ip:"+ip + "*連接上");
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys);
String text = new String(bys, 0, len);
System.out.println(text);
ss.close();


c.TCP協議的程序服務器給客戶端一個反饋

客戶端和服務器端在原有的基礎上添加反饋,接收端的部分寫到客戶端下邊,客戶端的部分寫到接收端下邊

d.一個大寫的轉換服務器

客戶端代碼:

Socket s = new Socket("192.168.1.34", 10086);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
BufferedReader brServer = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
if ("over".equals(line)) {
break;
}
bw.write(line+"\r\n");
bw.flush();
String serverText = brServer.readLine();
System.out.println("server:" + serverText);
}
br.close();
s.close();


注意:

1.字符流是有緩衝區的,每次數據寫入後,需要刷新緩衝區。

2.這樣操作後發現還是不行,那麼還有什麼原因呢?

3.考慮readLine的特點。一次讀取一行。但是不要忽略它的結束條件是:\r\n

服務器代碼:

ServerSocket ss = new ServerSocket(10086);
Socket s = ss.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
bw.write(line.toUpperCase()+"\r\n");
bw.flush();
}
ss.close();


e.用PrintWriter改寫轉換服務器

注意println和true的使用

4. 網絡編程什麼時候用?

計算機間需要進行數據傳輸時

5. 網絡編程有什麼特點?

網絡通信三要素

IP地址:InetAddress :網絡中設備的標識,不易記憶,可用主機名

端口號 :用於標識進程的邏輯地址,不同進程的標識

物理端口 網卡口

邏輯端口 我們指的就是邏輯端口

A:每個網絡程序都會至少有一個邏輯端口

B:用於標識進程的邏輯地址,不同進程的標識

C:有效端口:0~65535,其中0~1024系統使用或保留端口。自已定義一般在1萬以上

通過360可以查看端口號

傳輸協議:通訊的規則 ---常見協議:TCPUDP

UDP

將數據源和目的封裝成數據包中,不需要建立連接;每個數據報的大小在限制在64k;因無連接,是不可靠協議;不需要建立連接,速度快

TCP

建立連接,形成傳輸數據的通道;在連接中進行大數據量傳輸;通過三次握手完成連接,是可靠協議;必須建立連接,效率會稍低

Socket

用於描述IP地址和端口,是一個通信鏈的句柄。在Internet上的主機一般運行了多個服務軟件,同時提供幾種服務。每種服務都打開一個Socket,並綁定到一個端口上,不同的端口對應於不同的服務。

Socket就是爲網絡編程提供的一種機制;通信的兩端都有Socket;網絡通信其實就是Socket間的通信;數據在兩個Socket間通過IO傳輸。


                                                              ------ android培訓java培訓、期待與您交流! ----------


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章