許多學(xué)習(xí)java SE的小伙伴可能會(huì)羨慕學(xué)java web的小伙伴——他們能進(jìn)行前后端交互,看著就很厲害的樣子。而學(xué)會(huì)json的小伙伴可能會(huì)嘗試使用類(lèi)似web的方法通過(guò)json來(lái)進(jìn)行數(shù)據(jù)傳輸。但實(shí)際上,java提供了一種更加高效的程序間傳輸數(shù)據(jù)的方式,這就是socket。接下來(lái)的文章,小編將用一個(gè)socket的實(shí)際項(xiàng)目,來(lái)讓各位小伙伴了解什么是socket網(wǎng)絡(luò)編程。
什么是socket?
socket,中文翻譯為套接字。它是一種對(duì)網(wǎng)絡(luò)中不同主機(jī)上的應(yīng)用進(jìn)程(或者相同主機(jī)的不同應(yīng)用進(jìn)程)之間進(jìn)行雙向通信的端點(diǎn)的抽象。實(shí)際上就是兩個(gè)網(wǎng)絡(luò)各種通信連接中的端點(diǎn)。它的作用就是完成應(yīng)用間的數(shù)據(jù)傳輸。
套接字技術(shù)簡(jiǎn)單的來(lái)講就是通過(guò)socket,將兩個(gè)應(yīng)用進(jìn)行連接,連接之后就能進(jìn)行數(shù)據(jù)傳輸了。socket只是實(shí)現(xiàn)連接的方法。
小編認(rèn)為套接字這個(gè)翻譯并不能直接反映出這門(mén)技術(shù)的特點(diǎn)(過(guò)于生澀),socket可以被翻譯為插座,而實(shí)際上套接字技術(shù)更像是軟件上的“插座”和“插頭”。漢語(yǔ)中的套接,是一種水管對(duì)接的技術(shù),使用一個(gè)套接管將兩端的水管連接起來(lái),這種技術(shù)就叫套接,所以是不是能理解什么是套接字了呢?
更多關(guān)于socket協(xié)議的介紹,可以前往websocket協(xié)議進(jìn)行查看。
怎么使用socket?
不同語(yǔ)言實(shí)現(xiàn)套接字的方式不同,java有專(zhuān)門(mén)實(shí)現(xiàn)套接字的包。只需要?import
? 相應(yīng)的包,就可以進(jìn)行套接字編程。
創(chuàng)建socket連接后可以通過(guò)?getInputStream()
?和?getOutputStream()
?的方法來(lái)獲取和發(fā)送socket之間傳輸?shù)臄?shù)據(jù)。
接下來(lái)就用一個(gè)實(shí)例代碼來(lái)介紹一下怎么使用socket吧!
socket項(xiàng)目實(shí)戰(zhàn)
server.java
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class Server {
public static void main(String[] args){
try {
ServerSocket serverSocket = new ServerSocket(8888);
//在8888端口上監(jiān)聽(tīng),看是否有連接請(qǐng)求過(guò)來(lái)
System.out.println("開(kāi)啟服務(wù)端");
Socket accept = serverSocket.accept();
//獲取socket連接
System.out.println("有連接過(guò)來(lái)"+accept);
Thread thread1 = new Thread(){//使用多線程來(lái)進(jìn)行收發(fā),線程1用來(lái)接收消息
@Override
public void run() {
try {
InputStream inputStream = accept.getInputStream();//獲取socket輸入流
DataInputStream dataInputStream = new DataInputStream(inputStream);
//把輸入流封裝在DataInputStream
while (true){
String msg = dataInputStream.readUTF();//使用readUTF讀取字符串
System.out.println("監(jiān)聽(tīng)客戶端消息: "+msg);
}
} catch (IOException e) {
e.printStackTrace();
}
}
};
Thread thread2 = new Thread(){//線程2用來(lái)發(fā)送消息
@Override
public void run() {
try {
OutputStream outputStream = accept.getOutputStream();
//打開(kāi)輸出流
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
//把輸出流封裝在DataOutputStream中
Scanner scanner = new Scanner(System.in);
while (true){
String strServer = scanner.next();
dataOutputStream.writeUTF(strServer);//使用writeUTF發(fā)送字符串
}
} catch (IOException e) {
e.printStackTrace();
}
}
};
thread1.start();
thread2.start();
thread1.join();
System.out.println("服務(wù)器關(guān)閉");
accept.close();//關(guān)閉單個(gè)socket連接
serverSocket.close(); //關(guān)閉這個(gè)socket 服務(wù)器
} catch (Exception e) {
System.out.println("斷開(kāi)連接");
}
}
}
client.java
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) {
String host = "127.0.0.1";//目標(biāo)電腦的ip地址,這里的地址是本機(jī)地址
int port = 8888;//目標(biāo)電腦的端口
boolean flag = true;
try {
Socket socket = new Socket(host, port);//創(chuàng)建目標(biāo)連接,傳入ip地址和端口號(hào)
System.out.println("開(kāi)啟客戶端");
Thread thread1 = new Thread() {//使用多線程方法來(lái)實(shí)行收發(fā),線程1負(fù)責(zé)接收信息
@Override
public void run() {
try {
InputStream inputStream = socket.getInputStream();//獲取socket輸入流
DataInputStream dataInputStream = new DataInputStream(inputStream);
//把輸入流封裝在DataInputStream
while (true) {
String msg = dataInputStream.readUTF();//使用readUTF讀取字符串
System.out.println("接收服務(wù)端消息: " + msg);
}
} catch (IOException e) {
e.printStackTrace();
}
}
};
Thread thread2 = new Thread() {//線程2用來(lái)發(fā)送消息
@Override
public void run() {
try {
OutputStream outputStream = socket.getOutputStream();
//打開(kāi)輸出流
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
//把輸出流封裝在DataOutputStream中
Scanner scanner = new Scanner(System.in);
while (true) {
String str = scanner.next();
dataOutputStream.writeUTF(str);//使用writeUTF發(fā)送字符串
}
} catch (IOException e) {
e.printStackTrace();
}
}
};
thread1.start();
thread2.start();
thread1.join();
System.out.println("客戶端關(guān)閉");
socket.close();//關(guān)閉這個(gè)socket
} catch (Exception e) {
System.out.println("斷開(kāi)連接");
}
}
}
上述代碼涉及到多線程的知識(shí),如果對(duì)多線程有所疑問(wèn),可以前往java多線程編程進(jìn)行學(xué)習(xí)。如果理解不了socket代碼,也可以前往java網(wǎng)絡(luò)編程進(jìn)行學(xué)習(xí)。
小結(jié)
以上就是Java實(shí)現(xiàn)socket通信的方法。掌握socket通信對(duì)于java的多端開(kāi)發(fā)(比如服務(wù)器客戶端,或者兩個(gè)點(diǎn)對(duì)點(diǎn)應(yīng)用)是十分重要的,各位小伙伴一定要好好學(xué)習(xí)啊。