欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報邀請碼778899分享:Java網(wǎng)絡(luò)編程BIO/NIO

柚子快報邀請碼778899分享:Java網(wǎng)絡(luò)編程BIO/NIO

http://yzkb.51969.com/

Java網(wǎng)絡(luò)編程

網(wǎng)絡(luò)編程的基礎(chǔ)知識

Socket

Socket是應(yīng)用層與TCP/IP協(xié)議族通信的中間軟件抽象層,它是一組接口。在設(shè)計模式中,Socket其實就是一個門面模式,它把復(fù)雜的TCP/IP協(xié)議族隱藏在Socket接口后面,對用戶來說,一組簡單的接口就是全部,讓Socket去組織數(shù)據(jù),以符合指定的協(xié)議。

主機 A 的應(yīng)用程序要能和主機 B 的應(yīng)用程序通信,必須通過 Socket 建立連接,而建立 Socket 連接必須需要底層TCP/IP 協(xié)議來建立 TCP 連接。建立 TCP 連接需要底層 IP 協(xié)議來尋址網(wǎng)絡(luò)中的主機。

我們知道網(wǎng)絡(luò)層使用的 IP 協(xié)議可以幫助我們根據(jù) IP 地址來找到目標主機,但是一臺主機上可能運行著多個應(yīng)用程序,如何才能與指定的應(yīng)用程序通信就要通過 TCP 或 UPD 的地址也就是端口號來指定。這樣就可以通過一個 Socket 實例唯一代表一個主機上的一個應(yīng)用程序的通信鏈路了。

短連接與長連接

短連接:

連接->傳輸數(shù)據(jù)->關(guān)閉連接

傳統(tǒng)HTTP是無狀態(tài)的,瀏覽器和服務(wù)器每進行一次HTTP操作,就建立一次連接,但任務(wù)結(jié)束就中斷連接。

也可以這樣說:短連接是指SOCKET連接后發(fā)送后接收完數(shù)據(jù)后馬上斷開連接。

長連接:

連接->傳輸數(shù)據(jù)->保持連接 -> 傳輸數(shù)據(jù)-> 。。。 ->關(guān)閉連接。

長連接指建立SOCKET連接后不管是否使用都保持連接。

什么時候用長連接,短連接?

長連接多用于操作頻繁,點對點的通訊,而且連接數(shù)不能太多情況,。每個TCP連接都需要三步握手,這需要時間,如果每個操作都是先連接,再操作的話那么處理速度會降低很多,所以每個操作完后都不斷開,下次處理時直接發(fā)送數(shù)據(jù)包就OK了,不用建立TCP連接。例如:數(shù)據(jù)庫的連接用長連接, 如果用短連接頻繁的通信會造成socket錯誤,而且頻繁的socket 創(chuàng)建也是對資源的浪費。

而像WEB網(wǎng)站的http服務(wù)一般都用短鏈接,因為長連接對于服務(wù)端來說會耗費一定的資源,而像WEB網(wǎng)站這么頻繁的成千上萬甚至上億客戶端的連接用短連接會更省一些資源。

網(wǎng)絡(luò)通訊流程

在通信編程里提供服務(wù)的叫服務(wù)端,連接服務(wù)端使用服務(wù)的叫客戶端。

在開發(fā)過程中,如果類的名字有Server或者ServerSocket的,表示這個類是給服務(wù)端容納網(wǎng)絡(luò)服務(wù)用的,如果類的名字只有Socket的,那么表示這是負責(zé)具體的網(wǎng)絡(luò)讀寫的。那么對于服務(wù)端來說ServerSocket就只是個場所(娛樂場所),具體和客戶端溝通的還是一個一個的socket(娛樂事件),所以在通信編程里,ServerSocket并不負責(zé)具體的網(wǎng)絡(luò)讀寫,ServerSocket就只是負責(zé)接收客戶端連接后,新啟一個socket來和客戶端進行溝通。這一點對所有模式的通信編程都是適用的。

在通信編程里,我們關(guān)注的其實也就是三個事情

1、連接(客戶端連接服務(wù)器,服務(wù)器等待和接收連接)

2、讀網(wǎng)絡(luò)數(shù)據(jù)

3、寫網(wǎng)絡(luò)數(shù)據(jù)

所有模式的通信編程都是圍繞著這三件事情進行的。服務(wù)端提供IP和監(jiān)聽端口,客戶端通過連接操作想服務(wù)端監(jiān)聽的地址發(fā)起連接請求,通過三次握手連接,如果連接成功建立,雙方就可以通過套接字進行通信。

JDK網(wǎng)絡(luò)編程(BIO)

傳統(tǒng)的同步阻塞模型開發(fā)中,ServerSocket負責(zé)綁定IP地址,啟動監(jiān)聽端口;Socket負責(zé)發(fā)起連接操作。連接成功后,雙方通過輸入和輸出流進行同步阻塞式通信。代碼如下:

public class BIOClient {

public static void main(String[] args) {

Socket client = new Socket();

try {

client.connect(new InetSocketAddress("127.0.0.1", 12345));

System.out.println("客戶端發(fā)送數(shù)據(jù):");

BufferedReader sys=new BufferedReader(new InputStreamReader(System.in));

String msg = sys.readLine();

BufferedWriter bo = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));

BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));

bo.write(msg);

bo.newLine();

bo.flush();

msg = br.readLine();

System.out.println("接受服務(wù)器消息:" + msg);

bo.close();

br.close();

} catch (Exception e) {

e.printStackTrace();

}finally {

try {

client.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

public class BIOServer {

public static void main(String[] args) {

try {

ServerSocket ss = new ServerSocket(12345);

System.out.println("服務(wù)端啟動");

while (true) {

new Thread(new ServerTask(ss.accept())).start();

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

class ServerTask implements Runnable {

Socket socket;

public ServerTask(Socket s) {

this.socket = s;

}

@Override

public void run() {

try {

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

String msg = br.readLine();

System.out.println("接收客戶端數(shù)據(jù):" + msg);

bw.write("hello client");

bw.newLine();

bw.flush();

bw.close();

br.close();

} catch (Exception e) {

e.printStackTrace();

} finally {

try {

socket.close();

} catch (Exception e) {

}

}

}

}

NIO網(wǎng)絡(luò)編程

網(wǎng)絡(luò)三種I/O模型

分類: BIO:(同步 阻塞)jdk1.4以前 java.io包 NIO:(同步 非阻塞)jdk1.4 java.nio包 AIO:(異步 非阻塞)jdk1.7 java.nio包

如何如何理解:

當(dāng)我們?nèi)コ燥埧梢杂幸韵聨追N模式:

飯店 -> 服務(wù)器

飯菜-> 數(shù)據(jù)

飯菜好了-> 數(shù)據(jù)就緒

端菜 /送菜 -> 數(shù)據(jù)讀取

BIO:食堂排隊打飯模式:排隊在窗口,打好才走; NIO:點單、等待被叫模式:等待被叫,好了自己去端; AIO:包廂模式:點單后菜直接被端上桌。

阻塞與非阻塞

菜沒好,要不要死等 -> 數(shù)據(jù)就緒前要不要等待? 阻塞: 沒有數(shù)據(jù)傳過來時,讀會阻塞直到有數(shù)據(jù);緩沖區(qū)滿時,寫操作也會阻塞。 非阻塞: 遇到這些情況,都是直接返回

同步與異步

菜好了,誰端 -> 數(shù)據(jù)就緒后,數(shù)據(jù)操作誰完成?

同步: 數(shù)據(jù)就緒后需要自己去讀是同步

異步: 數(shù)據(jù)就緒直接讀好再回調(diào)給程序是異步

NIO和BIO的主要區(qū)別

面向流與面向緩沖

Java NIO和IO之間第一個最大的區(qū)別是,IO是面向流的,NIO是面向緩沖區(qū)的。 Java IO面向流意味著每次從流中讀一個或多個字節(jié),直至讀取所有字節(jié),它們沒有被緩存在任何地方。此外,它不能前后移動流中的數(shù)據(jù)。如果需要前后移動從流中讀取的數(shù)據(jù),需要先將它緩存到一個緩沖區(qū)。

Java NIO的緩沖導(dǎo)向方法略有不同。數(shù)據(jù)讀取到一個它稍后處理的緩沖區(qū),需要時可在緩沖區(qū)中前后移動。這就增加了處理過程中的靈活性。但是,還需要檢查是否該緩沖區(qū)中包含所有需要處理的數(shù)據(jù)。而且,需確保當(dāng)更多的數(shù)據(jù)讀入緩沖區(qū)時,不要覆蓋緩沖區(qū)里尚未處理的數(shù)據(jù)。

NIO三大核心組件

NIO有三大核心組件:Selector選擇器、Channel管道、buffer緩沖區(qū)。

Selector

Selector的英文含義是“選擇器”,也可以稱為為“輪詢代理器”、“事件訂閱器”、“channel容器管理機”都行。

Java NIO的選擇器允許一個單獨的線程來監(jiān)視多個輸入通道,你可以注冊多個通道使用一個選擇器(Selectors),然后使用一個單獨的線程來操作這個選擇器,進而“選擇”通道:這些通道里已經(jīng)有可以處理的輸入,或者選擇已準備寫入的通道。這種選擇機制,使得一個單獨的線程很容易來管理多個通道。

應(yīng)用程序?qū)⑾騍elector對象注冊需要它關(guān)注的Channel,以及具體的某一個Channel會對哪些IO事件感興趣。Selector中也會維護一個“已經(jīng)注冊的Channel”的容器。

Channel

通道,被建立的一個應(yīng)用程序和操作系統(tǒng)交互事件、傳遞內(nèi)容的渠道(注意是連接到操作系統(tǒng))。那么既然是和操作系統(tǒng)進行內(nèi)容的傳遞,那么說明應(yīng)用程序可以通過通道讀取數(shù)據(jù),也可以通過通道向操作系統(tǒng)寫數(shù)據(jù),而且可以同時進行讀寫。

所有被Selector(選擇器)注冊的通道,只能是繼承了SelectableChannel類的子類。ServerSocketChannel:應(yīng)用服務(wù)器程序的監(jiān)聽通道。只有通過這個通道,應(yīng)用程序才能向操作系統(tǒng)注冊支持“多路復(fù)用IO”的端口監(jiān)聽。同時支持UDP協(xié)議和TCP協(xié)議。ScoketChannel:TCP Socket套接字的監(jiān)聽通道,一個Socket套接字對應(yīng)了一個客戶端IP:端口到服務(wù)器IP:端口的通信連接。

通道中的數(shù)據(jù)總是要先讀到一個Buffer,或者總是要從一個Buffer中寫入。

buffer緩沖區(qū)

網(wǎng)絡(luò)通訊中負責(zé)數(shù)據(jù)讀寫的區(qū)域

NIO工作流程圖

NIO網(wǎng)絡(luò)編程

客戶端

public class Client {

private static NioClientHandle nioClientHandle;

public static void start() {

if (null == nioClientHandle) {

nioClientHandle = new NioClientHandle("127.0.0.1", 5555);

}

new Thread(nioClientHandle, "client").start();

}

public static boolean sendMsg(String msg) throws IOException {

nioClientHandle.sendMsg(msg);

return true;

}

public static void main(String[] args) throws IOException {

start();

Scanner sc = new Scanner(System.in);

while (Client.sendMsg(sc.next())) ;

}

public class NioClientHandle implements Runnable {

private String ip;

private Integer port;

private Selector selector;

private SocketChannel channel;

private volatile boolean started;

public NioClientHandle(String ip, int port) {

this.ip = ip;

this.port = port;

try {

//創(chuàng)建選擇器

selector = Selector.open();

//打開監(jiān)聽通道

channel = SocketChannel.open();

//false :非阻塞 true: 阻塞

channel.configureBlocking(false);

started = true;

} catch (IOException e) {

e.printStackTrace();

}

}

public void stop() {

this.started = false;

}

@Override

public void run() {

boolean connect = false;

try {

connect = channel.connect(new InetSocketAddress(ip, port));

if (connect) {

channel.register(selector, SelectionKey.OP_READ);

} else {

channel.register(selector, SelectionKey.OP_CONNECT);

}

} catch (IOException e) {

e.printStackTrace();

}

while (started) {

try {

selector.select();

Set selectionKeys = selector.selectedKeys();

Iterator iterator = selectionKeys.iterator();

while (iterator.hasNext()) {

SelectionKey key = iterator.next();

iterator.remove();

handle(key);

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

private void handle(SelectionKey key) throws IOException {

if (key.isValid()) {

SocketChannel channel = (SocketChannel) key.channel();

if (key.isConnectable()) {

if (channel.finishConnect()) {

channel.register(selector, SelectionKey.OP_READ);

} else {

System.exit(-1);

}

}

if (key.isReadable()) {

ByteBuffer buffer = ByteBuffer.allocate(1024);

int readBytes = channel.read(buffer);

if (readBytes > 0) {

buffer.flip();

byte[] bytes = new byte[buffer.remaining()];

buffer.get(bytes);

System.out.println(new String(bytes, StandardCharsets.UTF_8));

}

}

}

}

public void sendMsg(String msg) throws IOException {

doWrite(channel, msg);

}

public static void doWrite(SocketChannel channel, String msg) throws IOException {

//消息轉(zhuǎn)成字節(jié)數(shù)據(jù)

byte[] bytes = msg.getBytes(StandardCharsets.UTF_8);

//開辟一個內(nèi)存空間

ByteBuffer writeBuffer = ByteBuffer.allocate(1024);

//消息寫入ByteBuffer

writeBuffer.put(bytes);

//翻轉(zhuǎn),充值ByteBuffer

writeBuffer.flip();

//通過channel寫出數(shù)據(jù)

channel.write(writeBuffer);

}

}

服務(wù)端

public class NioServer {

private static NioServerHandle nioServerHandle;

public static void start(){

if(nioServerHandle !=null) nioServerHandle.stop();

nioServerHandle = new NioServerHandle(5555);

new Thread(nioServerHandle,"Server").start();

}

public static void main(String[] args){

start();

}

}

public class NioServerHandle implements Runnable{

private Selector selector;//reactor

private ServerSocketChannel serverChannel;

private volatile boolean started;

public NioServerHandle(int port) {

try{

//創(chuàng)建選擇器

selector = Selector.open();

//打開監(jiān)聽通道

serverChannel = ServerSocketChannel.open();

//如果為 true,則此通道將被置于阻塞模式;

// 如果為 false,則此通道將被置于非阻塞模式

serverChannel.configureBlocking(false);//開啟非阻塞模式

serverChannel.socket().bind(new InetSocketAddress(port));

serverChannel.register(selector, SelectionKey.OP_ACCEPT);

//標記服務(wù)器已開啟

started = true;

System.out.println("服務(wù)器已啟動,端口號:" + port);

}catch(Exception e){

e.printStackTrace();

System.exit(1);

}

}

public void stop(){

started = false;

}

@Override

public void run() {

//循環(huán)遍歷selector

while(started){

try{

//阻塞,只有當(dāng)至少一個注冊的事件發(fā)生的時候才會繼續(xù).

selector.select();

Set keys = selector.selectedKeys();

Iterator it = keys.iterator();

SelectionKey key = null;

while(it.hasNext()){

key = it.next();

it.remove();

try{

handleInput(key);

}catch(Exception e){

if(key != null){

key.cancel();

if(key.channel() != null){

key.channel().close();

}

}

}

}

}catch(Throwable t){

t.printStackTrace();

}

}

//selector關(guān)閉后會自動釋放里面管理的資源

if(selector != null)

try{

selector.close();

}catch (Exception e) {

e.printStackTrace();

}

}

private void handleInput(SelectionKey key) throws IOException{

if(key.isValid()){

//處理新接入的請求消息

if(key.isAcceptable()){

ServerSocketChannel ssc = (ServerSocketChannel)key.channel();

SocketChannel sc = ssc.accept();

System.out.println("建立連接");

sc.configureBlocking(false);

sc.register(selector,SelectionKey.OP_READ);

}

//讀消息

if(key.isReadable()){

System.out.println("socket channel 數(shù)據(jù)準備完成,可以去讀取");

SocketChannel sc = (SocketChannel) key.channel();

//創(chuàng)建ByteBuffer,并開辟一個1M的緩沖區(qū)

ByteBuffer buffer = ByteBuffer.allocate(1024);

//讀取請求碼流,返回讀取到的字節(jié)數(shù)

int readBytes = sc.read(buffer);

//讀取到字節(jié),對字節(jié)進行編解碼

if(readBytes>0){

//將緩沖區(qū)當(dāng)前的limit設(shè)置為position,position=0,

// 用于后續(xù)對緩沖區(qū)的讀取操作

buffer.flip();

//根據(jù)緩沖區(qū)可讀字節(jié)數(shù)創(chuàng)建字節(jié)數(shù)組

byte[] bytes = new byte[buffer.remaining()];

//將緩沖區(qū)可讀字節(jié)數(shù)組復(fù)制到新建的數(shù)組中

buffer.get(bytes);

String message = new String(bytes,"UTF-8");

System.out.println("服務(wù)器收到消息:" + message);

//處理數(shù)據(jù)

String result = "服務(wù)器響應(yīng)消息:"+ message ;

//發(fā)送應(yīng)答消息

doWrite(sc,result);

}

//鏈路已經(jīng)關(guān)閉,釋放資源

else if(readBytes<0){

key.cancel();

sc.close();

}

}

}

}

//發(fā)送應(yīng)答消息

private void doWrite(SocketChannel channel,String response)

throws IOException {

//將消息編碼為字節(jié)數(shù)組

byte[] bytes = response.getBytes();

//根據(jù)數(shù)組容量創(chuàng)建ByteBuffer

ByteBuffer writeBuffer = ByteBuffer.allocate(bytes.length);

//將字節(jié)數(shù)組復(fù)制到緩沖區(qū)

writeBuffer.put(bytes);

//flip操作

writeBuffer.flip();

//發(fā)送緩沖區(qū)的字節(jié)數(shù)組

channel.write(writeBuffer);

}

}

Reactor模式,核心流程:

注冊感興趣的事件 ->掃描是否有感興趣的事件發(fā)生 -> 事件發(fā)生后做出相應(yīng)的處理

單線程Reactor

多線程Reactor

主從多線程Reactor

柚子快報邀請碼778899分享:Java網(wǎng)絡(luò)編程BIO/NIO

http://yzkb.51969.com/

精彩內(nèi)容

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://m.gantiao.com.cn/post/19593575.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機訪問

文章目錄