ProtoBuf的优缺点不再叙说,本篇主要介绍是WCF服务端和WCF客户端通过ProtoBuf传输数据的例子。
1 数据流:

2 WCF服务端:
- 2.1 需要在项目引入
protobuf-net
- 2.2 创建需要在服务中需要传递的类型
UserInfo
,WCF服务
把它序列化为ProtoBuf
二进制数据传到客户端,供客户端调用并解析为UserInfo
类。注意服务端和客户端使用的UserInfo
类必须一样,这样才能解析出来。
UserInfo类:
using ProtoBuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FG_WCFServer
{
/// <summary>
/// 用户信息类
/// </summary>
[ProtoContract]
public class UserInfo
{
/// <summary>
/// 用户编号
/// </summary>
[ProtoMember(1)]
public int ID { get; set; }
/// <summary>
/// 账号
/// </summary>
[ProtoMember(2)]
public string UserAccount { get; set; }
/// <summary>
/// 密码
/// </summary>
[ProtoMember(3)]
public string UserPassWord { get; set; }
/// <summary>
/// 姓名
/// </summary>
[ProtoMember(4)]
public string UserName { get; set; }
/// <summary>
/// 性别
/// </summary>
[ProtoMember(5)]
public string UserSex { get; set; }
/// <summary>
/// 职位
/// </summary>
[ProtoMember(6)]
public string UserOffice { get; set; }
/// <summary>
/// 联系方式
/// </summary>
[ProtoMember(7)]
public string UserPhone { get; set; }
/// <summary>
/// 邮箱
/// </summary>
[ProtoMember(8)]
public string UserEmail { get; set; }
/// <summary>
/// 角色
/// </summary>
[ProtoMember(9)]
public int UserCharacter { get; set; }
/// <summary>
/// 所属工厂编号
/// </summary>
[ProtoMember(10)]
public int UserFactoryNum { get; set; }
/// <summary>
/// 上次登录时间
/// </summary>
[ProtoMember(11)]
public DateTime UserLastLoginTime { get; set; }
}
}
- 2.3 封装ProtoBuf序列化方法
/// <summary>
/// ProtoBuf序列化类用于序列化及解析数据
/// </summary>
public class SerializBaseModel
{
/// <summary>
/// 序列化类型数据
/// </summary>
/// <returns></returns>
public static byte[] SerializeModel<T>(T model)where T:new ()
{
try
{
using (MemoryStream ms = new MemoryStream())
{
Serializer.Serialize(ms, model);
ms.Position = 0;
return ms.ToArray();
}
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// 反序列化类型数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="array"></param>
/// <returns></returns>
public static T DeSerialize<T>(byte[] array) where T : new()
{
try
{
using (MemoryStream ms = new MemoryStream())
{
ms.Write(array, 0, array.Length);
ms.Position = 0;
return Serializer.Deserialize<T>(ms);
}
}
catch (Exception)
{
throw;
}
}
}
- 2.4 创建WCF服务需要的接口 IUserManagement
using FG_Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace FG_WCFServer
{
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IUserManagement”。
[ServiceContract]
public interface IUserManagement
{
[OperationContract]
string DoWork();
[OperationContract]
List<byte[]> GetUserInfoALL();
}
}
- 2.5创建实现接口的类 UserManagement
using FG_DAL;
using FG_Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace FG_WCFServer
{
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的类名“UserManagement”。
public class UserManagement : IUserManagement
{
public string DoWork()
{
return "WCF Server OK";
}
/// <summary>
/// 获取所有用户信息数据
/// </summary>
/// <returns></returns>
public List<byte[]> GetUserInfoALL()
{
UserManagementDal dal = new UserManagementDal();//数据解析层
List<UserInfo> list = dal.GetAllUserInfo();//获取MySql数据
List<byte[]> bytelist = new List<byte[]>();
foreach (var item in list)
{
//集合每一项序列化为ProtoBuf二级制数据
bytelist.Add(item.SerializeModel());
}
return bytelist;
}
}
}
- 2.6 WCF配置
<system.serviceModel>
<services>
<!--用户服务-->
<service name="FG_WCFServer.UserManagement">
<endpoint address="" binding="basicHttpBinding" contract="FG_WCFServer.IUserManagement" bindingConfiguration="BigBufferSendBinding">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/Design_Time_Addresses/FG_WCFServer/UserManagement/" />
</baseAddresses>
</host>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="BigBufferSendBinding" maxReceivedMessageSize="2147483647" messageEncoding="Text" transferMode="Streamed" sendTimeout="00:00:20">
<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- 为避免泄漏元数据信息,
请在部署前将以下值设置为 false -->
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="false" />
<!-- 要接收故障异常详细信息以进行调试,
请将以下值设置为 true。在部署前设置为 false
以避免泄漏异常信息 -->
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
- 2.7
WCF服务
初始化:
static void Main(string[] args)
{
ServiceHost wcfhost = new ServiceHost(typeof(FG_WCFServer.UserManagement));
wcfhost.Open();
Console.WriteLine("服务已启动");
Console.ReadKey();
}
3 客户端:
- 3.1 创建控制台项目, 引入
wcf
服务 - 3.2 同服务端需要引入
protobuf-net
,创建UserInfo
类及数据解析ProtoBuf
序列化方法(同服务端) - 3.3 修改控制台Main方法
static void Main(string[] args)
{
ServiceReference1.UserManagementClient client = new ServiceReference1.UserManagementClient();
var arraylist = client.GetUserInfoALL().ToList();
List<UserInfo> list = new List<UserInfo>();
foreach (var item in arraylist)
{
list.Add(SerializBaseModel.DeSerialize<UserInfo>(item));
}
foreach (var item in list)
{
Console.WriteLine($"账号:{item.UserAccount} 姓名:{item.UserName}");
}
Console.ReadKey();
}
4 结果:

网友评论