今日雞湯
紅色是心中永不褪色的赤誠(chéng)
Socket套接字
操作系統(tǒng)為網(wǎng)絡(luò)編程提供了Socket api
, Socket是基于TCP/IP協(xié)議的網(wǎng)絡(luò)通信的基本單元, 基于Socket的網(wǎng)絡(luò)程序開發(fā)就是網(wǎng)絡(luò)編程.
- 由于直接與應(yīng)用層聯(lián)系的是傳輸層, 所以針對(duì)應(yīng)用層協(xié)議(TCP, UDP), Shocket提供了三種套接字, 分別是
流套接字(使用TCP)
,數(shù)據(jù)報(bào)套接字(使用UDP)
,原始套接字
先簡(jiǎn)單介紹一下TCP和UDP吧
- TCP傳輸有連接, 可靠傳輸, 面向字節(jié)流, 全雙工
(1)有連接: 在數(shù)據(jù)轉(zhuǎn)發(fā)之前會(huì)先建立連接, 這里涉及到揮手, 之后會(huì)具體介紹
(2)可靠傳輸: 可靠傳輸不代表一定會(huì)傳輸過去, 而是說發(fā)送方會(huì)知道是否發(fā)送成功, 如果失敗, 則會(huì)重新發(fā)送
(3)面向字節(jié)流: 以字節(jié)為單位
(4) 全雙工: 在發(fā)送的同時(shí)也可以作為接收方來接收數(shù)據(jù)- UDP傳輸無連接, 不可靠, 面向報(bào)文段, 全雙工
(1) 無連接: 在數(shù)據(jù)轉(zhuǎn)發(fā)之前發(fā)送方和接收方不會(huì)建立連接
(2) 不可靠: 發(fā)送方在發(fā)送之后不會(huì)管是否被接受
(3) 面向報(bào)文段: 發(fā)送數(shù)據(jù)以報(bào)文段為單位
(4) 全雙工: 在發(fā)送數(shù)據(jù)的同時(shí)可以作為接收方接受數(shù)據(jù)
基于UDP來實(shí)現(xiàn)一個(gè)網(wǎng)絡(luò)通信程序
在這里要接觸到兩個(gè)類: DatagramSocket
, 和DatagramPacket
.
端口號(hào)
用于指定區(qū)分進(jìn)程, 因此一個(gè)端口只能同時(shí)被一個(gè)進(jìn)程使用(實(shí)際上端口是被Socket對(duì)象使用), 一個(gè)進(jìn)程可以同時(shí)使用多個(gè)進(jìn)程
(這里對(duì)端口號(hào)不熟悉有疑惑的同志可以先查閱了解一下端口號(hào)的作用)
當(dāng)進(jìn)程fock
一個(gè)子進(jìn)程時(shí), 可以實(shí)現(xiàn)一個(gè)端口被多個(gè)進(jìn)程使用, 但是java并沒有提供fock的api
DatagramSocket類
通過DatagramSocket類創(chuàng)建的對(duì)象就是一個(gè)Socket, 操作系統(tǒng)將這個(gè)socket對(duì)象看成是一個(gè)文件, 之前普通文件對(duì)應(yīng)的硬件為硬盤, 這里的socket對(duì)應(yīng)的硬件是網(wǎng)卡, 有了socket之后就可以通過socket來操作網(wǎng)卡, 從而實(shí)現(xiàn)與其他主機(jī)的通信了.
下面看一下DatagramSocket類中的方法
-
構(gòu)造方法
構(gòu)造方法無參時(shí), 會(huì)為當(dāng)前的通信線程隨機(jī)安排一個(gè)空閑端口, 指定port參數(shù)時(shí)會(huì)為當(dāng)前線程中的socket顯式綁定一個(gè)端口.
通常為服務(wù)器顯式指定一個(gè)端口, (因?yàn)榉?wù)器上的端口使用情況程序員是清楚的, 指定端口之后方便客戶端進(jìn)行訪問) 客戶端隨機(jī)分配空閑端口(因?yàn)椴淮_定當(dāng)前哪些端口空閑)
-
發(fā)送和接收
這兩個(gè)方法用于客戶端表示
向服務(wù)器發(fā)起請(qǐng)求, 接受來自服務(wù)器端的響應(yīng)
這兩個(gè)方法用于服務(wù)器表示接受客戶端的請(qǐng)求, 向客戶端發(fā)起響應(yīng)
-
關(guān)閉(釋放資源)
DatagramPacket類
通過DatagramPacket類創(chuàng)建的對(duì)象是一個(gè)數(shù)據(jù)報(bào). UDP是面向報(bào)文段, 創(chuàng)建了DatagramPacket對(duì)象之后便可以使用數(shù)據(jù)報(bào)來進(jìn)行通信, 下面看看這個(gè)類的方法
- 構(gòu)造方法
由構(gòu)造方法可以知道, 在創(chuàng)建數(shù)據(jù)報(bào)時(shí)可以使用緩沖區(qū)數(shù)組, 并需要指定目的ip地址和目的端口號(hào).
注意這里的緩沖數(shù)組是一個(gè)空數(shù)組, 在接收到來自客戶端的報(bào)文段時(shí)會(huì)填充, 屬于輸出型參數(shù)
還有一些獲取當(dāng)前報(bào)文段內(nèi)容, 獲取當(dāng)前報(bào)文段中的源ip, 獲取當(dāng)前報(bào)文段中的源端口等就不一 一列了
基于UDP的服務(wù)器端代碼
服務(wù)器要完成三個(gè)任務(wù):文章來源:http://www.zghlxwxcb.cn/news/detail-717448.html
- 接受來自客戶端的報(bào)文段(請(qǐng)求)
- 根據(jù)請(qǐng)求來計(jì)算響應(yīng)(復(fù)雜業(yè)務(wù)邏輯)
- 將響應(yīng)發(fā)送到客戶端
public class echoServer1 {
private DatagramSocket socket = null;
//創(chuàng)建pocket對(duì)象, 這里是服務(wù)器端, 需指定端口號(hào)
public echoServer1(int port) throws SocketException {
socket = new DatagramSocket(port);
}
public void start() throws IOException {
System.out.println("服務(wù)器啟動(dòng): ");
while (true){
//創(chuàng)建數(shù)據(jù)報(bào), 用于接受來自客戶端的數(shù)據(jù)報(bào)
DatagramPacket requestPacket = new DatagramPacket(new byte[1024], 1024);
//這里的receive會(huì)陷入阻塞, 直到有數(shù)據(jù)報(bào)發(fā)過來
socket.receive(requestPacket);
//將數(shù)據(jù)報(bào)中的內(nèi)容轉(zhuǎn)換為字符串, 方便計(jì)算響應(yīng)
//上面的緩沖數(shù)組不一定會(huì)填滿, 這里只獲取實(shí)際長(zhǎng)度即可(getLength)
String request = new String(requestPacket.getData(), 0, requestPacket.getLength());
//調(diào)用計(jì)算方法, 計(jì)算響應(yīng)
String response = handle(request);
//注意此處用response.getBytes().length, 而不用responsePacket.length(), 因?yàn)閞esponsePacket中可能含有漢字, 漢字轉(zhuǎn)換為byte類型之后字節(jié)個(gè)數(shù)與字符個(gè)數(shù)不一樣
DatagramPacket responsePacket =new DatagramPacket(response.getBytes(), response.getBytes().length,
requestPacket.getSocketAddress());
//將響應(yīng)發(fā)送給客戶端
socket.send(responsePacket);
//打印日志
System.out.printf("[%s, %d], req: %s, resp: %s \n", requestPacket.getAddress().toString(), requestPacket.getPort(),
request, response);
}
}
public String handle(String request){
//這里的響應(yīng)只是簡(jiǎn)單的回顯, 沒有復(fù)雜的代碼邏輯
return request;
}
public static void main(String[] args) throws IOException {
//創(chuàng)建服務(wù)器對(duì)象, 指定端口為1025, 此端口號(hào)與客戶端發(fā)送請(qǐng)求時(shí)指定的端口號(hào)需一致
echoServer1 server1 = new echoServer1(1025);
//調(diào)用start方法, 啟動(dòng)服務(wù)器
server1.start();
}
}
基于UDP的客戶端代碼
客戶端要完成四個(gè)任務(wù):文章來源地址http://www.zghlxwxcb.cn/news/detail-717448.html
- 從控制臺(tái)接收數(shù)據(jù)
- 根據(jù)數(shù)據(jù)向服務(wù)器發(fā)送請(qǐng)求
- 接受服務(wù)器的響應(yīng)
- 將服務(wù)器響應(yīng)打印出來
public
到了這里,關(guān)于基于UDP/TCP的網(wǎng)絡(luò)通信編程實(shí)現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!