本節來說說網絡數據的傳輸。在網絡信道中,所有數據都只能按字節傳輸。這好比,一棟大樓,先拆成一塊塊磚頭,然後再組合成一棟高樓。拆成磚頭的過程,我們可以稱之爲編碼,組成大樓的過程我可以稱之爲解碼。
首先我們從最簡單文本傳輸開始說,在文本的傳輸時,我們也要將字符串編碼和解碼;
編碼:
String -->byte[]
String msg = "Hello";
byte[] data = msg.getBytes("UTF-8"); // GBK
解碼:
byte[] --> String
byte[] data = new byte[4000]; // 準備一個大點的緩衝區
int n = inputStream.read( data ); // 實際收到了N字節
String msg = new String(data, 0, n, "UTF-8"); // 前N字節轉成字符串
值得注意的是,一箇中文字符要佔多少個字節,可能是2個也可能是3個,因爲不同編碼格式佔的字節時不同的。如果是GBK編碼,則佔2個字節,如果是UTF-8則是佔2~3個字節。所以在數據傳輸的時候,也要規定好編碼格式,否則就會出現亂碼情況。比如,用GBK格式編碼,然後用UTF-8的格式解碼,此時就會出現亂碼。
到此,我們學會了文本的數據的傳輸。下面思考有個問題,那麼對象應該如何傳輸呢。上面我們提到了文本傳輸,我們可以將對象轉成文本然後編碼對其進行傳輸。於是,有一個方案,首先將對象轉成json格式的對象,接着將json對象轉成文本,然後對文件進行編碼,解碼則是逆向過程。舉一個例子,有一個Student對象包含以下信息:
public class Student { public int id; public String name; public boolean sex; public String cellphone; }
下面我們對這些信息進行傳輸。這個例子需要導入一個第三方jar來處理json格式的數據:json-org-build20180908.jar
Student類
package my;
public class Student
{
private int id;
private String name;
private boolean sex;
private String cellPhone;
public Student()
{
super();
}
public Student(int id, String name, boolean sex, String cellPhone)
{
super();
this.id = id;
this.name = name;
this.sex = sex;
this.cellPhone = cellPhone;
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public boolean isSex()
{
return sex;
}
public void setSex(boolean sex)
{
this.sex = sex;
}
public String getCellPhone()
{
return cellPhone;
}
public void setCellPhone(String cellPhone)
{
this.cellPhone = cellPhone;
}
@Override
public String toString()
{
// TODO Auto-generated method stub
return "學號:" + this.id + "\r\n" + "姓名:" + this.name + "\r\n性別:" + this.sex + "\r\n手機號碼:" + this.cellPhone + "\r\n";
}
}
1、首先是服端的代碼
package my;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import org.json.JSONObject;
public class MyServer
{
public static void main(String[] args) throws IOException
{
// TODO Auto-generated method stub
//建立服務器,服務於2019端口
ServerSocket serverSock = new ServerSocket(2019);
System.out.println("服務器啓動,等待連接...");
while(true)
{
//監聽請求,阻塞等待,直到有客戶端發起連接...
Socket conn = serverSock.accept();
//從連接裏得到輸入輸出流
//InputStream:可以讀取客戶端發來的數據
//OutputStream:可以發送數據給客戶端
InputStream inputStream = conn.getInputStream();
OutputStream outputStream = conn.getOutputStream();
//接收數據
byte[] inputData = new byte[4000];
int n = inputStream.read(inputData);
if(n <= 0)
{
conn.close();
continue;
}
//發送數據
String inputMsg = new String(inputData , 0 , n , "UTF-8");
System.out.println("GOT:" + inputMsg);
//將接受到的數據轉換爲學生對象
JSONObject obj = new JSONObject(inputMsg);
Student stu = new Student();
stu.setId(obj.optInt("id" , 0));
stu.setName(obj.optString("name" , ""));
stu.setSex(obj.optBoolean("sex" , true));
stu.setCellPhone(obj.optString("cellPhone" , ""));
System.out.println("學生:" + stu.toString());
String outputMsg = "Welcome!";
byte[] ouputData = outputMsg.getBytes();
outputStream.write(ouputData);
System.out.println("ECHO:" + outputMsg + "\n");
//關閉連接
conn.close();
}
}
}
2、客戶端的代碼
package my;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import org.json.JSONObject;
public class MyClient
{
public static void main(String[] args) throws IOException
{
//一個Scoket代表一路連接
Socket sock = new Socket();
//連接至服務器
sock.connect(new InetSocketAddress("127.0.0.1" , 2019));
//InputStream用於接收數據,OutputStreet用於發送數據
InputStream inputStream = sock.getInputStream();
OutputStream outputStream = sock.getOutputStream();
//發送數據
//創建一個學生對象
Student stu = new Student(2018001 , "小明" , true , "18825030000");
JSONObject json = new JSONObject(stu);
String outputMsg = json.toString(2);// "Hello";
byte[] outputData = outputMsg.getBytes("UTF-8");
outputStream.write(outputData);
System.out.println(">>" + outputMsg);
//接收數據
byte[] inputData = new byte[4000];
int n = inputStream.read(inputData);
String inputMsg = new String(inputData , 0 , n , "UTF-8");
System.out.println("<<" + inputMsg);
//關閉連接
sock.close();
}
}