.proto 文件生成java代码解读
grpc是跨语言的通信框架,其自己定义.proto文件,并根据需要生成对应语言的代码。本篇只对生成出来的java代码和原.proto文件的对应关系做简单说明。
.proto文件
本demo的.proto 文件内容如下,关于proto的语法暂不说明。
syntax = "proto3";
option java_package = "com.why.grpc";
//option java_outer_classname = "OptionService";
option java_multiple_files = false;
// 定义通用的 Grpc 服务
service OptionService {
// 处理请求
rpc query (stream OrdersQuery) returns (stream OrdersAck) {}
// 处理请求
rpc result (stream OrdersQuery) returns (stream OrdersQueryResult) {}
// 处理的异步结果
rpc resultAsync (AsyncRegister) returns (stream AsyncResult) {}
}
// 定义通用的 Grpc 请求体
message OrdersAck {
string status = 1;
}
// 定义通用的 Grpc 请求体
message AsyncRegister {
string clientId = 1;
string ip = 2;
}
// 定义通用的 Grpc 请求体
message AsyncResult {
string clientId = 1;
string originReqType = 2;
string result = 3;
// 结果的字节集合
bytes messages = 4;
}
// 定义通用的 Grpc 请求体
message OrdersQuery {
string custId = 1;
string fundAccountId = 2;
string accountId = 3;
int64 clientSeqId = 4;
string clientFeatureCode = 5;
string userInfo = 6;
string password = 7;
int64 clOrdNO = 8;
int32 marketId = 9;
string securityId = 10;
int32 businessType = 11;
Side side = 12;
int32 orderQueryCondition = 13;
int64 queryIndex = 14;
int64 returnNum = 15;
int32 returnSeq = 16;
}
enum Side{
All = 0;
Buy = 1;
Sell = 2;
SellRepo = 3;
}
// 定义通用的 Grpc 响应体
message OrdersQueryResult {
string custId = 1;
string fundAccountId = 2;
string accountId = 3;
int64 clientSeqId = 4;
int32 queryResultCode = 5;
string userInfo = 6;
int64 lastIndex = 7;
int64 totalNum = 8;
repeated OrderInfo orderInfo = 9;
message OrderInfo{
int32 businessType = 1;
string securityId = 2;
string securitySymbol = 3;
int32 marketId = 4;
string accountId = 5;
Side side = 6;
string ordType = 7;
int32 orderStatus = 8;
int64 transactTime = 9;
int64 orderPrice = 10;
int64 execPrice = 11;
int64 orderQty = 12;
int64 leavesQty = 13;
int64 cumQty = 14;
int64 clientOrderNo = 15;
string orderId = 16;
string clOrdId = 17;
int64 clientSeqId = 18;
int64 originalClientOrderNo = 19;
int64 frozenTradeValue = 20;
int64 frozenFee = 21;
string orderRejectReason = 22;
}
}
java代码
由proto生成的java代码如下
package com.why.grpc;
import static io.grpc.stub.ClientCalls.asyncUnaryCall;
import static io.grpc.stub.ClientCalls.asyncServerStreamingCall;
import static io.grpc.stub.ClientCalls.asyncClientStreamingCall;
import static io.grpc.stub.ClientCalls.asyncBidiStreamingCall;
import static io.grpc.stub.ClientCalls.blockingUnaryCall;
import static io.grpc.stub.ClientCalls.blockingServerStreamingCall;
import static io.grpc.stub.ClientCalls.futureUnaryCall;
import static io.grpc.MethodDescriptor.generateFullMethodName;
import static io.grpc.stub.ServerCalls.asyncUnaryCall;
import static io.grpc.stub.ServerCalls.asyncServerStreamingCall;
import static io.grpc.stub.ServerCalls.asyncClientStreamingCall;
import static io.grpc.stub.ServerCalls.asyncBidiStreamingCall;
import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall;
import static io.grpc.stub.ServerCalls.asyncUnimplementedStreamingCall;
/**
* <pre>
* 定义通用的 Grpc 服务
* </pre>
*/
@javax.annotation.Generated(
value = "by gRPC proto compiler (version 0.15.0)",
comments = "Source: OptionService.proto")
public class OptionServiceGrpc {
private OptionServiceGrpc() {}
public static final String SERVICE_NAME = "OptionService";
// Static method descriptors that strictly reflect the proto.
@io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/1901")
public static final io.grpc.MethodDescriptor<com.why.grpc.OptionServiceOuterClass.OrdersQuery,
com.why.grpc.OptionServiceOuterClass.OrdersAck> METHOD_QUERY =
io.grpc.MethodDescriptor.create(
io.grpc.MethodDescriptor.MethodType.BIDI_STREAMING,
generateFullMethodName(
"OptionService", "query"),
io.grpc.protobuf.ProtoUtils.marshaller(com.why.grpc.OptionServiceOuterClass.OrdersQuery.getDefaultInstance()),
io.grpc.protobuf.ProtoUtils.marshaller(com.why.grpc.OptionServiceOuterClass.OrdersAck.getDefaultInstance()));
@io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/1901")
public static final io.grpc.MethodDescriptor<com.why.grpc.OptionServiceOuterClass.OrdersQuery,
com.why.grpc.OptionServiceOuterClass.OrdersQueryResult> METHOD_RESULT =
io.grpc.MethodDescriptor.create(
io.grpc.MethodDescriptor.MethodType.BIDI_STREAMING,
generateFullMethodName(
"OptionService", "result"),
io.grpc.protobuf.ProtoUtils.marshaller(com.why.grpc.OptionServiceOuterClass.OrdersQuery.getDefaultInstance()),
io.grpc.protobuf.ProtoUtils.marshaller(com.why.grpc.OptionServiceOuterClass.OrdersQueryResult.getDefaultInstance()));
@io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/1901")
public static final io.grpc.MethodDescriptor<com.why.grpc.OptionServiceOuterClass.AsyncRegister,
com.why.grpc.OptionServiceOuterClass.AsyncResult> METHOD_RESULT_ASYNC =
io.grpc.MethodDescriptor.create(
io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING,
generateFullMethodName(
"OptionService", "resultAsync"),
io.grpc.protobuf.ProtoUtils.marshaller(com.why.grpc.OptionServiceOuterClass.AsyncRegister.getDefaultInstance()),
io.grpc.protobuf.ProtoUtils.marshaller(com.why.grpc.OptionServiceOuterClass.AsyncResult.getDefaultInstance()));
/**
* Creates a new async stub that supports all call types for the service
*/
public static OptionServiceStub newStub(io.grpc.Channel channel) {
return new OptionServiceStub(channel);
}
/**
* Creates a new blocking-style stub that supports unary and streaming output calls on the service
*/
public static OptionServiceBlockingStub newBlockingStub(
io.grpc.Channel channel) {
return new OptionServiceBlockingStub(channel);
}
/**
* Creates a new ListenableFuture-style stub that supports unary and streaming output calls on the service
*/
public static OptionServiceFutureStub newFutureStub(
io.grpc.Channel channel) {
return new OptionServiceFutureStub(channel);
}
/**
* <pre>
* 定义通用的 Grpc 服务
* </pre>
*/
@java.lang.Deprecated public static interface OptionService {
/**
* <pre>
* 处理请求
* </pre>
*/
public io.grpc.stub.StreamObserver<com.why.grpc.OptionServiceOuterClass.OrdersQuery> query(
io.grpc.stub.StreamObserver<com.why.grpc.OptionServiceOuterClass.OrdersAck> responseObserver);
/**
* <pre>
* 处理请求
* </pre>
*/
public io.grpc.stub.StreamObserver<com.why.grpc.OptionServiceOuterClass.OrdersQuery> result(
io.grpc.stub.StreamObserver<com.why.grpc.OptionServiceOuterClass.OrdersQueryResult> responseObserver);
/**
* <pre>
* 处理的异步结果
* </pre>
*/
public void resultAsync(com.why.grpc.OptionServiceOuterClass.AsyncRegister request,
io.grpc.stub.StreamObserver<com.why.grpc.OptionServiceOuterClass.AsyncResult> responseObserver);
}
@io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/1469")
public static abstract class OptionServiceImplBase implements OptionService, io.grpc.BindableService {
@java.lang.Override
public io.grpc.stub.StreamObserver<com.why.grpc.OptionServiceOuterClass.OrdersQuery> query(
io.grpc.stub.StreamObserver<com.why.grpc.OptionServiceOuterClass.OrdersAck> responseObserver) {
return asyncUnimplementedStreamingCall(METHOD_QUERY, responseObserver);
}
@java.lang.Override
public io.grpc.stub.StreamObserver<com.why.grpc.OptionServiceOuterClass.OrdersQuery> result(
io.grpc.stub.StreamObserver<com.why.grpc.OptionServiceOuterClass.OrdersQueryResult> responseObserver) {
return asyncUnimplementedStreamingCall(METHOD_RESULT, responseObserver);
}
@java.lang.Override
public void resultAsync(com.why.grpc.OptionServiceOuterClass.AsyncRegister request,
io.grpc.stub.StreamObserver<com.why.grpc.OptionServiceOuterClass.AsyncResult> responseObserver) {
asyncUnimplementedUnaryCall(METHOD_RESULT_ASYNC, responseObserver);
}
@java.lang.Override public io.grpc.ServerServiceDefinition bindService() {
return OptionServiceGrpc.bindService(this);
}
}
/**
* <pre>
* 定义通用的 Grpc 服务
* </pre>
*/
@java.lang.Deprecated public static interface OptionServiceBlockingClient {
/**
* <pre>
* 处理的异步结果
* </pre>
*/
public java.util.Iterator<com.why.grpc.OptionServiceOuterClass.AsyncResult> resultAsync(
com.why.grpc.OptionServiceOuterClass.AsyncRegister request);
}
/**
* <pre>
* 定义通用的 Grpc 服务
* </pre>
*/
@java.lang.Deprecated public static interface OptionServiceFutureClient {
}
public static class OptionServiceStub extends io.grpc.stub.AbstractStub<OptionServiceStub>
implements OptionService {
private OptionServiceStub(io.grpc.Channel channel) {
super(channel);
}
private OptionServiceStub(io.grpc.Channel channel,
io.grpc.CallOptions callOptions) {
super(channel, callOptions);
}
@java.lang.Override
protected OptionServiceStub build(io.grpc.Channel channel,
io.grpc.CallOptions callOptions) {
return new OptionServiceStub(channel, callOptions);
}
@java.lang.Override
public io.grpc.stub.StreamObserver<com.why.grpc.OptionServiceOuterClass.OrdersQuery> query(
io.grpc.stub.StreamObserver<com.why.grpc.OptionServiceOuterClass.OrdersAck> responseObserver) {
return asyncBidiStreamingCall(
getChannel().newCall(METHOD_QUERY, getCallOptions()), responseObserver);
}
@java.lang.Override
public io.grpc.stub.StreamObserver<com.why.grpc.OptionServiceOuterClass.OrdersQuery> result(
io.grpc.stub.StreamObserver<com.why.grpc.OptionServiceOuterClass.OrdersQueryResult> responseObserver) {
return asyncBidiStreamingCall(
getChannel().newCall(METHOD_RESULT, getCallOptions()), responseObserver);
}
@java.lang.Override
public void resultAsync(com.why.grpc.OptionServiceOuterClass.AsyncRegister request,
io.grpc.stub.StreamObserver<com.why.grpc.OptionServiceOuterClass.AsyncResult> responseObserver) {
asyncServerStreamingCall(
getChannel().newCall(METHOD_RESULT_ASYNC, getCallOptions()), request, responseObserver);
}
}
public static class OptionServiceBlockingStub extends io.grpc.stub.AbstractStub<OptionServiceBlockingStub>
implements OptionServiceBlockingClient {
private OptionServiceBlockingStub(io.grpc.Channel channel) {
super(channel);
}
private OptionServiceBlockingStub(io.grpc.Channel channel,
io.grpc.CallOptions callOptions) {
super(channel, callOptions);
}
@java.lang.Override
protected OptionServiceBlockingStub build(io.grpc.Channel channel,
io.grpc.CallOptions callOptions) {
return new OptionServiceBlockingStub(channel, callOptions);
}
@java.lang.Override
public java.util.Iterator<com.why.grpc.OptionServiceOuterClass.AsyncResult> resultAsync(
com.why.grpc.OptionServiceOuterClass.AsyncRegister request) {
return blockingServerStreamingCall(
getChannel(), METHOD_RESULT_ASYNC, getCallOptions(), request);
}
}
public static class OptionServiceFutureStub extends io.grpc.stub.AbstractStub<OptionServiceFutureStub>
implements OptionServiceFutureClient {
private OptionServiceFutureStub(io.grpc.Channel channel) {
super(channel);
}
private OptionServiceFutureStub(io.grpc.Channel channel,
io.grpc.CallOptions callOptions) {
super(channel, callOptions);
}
@java.lang.Override
protected OptionServiceFutureStub build(io.grpc.Channel channel,
io.grpc.CallOptions callOptions) {
return new OptionServiceFutureStub(channel, callOptions);
}
}
@java.lang.Deprecated public static abstract class AbstractOptionService extends OptionServiceImplBase {}
private static final int METHODID_RESULT_ASYNC = 0;
private static final int METHODID_QUERY = 1;
private static final int METHODID_RESULT = 2;
private static class MethodHandlers<Req, Resp> implements
io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>,
io.grpc.stub.ServerCalls.ServerStreamingMethod<Req, Resp>,
io.grpc.stub.ServerCalls.ClientStreamingMethod<Req, Resp>,
io.grpc.stub.ServerCalls.BidiStreamingMethod<Req, Resp> {
private final OptionService serviceImpl;
private final int methodId;
public MethodHandlers(OptionService serviceImpl, int methodId) {
this.serviceImpl = serviceImpl;
this.methodId = methodId;
}
@java.lang.Override
@java.lang.SuppressWarnings("unchecked")
public void invoke(Req request, io.grpc.stub.StreamObserver<Resp> responseObserver) {
switch (methodId) {
case METHODID_RESULT_ASYNC:
serviceImpl.resultAsync((com.why.grpc.OptionServiceOuterClass.AsyncRegister) request,
(io.grpc.stub.StreamObserver<com.why.grpc.OptionServiceOuterClass.AsyncResult>) responseObserver);
break;
default:
throw new AssertionError();
}
}
@java.lang.Override
@java.lang.SuppressWarnings("unchecked")
public io.grpc.stub.StreamObserver<Req> invoke(
io.grpc.stub.StreamObserver<Resp> responseObserver) {
switch (methodId) {
case METHODID_QUERY:
return (io.grpc.stub.StreamObserver<Req>) serviceImpl.query(
(io.grpc.stub.StreamObserver<com.why.grpc.OptionServiceOuterClass.OrdersAck>) responseObserver);
case METHODID_RESULT:
return (io.grpc.stub.StreamObserver<Req>) serviceImpl.result(
(io.grpc.stub.StreamObserver<com.why.grpc.OptionServiceOuterClass.OrdersQueryResult>) responseObserver);
default:
throw new AssertionError();
}
}
}
public static io.grpc.ServiceDescriptor getServiceDescriptor() {
return new io.grpc.ServiceDescriptor(SERVICE_NAME,
METHOD_QUERY,
METHOD_RESULT,
METHOD_RESULT_ASYNC);
}
@java.lang.Deprecated public static io.grpc.ServerServiceDefinition bindService(
final OptionService serviceImpl) {
return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor())
.addMethod(
METHOD_QUERY,
asyncBidiStreamingCall(
new MethodHandlers<
com.why.grpc.OptionServiceOuterClass.OrdersQuery,
com.why.grpc.OptionServiceOuterClass.OrdersAck>(
serviceImpl, METHODID_QUERY)))
.addMethod(
METHOD_RESULT,
asyncBidiStreamingCall(
new MethodHandlers<
com.why.grpc.OptionServiceOuterClass.OrdersQuery,
com.why.grpc.OptionServiceOuterClass.OrdersQueryResult>(
serviceImpl, METHODID_RESULT)))
.addMethod(
METHOD_RESULT_ASYNC,
asyncServerStreamingCall(
new MethodHandlers<
com.why.grpc.OptionServiceOuterClass.AsyncRegister,
com.why.grpc.OptionServiceOuterClass.AsyncResult>(
serviceImpl, METHODID_RESULT_ASYNC)))
.build();
}
}
生成的java代码在OptionServiceGrpc类中。
该类有一下方法和内部类
OptionServiceGrpc中有一些静态变量,主要是为了构建ServiceDescriptor,和MethodDescriptor
OptionServiceGrpc方法如下:
方法名称 | 方法作用 |
---|---|
bindService | 向ServiceDescriptor中增加MethodDescriptor |
getServiceDescriptor | 获取ServiceDescriptor信息 |
newBlockingStub | 创建一个阻塞类型的stub,支持服务端单向流输出 |
newStub | 创建异步stub支持服务端类型的所有call |
newFutureStub | 创建ListenableFuture 类型的stub,支持服务端单向流输出 |
OptionServiceGrpc 中的内部类及其方法如下:
服务端接口
创建service继承OptionServiceGrpc.OptionServiceImplBase,该类中有在.proto中定义的方法。并在新创建的service中重写这些方法。这个方法若不重写项目可以正常启动,但是当客户端call对应的接口时,客户端会出现调用出错:UNIMPLEMENTED: Method OptionService/query is unimplemented 报错,服务端会爆出 Received DATA frame for an unknown stream 5的异常。
重写的方法中返回自己创建的streamObserver,在streamObserver定义发送(onNext),报错(onError)和关闭(onCompleted)的具体逻辑。
OptionServiceImplBase的bindService是sever进行addService时,绑定当前service并返回ServerServiceDefinition对象
本例中创建的service如下
package com.why.service.apiserver;
import com.orientsec.dts.option.messages.query.OrdersQuery;
import com.why.cache.ObserverCache;
import com.why.grpc.OptionServiceGrpc;
import com.why.grpc.OptionServiceOuterClass;
import io.grpc.stub.StreamObserver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Component
public class OptionService extends OptionServiceGrpc.OptionServiceImplBase {
private static final Logger log = LoggerFactory.getLogger(OptionService.class);
// private OptionApi optionApi = new OptionApi();
@Override
public StreamObserver<OptionServiceOuterClass.OrdersQuery> query(StreamObserver<OptionServiceOuterClass.OrdersAck> responseObserver) {
return new StreamObserver<OptionServiceOuterClass.OrdersQuery>() {
@Override
public void onNext(OptionServiceOuterClass.OrdersQuery value) {
log.info("接收到消息为:{}", value.getAccountId());
OptionServiceOuterClass.OrdersAck ordersAck = OptionServiceOuterClass.OrdersAck.newBuilder().setStatus("0").build();
responseObserver.onNext(ordersAck);
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
responseObserver.onNext(ordersAck);
}
@Override
public void onError(Throwable t) {
log.warn("调用出错:{}", t.getMessage());
}
@Override
public void onCompleted() {
responseObserver.onCompleted();
}
};
}
@Override
public StreamObserver<OptionServiceOuterClass.OrdersQuery> result(StreamObserver<OptionServiceOuterClass.OrdersQueryResult> responseObserver) {
ObserverCache.ordersQueryResultCache.put("option", responseObserver);
return new StreamObserver<OptionServiceOuterClass.OrdersQuery>() {
@Override
public void onNext(OptionServiceOuterClass.OrdersQuery value) {
log.info("responseObserver 建立成功:{}", value.getAccountId());
}
@Override
public void onError(Throwable t) {
log.warn("调用出错:{}", t.getMessage());
}
@Override
public void onCompleted() {
responseObserver.onCompleted();
}
};
}
@Override
public void resultAsync(OptionServiceOuterClass.AsyncRegister request, StreamObserver<OptionServiceOuterClass.AsyncResult> responseObserver) {
ObserverCache.asyncResultCache.put("option_async", responseObserver);
new StreamObserver<OptionServiceOuterClass.AsyncRegister>() {
@Override
public void onNext(OptionServiceOuterClass.AsyncRegister value) {
log.info("responseObserver 建立成功:{}", value.getClientId());
}
@Override
public void onError(Throwable t) {
log.warn("调用出错:{}", t.getMessage());
}
@Override
public void onCompleted() {
responseObserver.onCompleted();
}
};
}
private OrdersQuery converter(OptionServiceOuterClass.OrdersQuery request) {
OrdersQuery ordersQuery = new OrdersQuery();
BeanUtils.copyProperties(request, ordersQuery);
return ordersQuery;
}
}
客户端调用
客户端首先创建ManagedChannel对象,代码如下:
ManagedChannel channel = ManagedChannelBuilder
.forAddress(server.getHost(), server.getPort())
.defaultLoadBalancingPolicy("round_robin")
.nameResolverFactory(new DnsNameResolverProvider())
.idleTimeout(30, TimeUnit.SECONDS)
.usePlaintext().build();
channel 创建成功后创建stub对象,stub是由.proto文件生成的代码,创建stub的代码如下:
private Channel channel;
private final SerializeService defaultSerializeService;
private CommonServiceGrpc.CommonServiceBlockingStub blockingStub;
private OptionServiceGrpc.OptionServiceStub optionServiceBlockingStub;
ServerContext(Channel channel, SerializeService serializeService) {
this.channel = channel;
this.defaultSerializeService = serializeService;
blockingStub = CommonServiceGrpc.newBlockingStub(channel);
optionServiceBlockingStub = OptionServiceGrpc.newStub(channel);
resultAsync();
}
后面就编写自己需要调用的方法,如果是stream类型的接口,需要创建StreamObserver对象,用来接收返回值,代码如下:
/**
* 处理 gRPC 请求
*/
public GrpcResponse handle(SerializeType serializeType, GrpcRequest grpcRequest) {
SerializeService serializeService = SerializeUtils.getSerializeService(serializeType, this.defaultSerializeService);
ByteString bytes = serializeService.serialize(grpcRequest);
int value = (serializeType == null ? -1 : serializeType.getValue());
GrpcService.Request request = GrpcService.Request.newBuilder().setSerialize(value).setRequest(bytes).build();
GrpcService.Response response = null;
try {
System.out.println("blockingStub: " + blockingStub.toString());
response = blockingStub.handle(request);
} catch (Exception exception) {
log.warn("rpc exception: {}", exception.getMessage());
if ("UNAVAILABLE: io exception".equals(exception.getMessage().trim())) {
response = blockingStub.handle(request);
}
}
return serializeService.deserialize(response);
}
/**
* 处理 gRPC 请求
*/
public GrpcResponse query(OptionServiceOuterClass.OrdersQuery ordersQuery) {
StreamObserver<OptionServiceOuterClass.OrdersAck> queryStreamObserver = new StreamObserver<OptionServiceOuterClass.OrdersAck>() {
@Override
public void onNext(OptionServiceOuterClass.OrdersAck value) {
log.info("得到结果为 OrdersAck:{}", value);
}
@Override
public void onError(Throwable t) {
log.warn("调用出错:{}", t.getMessage());
}
@Override
public void onCompleted() {
log.info("调用完成");
}
};
OptionServiceOuterClass.OrdersQuery query = OptionServiceOuterClass.OrdersQuery.newBuilder().setBusinessType(1).setAccountId("1").build();
StreamObserver<OptionServiceOuterClass.OrdersQuery> resultStreamObserver = null;
try {
System.out.println("optionServiceBlockingStub: " + optionServiceBlockingStub.toString());
resultStreamObserver = optionServiceBlockingStub.query(queryStreamObserver);
} catch (Exception exception) {
log.warn("rpc exception: {}", exception.getMessage());
if ("UNAVAILABLE: io exception".equals(exception.getMessage().trim())) {
resultStreamObserver = optionServiceBlockingStub.query(queryStreamObserver);
}
}
assert resultStreamObserver != null;
resultStreamObserver.onNext(query);
result(query);
resultStreamObserver.onNext(query);
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
resultStreamObserver.onNext(query);
// return serializeService.deserialize(response);
return null;
}
这样就可以实现简单的grpc客户端和服务端的通信了。