上一章我们简单介绍了一下grpc 概念方面的信息,这一章我们具体学习grpc 在golang的知识。

源码地址:

https://github.com/grpc/grpc-go/tree/master/examples/route_guide

关于protocol buffers 的相关信息我们这里暂不赘述,如果有读者对这部分的知识不熟悉可以参看以下链接学习。

http://doc.oschina.net/grpc?t=60133

先上我们的route_guide.proto 文件

// Interface exported by the server.
service RouteGuide {// A simple RPC. 最基本的不含流式信息的rpc 接口//// Obtains the feature at a given position.//// A feature with an empty name is returned if there's no feature at the given// position.rpc GetFeature(Point) returns (Feature) {}// A server-to-client streaming RPC. 服务器端是流式信息的接口//// Obtains the Features available within the given Rectangle.  Results are// streamed rather than returned at once (e.g. in a response message with a// repeated field), as the rectangle may cover a large area and contain a// huge number of features.rpc ListFeatures(Rectangle) returns (stream Feature) {}// A client-to-server streaming RPC.  客户端是流式信息的接口//// Accepts a stream of Points on a route being traversed, returning a// RouteSummary when traversal is completed.rpc RecordRoute(stream Point) returns (RouteSummary) {}// A Bidirectional streaming RPC. //双端流式信息的接口//// Accepts a stream of RouteNotes sent while a route is being traversed,// while receiving other RouteNotes (e.g. from other users).rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
}

相信读者已经看出来了在我们定义的服务中,普通的rpc 与流式rpc是使用stream 进行标识。

当我们完成route_guide.proto 服务的定义后,接下来我们需要从 .proto 的服务定义中生成 gRPC 客户端和服务器端的接口。我们通过 protocol buffer 的编译器 protoc 以及一个特殊的 gRPC Go 插件来完成。

具体生成步骤我们可以参考关于protocol buffers 的链接进行学习,这部分暂时只介绍代码结构的内容。

我们会生成  route_guide.pb.go 这个文件,

文件内容包括:

  • 所有用于填充,序列化和获取我们请求和响应消息类型的 protocol buffer 代码
  • 一个为客户端调用定义在RouteGuide服务的方法的接口类型(或者 存根 )
  • 一个为服务器使用定义在RouteGuide服务的方法去实现的接口类型(或者 存根 )
package routeguideimport (...)/*这部分是所有用于填充,序列化和获取我们请求和响应消息类型的 protocol buffer 代码,我们不用特别关注这些代码,所以由于篇幅的原因就不记录
如果有读者对着部分代码充满好奇可以 通过 https://github.com/grpc/grpc-go/blob/master/examples/route_guide/routeguide/route_guide.pb.go 查看
*/
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4// RouteGuideClient is the client API for RouteGuide service.
//
// 生成的RouteGuide 客户端接口代码
type RouteGuideClient interface {// A simple RPC.//GetFeature(ctx context.Context, in *Point, opts ...grpc.CallOption) (*Feature, error)// A server-to-client streaming RPC.//ListFeatures(ctx context.Context, in *Rectangle, opts ...grpc.CallOption) (RouteGuide_ListFeaturesClient, error)// A client-to-server streaming RPC.//RecordRoute(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RecordRouteClient, error)// A Bidirectional streaming RPC.RouteChat(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RouteChatClient, error)
}type routeGuideClient struct {cc *grpc.ClientConn
}func NewRouteGuideClient(cc *grpc.ClientConn) RouteGuideClient {return &routeGuideClient{cc}
}func (c *routeGuideClient) GetFeature(ctx context.Context, in *Point, opts ...grpc.CallOption) (*Feature, error) {out := new(Feature)err := c.cc.Invoke(ctx, "/routeguide.RouteGuide/GetFeature", in, out, opts...)if err != nil {return nil, err}return out, nil
}func (c *routeGuideClient) ListFeatures(ctx context.Context, in *Rectangle, opts ...grpc.CallOption) (RouteGuide_ListFeaturesClient, error) {stream, err := c.cc.NewStream(ctx, &_RouteGuide_serviceDesc.Streams[0], "/routeguide.RouteGuide/ListFeatures", opts...)if err != nil {return nil, err}x := &routeGuideListFeaturesClient{stream}if err := x.ClientStream.SendMsg(in); err != nil {return nil, err}if err := x.ClientStream.CloseSend(); err != nil {return nil, err}return x, nil
}type RouteGuide_ListFeaturesClient interface {Recv() (*Feature, error)grpc.ClientStream
}type routeGuideListFeaturesClient struct {grpc.ClientStream
}func (x *routeGuideListFeaturesClient) Recv() (*Feature, error) {m := new(Feature)if err := x.ClientStream.RecvMsg(m); err != nil {return nil, err}return m, nil
}func (c *routeGuideClient) RecordRoute(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RecordRouteClient, error) {stream, err := c.cc.NewStream(ctx, &_RouteGuide_serviceDesc.Streams[1], "/routeguide.RouteGuide/RecordRoute", opts...)if err != nil {return nil, err}x := &routeGuideRecordRouteClient{stream}return x, nil
}type RouteGuide_RecordRouteClient interface {Send(*Point) errorCloseAndRecv() (*RouteSummary, error)grpc.ClientStream
}type routeGuideRecordRouteClient struct {grpc.ClientStream
}func (x *routeGuideRecordRouteClient) Send(m *Point) error {return x.ClientStream.SendMsg(m)
}func (x *routeGuideRecordRouteClient) CloseAndRecv() (*RouteSummary, error) {if err := x.ClientStream.CloseSend(); err != nil {return nil, err}m := new(RouteSummary)if err := x.ClientStream.RecvMsg(m); err != nil {return nil, err}return m, nil
}func (c *routeGuideClient) RouteChat(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RouteChatClient, error) {stream, err := c.cc.NewStream(ctx, &_RouteGuide_serviceDesc.Streams[2], "/routeguide.RouteGuide/RouteChat", opts...)if err != nil {return nil, err}x := &routeGuideRouteChatClient{stream}return x, nil
}type RouteGuide_RouteChatClient interface {Send(*RouteNote) errorRecv() (*RouteNote, error)grpc.ClientStream
}type routeGuideRouteChatClient struct {grpc.ClientStream
}func (x *routeGuideRouteChatClient) Send(m *RouteNote) error {return x.ClientStream.SendMsg(m)
}func (x *routeGuideRouteChatClient) Recv() (*RouteNote, error) {m := new(RouteNote)if err := x.ClientStream.RecvMsg(m); err != nil {return nil, err}return m, nil
}// RouteGuideServer is the server API for RouteGuide service.
type RouteGuideServer interface {// A simple RPC.//// Obtains the feature at a given position.//// A feature with an empty name is returned if there's no feature at the given// position.GetFeature(context.Context, *Point) (*Feature, error)// A server-to-client streaming RPC.//// Obtains the Features available within the given Rectangle.  Results are// streamed rather than returned at once (e.g. in a response message with a// repeated field), as the rectangle may cover a large area and contain a// huge number of features.ListFeatures(*Rectangle, RouteGuide_ListFeaturesServer) error// A client-to-server streaming RPC.//// Accepts a stream of Points on a route being traversed, returning a// RouteSummary when traversal is completed.RecordRoute(RouteGuide_RecordRouteServer) error// A Bidirectional streaming RPC.//// Accepts a stream of RouteNotes sent while a route is being traversed,// while receiving other RouteNotes (e.g. from other users).RouteChat(RouteGuide_RouteChatServer) error
}// UnimplementedRouteGuideServer can be embedded to have forward compatible implementations.
type UnimplementedRouteGuideServer struct {
}func (*UnimplementedRouteGuideServer) GetFeature(ctx context.Context, req *Point) (*Feature, error) {return nil, status.Errorf(codes.Unimplemented, "method GetFeature not implemented")
}
func (*UnimplementedRouteGuideServer) ListFeatures(req *Rectangle, srv RouteGuide_ListFeaturesServer) error {return status.Errorf(codes.Unimplemented, "method ListFeatures not implemented")
}
func (*UnimplementedRouteGuideServer) RecordRoute(srv RouteGuide_RecordRouteServer) error {return status.Errorf(codes.Unimplemented, "method RecordRoute not implemented")
}
func (*UnimplementedRouteGuideServer) RouteChat(srv RouteGuide_RouteChatServer) error {return status.Errorf(codes.Unimplemented, "method RouteChat not implemented")
}func RegisterRouteGuideServer(s *grpc.Server, srv RouteGuideServer) {s.RegisterService(&_RouteGuide_serviceDesc, srv)
}func _RouteGuide_GetFeature_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {in := new(Point)if err := dec(in); err != nil {return nil, err}if interceptor == nil {return srv.(RouteGuideServer).GetFeature(ctx, in)}info := &grpc.UnaryServerInfo{Server:     srv,FullMethod: "/routeguide.RouteGuide/GetFeature",}handler := func(ctx context.Context, req interface{}) (interface{}, error) {return srv.(RouteGuideServer).GetFeature(ctx, req.(*Point))}return interceptor(ctx, in, info, handler)
}func _RouteGuide_ListFeatures_Handler(srv interface{}, stream grpc.ServerStream) error {m := new(Rectangle)if err := stream.RecvMsg(m); err != nil {return err}return srv.(RouteGuideServer).ListFeatures(m, &routeGuideListFeaturesServer{stream})
}type RouteGuide_ListFeaturesServer interface {Send(*Feature) errorgrpc.ServerStream
}type routeGuideListFeaturesServer struct {grpc.ServerStream
}func (x *routeGuideListFeaturesServer) Send(m *Feature) error {return x.ServerStream.SendMsg(m)
}func _RouteGuide_RecordRoute_Handler(srv interface{}, stream grpc.ServerStream) error {return srv.(RouteGuideServer).RecordRoute(&routeGuideRecordRouteServer{stream})
}type RouteGuide_RecordRouteServer interface {SendAndClose(*RouteSummary) errorRecv() (*Point, error)grpc.ServerStream
}type routeGuideRecordRouteServer struct {grpc.ServerStream
}func (x *routeGuideRecordRouteServer) SendAndClose(m *RouteSummary) error {return x.ServerStream.SendMsg(m)
}func (x *routeGuideRecordRouteServer) Recv() (*Point, error) {m := new(Point)if err := x.ServerStream.RecvMsg(m); err != nil {return nil, err}return m, nil
}func _RouteGuide_RouteChat_Handler(srv interface{}, stream grpc.ServerStream) error {return srv.(RouteGuideServer).RouteChat(&routeGuideRouteChatServer{stream})
}type RouteGuide_RouteChatServer interface {Send(*RouteNote) errorRecv() (*RouteNote, error)grpc.ServerStream
}type routeGuideRouteChatServer struct {grpc.ServerStream
}func (x *routeGuideRouteChatServer) Send(m *RouteNote) error {return x.ServerStream.SendMsg(m)
}func (x *routeGuideRouteChatServer) Recv() (*RouteNote, error) {m := new(RouteNote)if err := x.ServerStream.RecvMsg(m); err != nil {return nil, err}return m, nil
}var _RouteGuide_serviceDesc = grpc.ServiceDesc{ServiceName: "routeguide.RouteGuide",HandlerType: (*RouteGuideServer)(nil),Methods: []grpc.MethodDesc{{MethodName: "GetFeature",Handler:    _RouteGuide_GetFeature_Handler,},},Streams: []grpc.StreamDesc{{StreamName:    "ListFeatures",Handler:       _RouteGuide_ListFeatures_Handler,ServerStreams: true,},{StreamName:    "RecordRoute",Handler:       _RouteGuide_RecordRoute_Handler,ClientStreams: true,},{StreamName:    "RouteChat",Handler:       _RouteGuide_RouteChat_Handler,ServerStreams: true,ClientStreams: true,},},Metadata: "route_guide.proto",
}

不知道大家有没有从上面的部分看出来普通rpc 接口与流式rpc接口的区别。

关于流式的说明。

1:在什么情况下会在*.pb.go 文件产生Send() 和 Recv(),以及CloseAndRecv(),SendAndClose 方法

首先我们需要了解到,只有在流式处理的情况才会自动生成Send()Recv() 方法。

Recv() 方法是用来接受流式信息的,就如同在ListFeatures()方法中cient 端需要一个Recv() 方法。

Send() 方法是用来发起流式信息的,就如同在ListFeatures()方法中server端需要一个Send() 方法。但是不会有CloseAndRecv()。

在RecordRoute()方法中,在client 端就会有Send()和 CloseAndRecv() 方法,在server 端会存在SendAndClose()和Recv() 方法。

在RouteChat() 方法中无论是client端还是server 端,都只存在Send()和Recv() 方法。

其实route_guide.pb.go 中的代码信息我们不用特别的关注,只需要知道相应的接口的作用就ok了。

 

介绍完了相应的配置工作,下面我们将详细学习关于服务器代码与客户端代码的编写工作。

服务端源码地址:   https://github.com/grpc/grpc-go/blob/master/examples/route_guide/server/server.go

客户端源码地址:https://github.com/grpc/grpc-go/blob/master/examples/route_guide/client/client.go

实现RouteGuide

服务器端我们需要实现 RouteGuideServer 接口的routeGuideServer 结构类型,并且实现RouteGuideServer 的所有接口。

简单 RPC

routeGuideServer 实现了我们所有的服务方法。首先让我们看看最简单的类型 GetFeature,它从客户端拿到一个 Point 对象,然后从返回包含从数据库拿到的feature信息的 Feature.

// GetFeature returns the feature at the given point.
func (s *routeGuideServer) GetFeature(ctx context.Context, point *pb.Point) (*pb.Feature, error) {for _, feature := range s.savedFeatures {if proto.Equal(feature.Location, point) {return feature, nil}}// No feature was found, return an unnamed featurereturn &pb.Feature{Location: point}, nil
}

该方法传入了 RPC 的上下文对象,以及客户端的 Point protocol buffer请求。它返回了一个包含响应信息和errorFeature protocol buffer对象。在方法中我们用适当的信息填充 Feature,然后将其和一个nil错误一起返回,告诉 gRPC 我们完成了对 RPC 的处理,并且 Feature 可以返回给客户端。

服务器端流式 RPC

现在让我们来看看我们的一种流式 RPC。 ListFeatures 是一个服务器端的流式 RPC,所以我们需要将多个 Feature 发回给客户端。

// ListFeatures lists all features contained within the given bounding Rectangle.
func (s *routeGuideServer) ListFeatures(rect *pb.Rectangle, stream pb.RouteGuide_ListFeaturesServer) error {for _, feature := range s.savedFeatures {if inRange(feature.Location, rect) {if err := stream.Send(feature); err != nil {return err}}}return nil
}

如你所见,这里的请求对象是一个 Rectangle,客户端期望从中找到 Feature,这次我们得到了一个请求对象和一个特殊的RouteGuide_ListFeaturesServer来写入我们的响应,而不是得到方法参数中的简单请求和响应对象。

在这个方法中,我们填充了尽可能多的 Feature 对象去返回,用它们的 Send() 方法把它们写入 RouteGuide_ListFeaturesServer。最后,在我们的简单 RPC中,我们返回了一个 nil 错误告诉 gRPC 响应的写入已经完成。如果在调用过程中发生任何错误,我们会返回一个非 nil 的错误;gRPC 层会将其转化为合适的 RPC 状态通过线路发送。

客户端流式 RPC

现在让我们看看稍微复杂点的东西:客户端流方法 RecordRoute,我们通过它可以从客户端拿到一个 Point 的流,其中包括它们路径的信息。如你所见,这次这个方法没有请求参数。相反的,它拿到了一个 RouteGuide_RecordRouteServer 流,服务器可以用它来同时读 写消息——它可以用自己的 Recv() 方法接收客户端消息并且用 SendAndClose() 方法返回它的单个响应。

// RecordRoute records a route composited of a sequence of points.
//
// It gets a stream of points, and responds with statistics about the "trip":
// number of points,  number of known features visited, total distance traveled, and
// total time spent.
func (s *routeGuideServer) RecordRoute(stream pb.RouteGuide_RecordRouteServer) error {var pointCount, featureCount, distance int32var lastPoint *pb.PointstartTime := time.Now()for {point, err := stream.Recv()if err == io.EOF {endTime := time.Now()return stream.SendAndClose(&pb.RouteSummary{PointCount:   pointCount,FeatureCount: featureCount,Distance:     distance,ElapsedTime:  int32(endTime.Sub(startTime).Seconds()),})}if err != nil {return err}pointCount++for _, feature := range s.savedFeatures {if proto.Equal(feature.Location, point) {featureCount++}}if lastPoint != nil {distance += calcDistance(lastPoint, point)}lastPoint = point}
}

在方法体中,我们使用 RouteGuide_RecordRouteServerRecv() 方法去反复读取客户端的请求到一个请求对象(在这个场景下是 Point),直到没有更多的消息:服务器需要在每次调用后检查 Read() 返回的错误。如果返回值为 nil,流依然完好,可以继续读取;如果返回值为 io.EOF,消息流结束,服务器可以返回它的 RouteSummary。如果它还有其它值,我们原样返回错误,gRPC 层会把它转换为 RPC 状态。

双向流式 RPC

最后,让我们看看双向流式 RPC RouteChat()

// RouteChat receives a stream of message/location pairs, and responds with a stream of all
// previous messages at each of those locations.
func (s *routeGuideServer) RouteChat(stream pb.RouteGuide_RouteChatServer) error {for {in, err := stream.Recv()if err == io.EOF {return nil}if err != nil {return err}key := serialize(in.Location)s.mu.Lock()s.routeNotes[key] = append(s.routeNotes[key], in)// Note: this copy prevents blocking other clients while serving this one.// We don't need to do a deep copy, because elements in the slice are// insert-only and never modified.rn := make([]*pb.RouteNote, len(s.routeNotes[key]))copy(rn, s.routeNotes[key])s.mu.Unlock()for _, note := range rn {if err := stream.Send(note); err != nil {return err}}}
}

这次我们得到了一个 RouteGuide_RouteChatServer 流,和我们的客户端流的例子一样,它可以用来读写消息。但是,这次当客户端还在往 它们 的消息流中写入消息时,我们通过方法的流返回值。

这里读写的语法和客户端流方法相似,除了服务器会使用流的 Send() 方法而不是 SendAndClose(),因为它需要写多个响应。虽然客户端和服务器端总是会拿到对方写入时顺序的消息,它们可以以任意顺序读写——流的操作是完全独立的。

启动服务器

一旦我们实现了所有的方法,我们还需要启动一个gRPC服务器,这样客户端才可以使用服务。下面这段代码展示了在我们RouteGuide服务中实现的过程:

func main() {flag.Parse()lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", *port))if err != nil {log.Fatalf("failed to listen: %v", err)}var opts []grpc.ServerOptionif *tls {if *certFile == "" {*certFile = testdata.Path("server1.pem")}if *keyFile == "" {*keyFile = testdata.Path("server1.key")}creds, err := credentials.NewServerTLSFromFile(*certFile, *keyFile)if err != nil {log.Fatalf("Failed to generate credentials %v", err)}opts = []grpc.ServerOption{grpc.Creds(creds)}}grpcServer := grpc.NewServer(opts...)//newServer() new routeGuideServer structpb.RegisterRouteGuideServer(grpcServer, newServer())grpcServer.Serve(lis)
}

为了构建和启动服务器,我们需要:

  1. 使用 lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port)) 指定我们期望客户端请求的监听端口。
  2. 使用grpc.NewServer()创建 gRPC 服务器的一个实例。
  3. 在 gRPC 服务器注册我们的服务实现。
  4. 用服务器 Serve() 方法以及我们的端口信息区实现阻塞等待,直到进程被杀死或者 Stop() 被调用

 

创建客户端

下面部分,我们将介绍为 RouteGuide 服务创建一个 Go 客户端。

为了调用服务方法,我们首先创建一个 gRPC channel 和服务器交互。我们通过给 grpc.Dial() 传入服务器地址和端口号做到这点,如下:

func main() {flag.Parse()var opts []grpc.DialOptionif *tls {if *caFile == "" {*caFile = testdata.Path("ca.pem")}creds, err := credentials.NewClientTLSFromFile(*caFile, *serverHostOverride)if err != nil {log.Fatalf("Failed to create TLS credentials %v", err)}opts = append(opts, grpc.WithTransportCredentials(creds))} else {opts = append(opts, grpc.WithInsecure())}opts = append(opts, grpc.WithBlock())conn, err := grpc.Dial(*serverAddr, opts...)if err != nil {log.Fatalf("fail to dial: %v", err)}defer conn.Close()client := pb.NewRouteGuideClient(conn)// Looking for a valid featureprintFeature(client, &pb.Point{Latitude: 409146138, Longitude: -746188906})// Feature missing.printFeature(client, &pb.Point{Latitude: 0, Longitude: 0})// Looking for features between 40, -75 and 42, -73.printFeatures(client, &pb.Rectangle{Lo: &pb.Point{Latitude: 400000000, Longitude: -750000000},Hi: &pb.Point{Latitude: 420000000, Longitude: -730000000},})// RecordRouterunRecordRoute(client)// RouteChatrunRouteChat(client)
}

调用服务方法

现在让我们看看如何调用服务方法。注意,在 gRPC-Go 中,RPC以阻塞/同步模式操作,这意味着 RPC 调用等待服务器响应,同时要么返回响应,要么返回错误。

简单 RPC

调用简单 RPC GetFeature 几乎是和调用一个本地方法一样直观。

feature, err := client.GetFeature(context.Background(), &pb.Point{409146138, -746188906})
if err != nil {...
}

如你所见,我们调用了前面创建的存根上的方法。在我们的方法参数中,我们创建并且填充了一个请求的 protocol buffer 对象(例子中为 Point)。我们同时传入了一个 context.Context ,在有需要时可以让我们改变 RPC 的行为,比如超时/取消一个正在运行的 RPC。 如果调用没有返回错误,那么我们就可以从服务器返回的第一个返回值中读到响应信息。

log.Println(feature)

服务器端流式 RPC

ListFeatures 就是我们说的服务器端流方法,它会返回地理的Feature 流。 如果你已经读过创建服务器,本节的一些内容也许看上去会很熟悉——流式 RPC 是在客户端和服务器两端以一种类似的方式实现的。

rect := &pb.Rectangle{ ... }  // initialize a pb.Rectangle
stream, err := client.ListFeatures(context.Background(), rect)
if err != nil {...
}
for {feature, err := stream.Recv()if err == io.EOF {break}if err != nil {log.Fatalf("%v.ListFeatures(_) = _, %v", client, err)}log.Println(feature)
}

在简单 RPC 的例子中,我们给方法传入一个上下文和请求。然而,我们得到返回的是一个 RouteGuide_ListFeaturesClient 实例,而不是一个应答对象。客户端可以使用 RouteGuide_ListFeaturesClient 流去读取服务器的响应。

我们使用 RouteGuide_ListFeaturesClientRecv() 方法去反复读取服务器的响应到一个响应 protocol buffer 对象(在这个场景下是Feature)直到消息读取完毕:每次调用完成时,客户端都要检查从 Recv() 返回的错误 err。如果返回为 nil,流依然完好并且可以继续读取;如果返回为 io.EOF,则说明消息流已经结束;否则就一定是一个通过 err 传过来的 RPC 错误。

客户端流式 RPC

除了我们需要给方法传入一个上下文而后返回 RouteGuide_RecordRouteClient 流以外,客户端流方法 RecordRoute 和服务器端方法类似,它可以用来读 写消息。

// Create a random number of random points
r := rand.New(rand.NewSource(time.Now().UnixNano()))
pointCount := int(r.Int31n(100)) + 2 // Traverse at least two points
var points []*pb.Point
for i := 0; i < pointCount; i++ {points = append(points, randomPoint(r))
}
log.Printf("Traversing %d points.", len(points))
stream, err := client.RecordRoute(context.Background())
if err != nil {log.Fatalf("%v.RecordRoute(_) = _, %v", client, err)
}
for _, point := range points {if err := stream.Send(point); err != nil {log.Fatalf("%v.Send(%v) = %v", stream, point, err)}
}
reply, err := stream.CloseAndRecv()
if err != nil {log.Fatalf("%v.CloseAndRecv() got error %v, want %v", stream, err, nil)
}
log.Printf("Route summary: %v", reply)

RouteGuide_RecordRouteClient 有一个 Send() 方法,我们可以用它来给服务器发送请求。一旦我们完成使用 Send() 方法将客户端请求写入流,就需要调用流的 CloseAndRecv()方法,让 gRPC 知道我们已经完成了写入同时期待返回应答。我们从 CloseAndRecv() 返回的 err 中获得 RPC 的状态。如果状态为nil,那么CloseAndRecv()的第一个返回值将会是合法的服务器应答。

双向流式 RPC

最后,让我们看看双向流式 RPC RouteChat()。 和 RecordRoute 的场景类似,我们只给函数传 入一个上下文对象,拿到可以用来读写的流。但是,当服务器依然在往 他们 的消息流写入消息时,我们 通过方法流返回值。

stream, err := client.RouteChat(context.Background())
waitc := make(chan struct{})
go func() {for {in, err := stream.Recv()if err == io.EOF {// read done.close(waitc)return}if err != nil {log.Fatalf("Failed to receive a note : %v", err)}log.Printf("Got message %s at point(%d, %d)", in.Message, in.Location.Latitude, in.Location.Longitude)}
}()
for _, note := range notes {if err := stream.Send(note); err != nil {log.Fatalf("Failed to send a note: %v", err)}
}
stream.CloseSend()
<-waitc

这里读写的语法和我们的客户端流方法很像,除了在完成调用时,我们会使用流的 CloseSend() 方法。 虽然每一端获取对方信息的顺序和信息被写入的顺序一致,客户端和服务器都可以以任意顺序读写——流的操作是完全独立的。

到这里我们grpc 的介绍就完成了。

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 任务调度设计与实现(Timer、Thread、Quartz)

    一、概要1、设计目标:* 调度* 主要功能:立刻执行、延时执行、循环执行二、实现设计思路定义一个接口(ISchedule),来规范行为实现类来实现 该接口package spzc.platform.utils.schedule;/*** 调度,接口* @author live* Jan 8, 2019 11:30:18 AM*/ public interface ISched…...

    2024/4/10 2:51:54
  2. PAT乙级刷题之路1089 狼人杀-简单版 (20分)

    1089 狼人杀-简单版 (20分) 以下文字摘自《灵机一动好玩的数学》:“狼人杀”游戏分为狼人、好人两大阵营。在一局“狼人杀”游戏中,1 号玩家说:“2 号是狼人”,2 号玩家说:“3 号是好人”,3 号玩家说:“4 号是狼人”,4 号玩家说:“5 号是好人”,5 号玩家说:“4 号是…...

    2024/3/29 6:48:24
  3. 近期所用所学

    目录文件取后缀 os pg学习 top命令 rm3 自学习平台 脏数据理解 koa2 线程新用 sqlite + navicat 钉钉小程序 Cookiecutter pymupdf nametuple 字符里标点、数字、数量统计 ThreadPoolExecutor Jekins kube 简单使用 cron 定时任务 zip 相反技巧 openvino spy++ http://pan.bai…...

    2024/3/29 15:17:56
  4. 【自由生长的Python】为了能有资格放弃,tkinter第一个窗体+熟悉git环境【01】

    上手git+第一个tkinter窗体目标总结步骤Github上新建一个仓库创建一个本地git仓库tkinter的第一个窗体打标签+用标签 目标 上手git和tkinter,利用tkinter显示一个简单窗体,利用git进行代码版本控制。Github上新建一个库,用来同步文件; 本地新建一个Git仓库,存放开发中的文…...

    2024/5/8 11:32:49
  5. flea-frame-auth使用之用户子模块介绍

    用户子模块 本篇主要介绍笔者 授权模块【flea-frame-auth】下的用户子模块。 相关表表名 中文描述flea_account 账户flea_account_attr 账户扩展属性flea_user 用户flea_user_attr 用户扩展属性flea_user_rel 用户关联(角色,角色组)flea_user_group 用户组flea_user_group_r…...

    2024/3/29 15:17:54
  6. rio 10.3 vcl应用更换皮肤

    1、鼠标右击项目。选择options2、选择application->appearance选项。3、结果。...

    2024/4/18 17:06:02
  7. 如何让scss变量能够当做js变量来使用

    如何让scss变量能够当做js变量来使用 当前我们使用scss变量有两个痛点:需要手动导入 无法与js建立联系或者很难,后续不能在此基础上做一些骚操作 为了解决这两个问题,我们以创建js文件以json格式定义scss变量,然后通过配置webpack的解析规则来达到即能像普通scss一样使用,…...

    2024/3/29 15:17:52
  8. 字符串异常:String index out of range: -2

    https://blog.csdn.net/shareye1992/article/details/79975675使用字符subString操作的时候,经常会出现一个String index out of range: -1,这个是典型的下标越界,其实位置小于0,结束位置大于字符长度都会报 -1 这个异常。...

    2024/3/29 15:17:54
  9. 搭建我的网站

    今天初步搭建了我的网站。 一,用django尝试了helloword 二,去寻找网页设计的模板 三,用django尝试render了一个网页模板 四,优化了我的django项目的目录 五,搭建好找到的网页模板 好,展开记一下。。。。 django英文文档:https://docs.djangoproject.com/en/3.0/ 一,用d…...

    2024/5/8 14:33:01
  10. unity3d配置Android环境,打包发布Apk流程详解

    目录一、目的:1、以前一直有个流程图片上面介绍了Unity打包到安卓,现在我找到了链接,所以拿出来分享,一、参考:1、Unity2017发布安卓①总结:good:这个是我在2017中发布的方法,亲测很好用2、unity3d配置Android环境,打包发布Apk流程详解①总结:good:这个是我之前使用…...

    2024/3/29 15:17:49
  11. AcWing 482 合唱队形

    题目描述:N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。     合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK,  则他们的身高满足T1<…<Ti>Ti+1>…>TK(…...

    2024/3/29 15:17:49
  12. JAVA经典算法(二十四)

    题目:给一个不多于5位的正整数,要求:一、求它是几位数,二、逆序打印出各位数字。package cn.ls.lanqiao;import java.util.*;public class Test24 {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();converse(n);/** fo…...

    2024/5/8 15:56:04
  13. jboss安装 - openRASP项目部署

    本次对jboss安装以及项目部署到最后链接openRASP的过程做个简单的记录 jboss安装流程: 1、下载 jboss: 下载https://download.jboss.org/jbossas/7.1/jboss-as-7.1.1.Final/jboss-as-7.1.1.Final.zip 到E盘 2、在E盘解压 E:\jboss-as-7.1.1.Final 注意不要有空格 3、配置环境变…...

    2024/3/29 15:17:46
  14. CCF CSP 竞赛试题——报数(201912-1)

    #include <bits/stdc++.h> using namespace std;bool shouldSkip(int x) {if (x % 7 == 0) return true; // 7的倍数auto s = to_string(x);if (find(s.begin(), s.end(), 7) != s.end()) return true; // 含有数字7return false; }int main() {int n;cin >> n;vec…...

    2024/4/16 23:11:57
  15. Azure可用性保障最佳实践中文版

    作者:王文勤 时间:2017-12-101,应用程序设计避免任何单点故障 所有的组件、服务、资源以及计算节点都应该部署成多个实例,以此来避免单点故障导致可用性受影响。比如虚拟机资源,同一应用的虚拟机要部署成多实例,当单个实例故障时,服务不受影响。 认证机制也要避免单点。…...

    2024/3/29 15:17:44
  16. 8.2利用python读写文件

    在python中,读写文件有3个步骤: 1.调用open( )函数,返回一个File对象,打开文件。 2.调用File对象的read( )或write( )方法,进行读写操作。 3.调用File对象的close( )方法,关闭该文件。 读取文件 >>> >>> test1File = open(C:\\Users\\Administrator\\D…...

    2024/3/29 15:17:43
  17. 牛客网 PTA乙级真题 1003 数素数

    数素数 (20)时间限制 1000 ms 内存限制 32768 KB 代码长度限制 100 KB 判断程序 Standard (来自 小小)题目描述令Pi表示第i个素数。现任给两个正整数M <= N <= 10000,请输出PM到PN的所有素数。输入描述:输入在一行中给出M和N,其间以空格分隔。输出描述:输出从PM到PN的所…...

    2024/3/29 15:17:42
  18. unity shader 自定义定时器函数 interval

    定时器函数 在指定的时间区域内不断重复提醒。到点返回true,没到点返回false,简单吧。 当然也可以直接使用_Time.z >- 0实现。.z是计算sin(t)的。 bool timeInterval(float interval){//如果当前的时间余(间隔时间*2),返回的数是0-interval*2 // _Time.y当前时间,单位…...

    2024/3/29 15:17:41
  19. JAVA基础学习总结,day15(Map集合)

    Map 集合(双列集合接口) 特点: 1.以键值对的形式存储元素 2.通过键可以找到值 3.键是唯一的,值是可以重复的 4.Map集合的<k,v>泛型,是用来限制Map集合中的键的类型和值的类型常用子类: HashMap:存储数据采用的哈希表结构,元素的存取顺序不能保证一致 由于要保证 键…...

    2024/3/29 6:48:35
  20. 创建Java对象的四种方法 面试常见问题

    1.最常见的,使用New创建对象,大家肯定都知道 2.使用反射机制创建对象 ①使用Class类的newInstance方法创建对象 ②使用Constructor类的newInstance方法创建对象 3.调用clone方法实现Cloneable接口 4.采用序列化机制...

    2024/3/29 6:48:34

最新文章

  1. SpringBoot多数据源配置

    &#x1f353; 简介&#xff1a;java系列技术分享(&#x1f449;持续更新中…&#x1f525;) &#x1f353; 初衷:一起学习、一起进步、坚持不懈 &#x1f353; 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正&#x1f64f; &#x1f353; 希望这篇文章对你有所帮助,欢…...

    2024/5/8 16:57:40
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/5/7 10:36:02
  3. 01背包问题 小明的背包

    2.小明的背包1 - 蓝桥云课 (lanqiao.cn) #include <bits/stdc.h> using namespace std; const int N1010;//开始写的105 开小了 样例过了但最后只过了很少一部分 int n,m; int v[N],w[N]; int f[N][N];int main() {cin>>n>>m;for(int i1;i<n;i){cin>&…...

    2024/5/5 8:41:06
  4. 第十一届蓝桥杯物联网试题(省赛)

    对于通信方面&#xff0c;还是终端A、B都保持接收状态&#xff0c;当要发送的数组不为空再发送数据&#xff0c;发送完后立即清除&#xff0c;接收数据的数组不为空则处理&#xff0c;处理完后立即清除&#xff0c;分工明确 继电器不亮一般可能是电压不够 将数据加空格再加\r…...

    2024/5/7 16:25:59
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/8 6:01:22
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/7 9:45:25
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/5/4 23:54:56
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/7 14:25:14
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/5/4 23:54:56
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/5/4 23:55:05
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/5/4 23:54:56
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/5/7 11:36:39
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/5/4 23:54:56
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/6 1:40:42
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/5/4 23:54:56
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/5/4 23:55:17
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/5/7 9:26:26
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/5/4 23:54:56
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/4 23:55:06
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/5/5 8:13:33
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/5/4 23:55:16
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/5/4 23:54:58
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/6 21:42:42
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/5/4 23:54:56
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57