一、網絡編程作用
1、通過網絡編程,我們可以實現通過網絡編程的程序訪問其他的計算機實現資源共享和數據通信
2、我們要做的是實現兩臺計算機之間的通信:
需要先通過電腦的ip地址找到計算機,
然後通過應用程序的端口號找到需要通信的應用程序
然後按照某種協議發送數據
3、
- 本機的地址
通過dos命令行的ipconfig命令,可以獲取本機的IP地址
package 網絡連接三要素;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPSend {
public static void main(String[] args) throws Exception {
DatagramSocket ds=new DatagramSocket();
//創建數據包
// DatagramPacket(byte[] buf, int length, InetAddress address, int port)
// 構造用於發送長度的分組的數據報包 length指定主機上到指定的端口號。
byte [] b="我是JAVA".getBytes();
int len=b.length;
InetAddress address=InetAddress.getByName("msn");
int port=10088;
DatagramPacket p=new DatagramPacket(b,len,address,port);
//發送數據
ds.send( p);
//關閉資源
ds.close();
}
}
package 網絡連接三要素;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDPRecieve {
//此版本出現的問題:使用的byte是1024kb,但是我們接收的的數據只有幾個字符,所以解析時應該注意長度
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket(10088);
// 接收數據包
byte bys[] = new byte[1024];
DatagramPacket p = new DatagramPacket(bys, bys.length);
ds.receive(p);
// 解析數據包
// getData()
// 返回數據緩衝區
byte[] data = p.getData();
// String string = data.toString();
// 返回要發送的數據的長度或接收到的數據的長度
String string = new String(data, 0, p.getLength());
// 輸出數據
System.out.println(string);
// 關閉客戶端
ds.close();
}
}
package 網絡連接三要素;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
public class TCPSend {
public static void main(String[] args) throws IOException {
Socket s = new Socket("192.168.2.138", 10010);
OutputStream os = s.getOutputStream();
os.write("我來了,TCP".getBytes());
s.close();
}
}
package 網絡連接三要素;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPRecieve {
public static void main(String[] args) throws IOException {
ServerSocket s = new ServerSocket(10010);
Socket accept = s.accept();
InputStream is = accept.getInputStream();
byte[] b = new byte[1024];
int read = is.read(b);// 將數據讀取到b中,並返回數組長度
String string = new String(b, 0, read);
System.out.println(string);
s.close();
}
}
寫代碼過程中遇到的問題
1、思路整理:
UDP協議:
- 首先,使用DatagramSocket創建一個無參客戶端對象,
- 然後將數據打包,通過客戶端對象的send方法發送,
- 最後關閉客戶端對象。
其中,打包使用DatagramPacket類進行,這個類可以將字節數組的數據進行打包。打包使用的內容有:字節數組,字節數組的長度,以及服務器端的IP,也就是InetAddress對象,還有應用程序的端口號。 - 當服務端接收數據時,也是通過DatagramSocket對象,接收客戶端發送的數據包,
- 然後將數據包中的內容解析,相當於一個解壓縮的過程。
- 解析後通過數據包的getData方法會得到一個字節數組,對數據進行操作,比如說可以進行輸出。
- 然後將服務端對象關閉。
那麼接收客戶端發來的數據通過的也是數據包DatagramPacket對象。這個對象需要有一個容器存放數據,也就是字節數組,還需要知道要讀取的字節數。一般寫的比較大,比如1024。然後通過服務端對象的recieve方法對數據包進行接收。
2、String問題
在解析客戶端發來的數據時,會通過包的getData方法得到數據的字節數組。一般爲了方便操作,比如輸出方便,會將其轉化爲字符串類型。老師講課使用的構造方法,我想爲什麼不適用toString().我轉字符串類型時,想當然地使用的b.toString()方法,結果總是不對。後來經過查閱資料和思考,突然想起來平時我們輸出一個類時會重寫toString方法,然後我查看toString源碼,發現跟輸出結果相同。
所以,要實現此功能需要使用字符串的構造方法String s=new String(b);
3、TCP協議區分輸入和輸出流
對於客戶端來說,input是服務端回寫的時候使用,output是向服務端發送數據使用
對於服務端,input是服務端接受數據使用,output是服務端回寫的時候使用
總結:不論是哪個端,有一方告訴你數據,那麼你就需要讀內容,讀也就是輸入,input。當要告訴其他方時,需要使用output
4、TCP理解對象構造方法
對於客戶端,我們需要告知所需要訪問的電腦和應用程序,所以參數使用兩個
對於服務端,訪問的電腦已經確定,需要確定的是端口號,因此參數是端口號
5、TCP輸入輸出流
ServiceSocket類中,是沒有輸入輸出流相關方法的,它使用的是Socket對象的輸入輸出流,所以在服務端必須先通過accept()方法獲取客戶端的Socket對象。
InputStream的read方法只能讀取字節數組,返回值是讀取到的個數
另外,TCP都是對字節流進行操作
6、其他錯誤
ERROR: JDWP Unable to get JNI 1.2 environment, jvm->GetEnv() return code = -2 JDWP exit error AGENT_ERROR_NO_JNI_ENV(183): [util.c:840]
參考的博客