Socket是什么:所謂Socket 通常也稱作”套接字”,用於描述IP地址和端口,是一個通信鏈的句柄。應用程序通常通過”套接字”向網絡發出請求或者應答網絡請求。Socket內部又有兩種協議(Tcp/Udp),我們來說說其各自的特點。
先來說說網絡編程的三要素1.IP地址:網絡中計算機的唯一標識
2.端口
3.協議:通信的規則
Tcp/Udp特點
一、 TCP(協議):
建立連接,形成傳輸數據的通道
在連接中進行大數據量傳輸
通過三次握手完成連接,是可靠協議
必須建立連接,效率稍微低點
二. UDP(協議):
將數據及源和目的封裝在數據包中,不需要建立連接
每個數據包的大小限制在64K內
因無連接,是不可靠協議
不需要建立連接,速度快
Socket工作圖解
TCP協議進行數據傳輸,實現兩台設備的一個簡單數據發送。
客戶端發送數據/**
*@param serverAddress 要發送到服務端的ip
* 1.創建socket並指定ip和端口號
* 2.獲取輸出流,寫數據
* 3.釋放資源
* 4.Tcp一定要先開接收端
*/
public void send_tcp(String serverAddress) {
try {
Socket s = new Socket(serverAddress, WIFIAdmin.PORT);
//為了發送數據,應該獲得socket流中的輸出流
OutputStream out = s.getOutputStream();
out.write((content.getText().toString()).getBytes());
s.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
服務端接收數據/**
* TCP協議接收數據
* 1.創建接收端的Socket對象
* 2.監聽客戶端接收,返回一個Socket對象
* 3.獲取輸入流,讀取數據顯示在控制台
* 4.釋放資源
*/
public void receive_tcp() {
try {
//1.建立連接,監聽端口
ServerSocket ss = new ServerSocket(WIFIAdmin.PORT);
//2.連接客戶端對象
while (true) {
//阻塞式方法,只有客戶端連接了才會繼續往下運行
Socket accept = ss.accept();
//獲取ip
String ip = accept.getInetAddress().getHostAddress();
//3.獲取客戶端發送過來的數據
InputStream in = accept.getInputStream();
//4.開始讀取,獲取輸入信息
BufferedReader bff = new BufferedReader(new InputStreamReader(in));
//讀取信息
String line;
final StringBuilder sb = new StringBuilder();
while ((line = bff.readLine()) != null) {
sb.append(line);
}
Message message = new Message();
message.obj = sb.toString();
handler.sendMessage(message);
//5.關閉
//ss.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
現在來看下UDP協議是怎么進行數據傳輸的。
先來看下發送端/*
* UDP協議發送數據:
* 1.創建發送端Socket對象
* 2.創建數據,並把數據打包
* 3.調用Socket對象發送方法發送數據包
* 4.釋放資源
*/
private void udpSendMessage() {
DhcpInfo info = wifiManager.getDhcpInfo();
String serverAddress = WIFIAdmin.intToIp(info.serverAddress);
// 創建發送端Socket對象
try {
// 創建發送端Socket對象
DatagramSocket ds = new DatagramSocket();
// 創建數據,並把數據打包
byte[] bys = content.getText().toString().getBytes();
DatagramPacket dp = new DatagramPacket(bys, bys.length, InetAddress.getByName(serverAddress),
WIFIAdmin.UDP_PORT);
// 調用Socket對象發送方法發送數據包
ds.send(dp);
// 釋放資源
ds.close();
} catch (Exception e) {
e.printStackTrace();
}
}
在瞄一下接收端/*
* UDP協議接收數據:
* 1.創建接收端Socket對象
* 2.創建一個數據包(接收容器)
* 3.調用Socket對象接收方法接收數據包
* 4.解析數據包
* 5.釋放資源
*/
private void receive_udp() {
try {
// 創建接收端Socket對象
DatagramSocket ds = new DatagramSocket(WIFIAdmin.UDP_PORT);
// 創建一個數據包(接收容器)
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, bys.length);
// 調用Socket對象接收方法接收數據包
ds.receive(dp);
// 獲取對方的ip
String ip = dp.getAddress().getHostAddress();
// 解析數據
String data = new String(dp.getData(), 0, dp.getLength());
Message message = new Message();
message.obj = data;
message.what = 2;
handler.sendMessage(message);
ds.close();
} catch (Exception e) {
e.printStackTrace();
}
}
使用Tcp協議傳輸大文件,循環將數據寫入流中(Tcp發送端)/*
* @param path 文件路徑
* @param FileName 文件名
*/
public void sendFile(String path, String FileName) {
DhcpInfo info = wifiManager.getDhcpInfo();
serverAddress = WifiAdmin.intToIp(info.serverAddress);
Socket s = new Socket(serverAddress, PORT);
OutputStream out = s.getOutputStream();
//將文件名寫在流的頭部以#分割
out.write((FileName + "#").getBytes());
FileInputStream inputStream = new FileInputStream(new File(path));
byte[] buf = new byte[1024];
int len;
//判斷是否讀到文件末尾
while ((len = inputStream.read(buf)) != -1) {
out.write(buf, 0, len);//將文件循環寫入輸出流
}
//告訴服務端,文件已傳輸完畢
s.shutdownOutput();
//獲取從服務端反饋的信息
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
String serverBack = in.readLine();
Log.d("TAG", serverBack);
//資源關閉
s.close();
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
大文件傳輸(Tcp接收端)public synchronized void receiveFile() {
try {
ServerSocket ss = new ServerSocket(WifiAdmin.PORT);
while (true) {
Socket socket = ss.accept();
InputStream in = socket.getInputStream();
int content;
//裝載文件名的數組
byte[] c = new byte[1024];
//解析流中的文件名,也就是開頭的流
for (int i = 0; (content = in.read()) != -1; i++) {
//表示文件名已經讀取完畢
if (content == '#') {
break;
}
c[i] = (byte) content;
}
//將byte[]轉化為字符,也就是我們需要的文件名
String FileName = new String(c, "utf-8").trim();
//創建一個文件,指定保存路徑和剛才傳輸過來的文件名
OutputStream saveFile = new FileOutputStream(
new File(Environment.getExternalStorageDirectory().toString(), FileName));
byte[] buf = new byte[1024];
int len;
//判斷是否讀到文件末尾
while ((len = in.read(buf)) != -1) {
saveFile.write(buf, 0, len);
}
saveFile.flush();
saveFile.close();
//告訴發送端我已經接收完畢
OutputStream outputStream = socket.getOutputStream();
outputStream.write("文件接收成功".getBytes());
outputStream.flush();
outputStream.close();
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
掌握了Socket的基本傳輸規則,相信你很快就能寫出一個利用局域網讓兩台設備進行數據傳輸了。