73、[练习]客户端进阶

专有Client类型

客户端的所有交互都相当低级:我们必须手动建立一个响应通道,建立命令,将其发送到服务器,然后在响应通道上调用 recv 来获取响应。

这是大量可以抽象掉的模板代码,而这正是我们在本练习中要做的。

 

练习

 

use crate::data::{Ticket, TicketDraft};
use crate::store::{TicketId, TicketStore};
use std::sync::mpsc::{Receiver, Sender};

pub mod data;
pub mod store;

#[derive(Clone)]
// TODO: flesh out the client implementation.
pub struct TicketStoreClient {
    sender: Sender<Command>,
}

impl TicketStoreClient {
    // Feel free to panic on all errors, for simplicity.
    pub fn insert(&self, draft: TicketDraft) -> TicketId {
        /* TODO */
    }

    pub fn get(&self, id: TicketId) -> Option<Ticket> {
        /* TODO */
    }
}

pub fn launch() -> TicketStoreClient {
    let (sender, receiver) = std::sync::mpsc::channel();
    std::thread::spawn(move || server(receiver));
    /* TODO */
}

// No longer public! This becomes an internal detail of the library now.
enum Command {
    Insert {
        draft: TicketDraft,
        response_channel: Sender<TicketId>,
    },
    Get {
        id: TicketId,
        response_channel: Sender<Option<Ticket>>,
    },
}

fn server(receiver: Receiver<Command>) {
    let mut store = TicketStore::new();
    loop {
        match receiver.recv() {
            Ok(Command::Insert {
                draft,
                response_channel,
            }) => {
                let id = store.add_ticket(draft);
                let _ = response_channel.send(id);
            }
            Ok(Command::Get {
                id,
                response_channel,
            }) => {
                let ticket = store.get(id);
                let _ = response_channel.send(ticket.cloned());
            }
            Err(_) => {
                // There are no more senders, so we can safely break
                // and shut down the server.
                break;
            }
        }
    }
}


use crate::data::{Ticket, TicketDraft};
use crate::store::{TicketId, TicketStore};
use std::sync::mpsc::{Receiver, Sender};

pub mod data;
pub mod store;

#[derive(Clone)]
// TODO: flesh out the client implementation.
pub struct TicketStoreClient {
    sender: Sender<Command>,
}

impl TicketStoreClient {
    // Feel free to panic on all errors, for simplicity.
    pub fn insert(&self, draft: TicketDraft) -> TicketId {
        // TODO
        let (response_sender, response_receiver) = std::sync::mpsc::channel();//创建一个channel
        //构造一个Command::Insert,因为是客户端,所以是把TicketDraft上传,并且设置供给接收方使用的sender
        self.sender
            .send(Command::Insert {
                draft,
                response_channel: response_sender,
            })
            .unwrap();
       	//客户端使用刚刚创建的channel对,对应接收server发回来的数据,返回值就是TicketId
        response_receiver.recv().unwrap()
        // TODO
    }

    pub fn get(&self, id: TicketId) -> Option<Ticket> {
        // TODO
        let (response_sender, response_receiver) = std::sync::mpsc::channel();
        self.sender
            .send(Command::Get {
                id,
                response_channel: response_sender,
            })
            .unwrap();
        response_receiver.recv().unwrap()
        // TODO
    }
}

pub fn launch() -> TicketStoreClient {
    let (sender, receiver) = std::sync::mpsc::channel();
    std::thread::spawn(move || server(receiver));
    // TODO
    //这里的函数创建的才是真正供给client使用的channel对,receiver给了server,我们留下了sender
    TicketStoreClient { sender }
    // TODO
}

// No longer public! This becomes an internal detail of the library now.
enum Command {
    Insert {
        draft: TicketDraft,
        response_channel: Sender<TicketId>,
    },
    Get {
        id: TicketId,
        response_channel: Sender<Option<Ticket>>,
    },
}

fn server(receiver: Receiver<Command>) {
    let mut store = TicketStore::new();
    loop {
        match receiver.recv() {
            Ok(Command::Insert {
                draft,
                response_channel,
            }) => {
                let id = store.add_ticket(draft);
                let _ = response_channel.send(id);
            }
            Ok(Command::Get {
                id,
                response_channel,
            }) => {
                let ticket = store.get(id);
                let _ = response_channel.send(ticket.cloned());
            }
            Err(_) => {
                // There are no more senders, so we can safely break
                // and shut down the server.
                break;
            }
        }
    }
}

 

阅读剩余
THE END