本文部分參考:
《Socket通信原理》
1捞烟、什么是Socket
Socket是應(yīng)用層與TCP/IP協(xié)議族通信的中間軟件抽象層嗽仪,它是一組接口鳄哭。在設(shè)計(jì)模式中,Socket其實(shí)就是一個(gè)門(mén)面模式萎胰,他把復(fù)雜的TCP/IP協(xié)議族隱藏在Socket接口后面碾盟,對(duì)用戶(hù)來(lái)說(shuō),一組簡(jiǎn)單的接口就是全部技竟,讓Socket去組織數(shù)據(jù)冰肴,以符合指定的協(xié)議。
2、幾個(gè)專(zhuān)用名詞
- IP:每個(gè)計(jì)算機(jī)都有對(duì)應(yīng)的唯一標(biāo)識(shí)即IP地址熙尉,IP地址格式為:255.255.255.255联逻。目前是第4版本IPV4。
- 端口號(hào):端口號(hào)是網(wǎng)絡(luò)應(yīng)用程序的區(qū)分標(biāo)識(shí)检痰,有了端口號(hào)包归,計(jì)算機(jī)就知道將接受到的數(shù)據(jù)傳給哪一個(gè)應(yīng)用的程序,端口號(hào)范圍065535铅歼,其中01023為系統(tǒng)所保留公壤。
-
協(xié)議:
-
TCP/IP協(xié)議:
?????? TCP:Transmission Control Protocol ——傳輸控制協(xié)議
?????? IP:Internet Protocol——互聯(lián)網(wǎng)協(xié)議
?????? TCP/IP協(xié)議是目前世界上最為廣泛的協(xié)議,是以TCP/IP為基礎(chǔ)的不同層次上多個(gè)協(xié)議的集合椎椰,也稱(chēng):TCP/IP協(xié)議族或TCP/IP協(xié)議棧,包括運(yùn)輸層境钟、網(wǎng)絡(luò)層、鏈路層俭识。它定義了電子設(shè)備如何連入Internet,以及數(shù)據(jù)如何在他們之間傳輸?shù)臉?biāo)準(zhǔn)洞渔。 -
UDP協(xié)議:
??????UDP:User Data Protocol——用戶(hù)數(shù)據(jù)報(bào)協(xié)議
??????它是與TCP相對(duì)應(yīng)面向非連接的協(xié)議套媚,它不與對(duì)方建立連接,而是直接就把數(shù)據(jù)包發(fā)送過(guò)去磁椒。
-
2.1堤瘤、TCP和UDP協(xié)議比較
協(xié)議類(lèi)型 | TCP | UDP |
---|---|---|
連接可靠性 |
三次握手 比較可靠 |
啥都不管就發(fā) |
數(shù)據(jù)大小限制 | IO流 無(wú)限制 | 數(shù)據(jù)包不能超過(guò)64K |
傳輸效率 | 占用資源大,傳輸慢 | 占用資源少浆熔,傳輸快 |
應(yīng)用案例 | FTP/SMTP 傳文件 | QQ聊天本辐、飛秋聊天 |
3、Socket和TCP/UDP的關(guān)系
4医增、基于TCP協(xié)議的Socket編程
- Scoket:客戶(hù)端一臺(tái)機(jī)器慎皱。
- 主機(jī)服務(wù)器:先打開(kāi)ServerSocket
- 基于TCP協(xié)議實(shí)現(xiàn)的網(wǎng)絡(luò)通信的類(lèi) :
- ServerSocket類(lèi):用于表示服務(wù)器端Socket
- Socket類(lèi):用于表示客戶(hù)端Socket
4.1編寫(xiě)Socket寫(xiě)入線程(繼承Thread類(lèi))
private Socket socket = null;
private DataOutputStream dataOutputStream = null;
private Scanner scanner = null;
public SocketWriter(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
while (true) {
dataOutputStream = new DataOutputStream(socket.getOutputStream());
scanner = new Scanner(System.in);
String line = scanner.nextLine();
if ("exit".equals(line)) {
System.out.println("bye-bye");
dataOutputStream.writeUTF("bye-bye");
break;
} else {
dataOutputStream.writeUTF(line);
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
try {
if (scanner != null) scanner.close();
if (dataOutputStream != null) dataOutputStream.close();
if (socket != null) socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.2編寫(xiě)Socket讀取線程(繼承Thread類(lèi))
private Socket socket = null;
private DataInputStream dataInputStream = null;
public SocketReader(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
while (true) {
dataInputStream = new DataInputStream(socket.getInputStream());
String readUTF = dataInputStream.readUTF();
System.out.println(readUTF);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (dataInputStream != null) dataInputStream.close();
if (socket != null) socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.3編寫(xiě)Socket服務(wù)端啟動(dòng)類(lèi)
public class SocketServer {
public static void main(String[] args) {
try {
//1、創(chuàng)建一個(gè)服務(wù)端
ServerSocket serverSocket = new ServerSocket(8888);
//2叶骨、接受客戶(hù)端的連接
Socket socket = serverSocket.accept();
System.out.println(socket);
System.out.println("客戶(hù)端連接成功:" + socket.getInetAddress().getHostAddress());
//3茫多、服務(wù)端啟動(dòng)讀取線程和寫(xiě)入線程
new SocketWriter(socket).start();
new SocketReader(socket).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.4編寫(xiě)Socket客戶(hù)端啟動(dòng)類(lèi)
public class SocketClient {
public static void main(String[] args){
try {
//1、根據(jù)IP和端口號(hào)創(chuàng)建一個(gè)客戶(hù)端
Socket socket=new Socket("127.0.0.1",8888);
//2忽刽、啟動(dòng)讀取和寫(xiě)入線程
new SocketReader(socket).start();
new SocketWriter(socket).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.5啟動(dòng)服務(wù)
先啟動(dòng)服務(wù)端啟動(dòng)類(lèi)天揖,在啟動(dòng)客戶(hù)端啟動(dòng)類(lèi),就可以實(shí)現(xiàn)服務(wù)端和客戶(hù)端的簡(jiǎn)單通信啦跪帝。