C#网络编程-详细解读-实现简单的服务端和客户端,并在客户端调用服务端的中方法

571 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第17天,点击查看活动详情

服务器端

1. 创建 WCF 服务应用程序

1.1 WCF 应用程序的目录结构(以创建的时候,程序名为 默认的 WcfService1 为例)

  • IService1.cs : 服务的接口的定义

    • [ServiceContract] : 服务协定
    • [OperationContract] : 操作协定:接口中每定义一个方法之前,都要在这个定义的方法之前加上这个操作协定,否则该方法不能被调用
    // 案例: 定义一个 sayHello 的方法
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        string sayHello(string name);
    
        //...省略部分代码...
    
        // TODO: 在此添加您的服务操作
    }
    
  • Service1.svc : 服务

    • ​ Service1.svc.cs : 实现 服务中定义的接口 的类

      // 案例:实现上面定义的那个 sayHello 方法
      
          // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、svc 和配置文件中的类名“Service1”。
          // 注意: 为了启动 WCF 测试客户端以测试此服务,请在解决方案资源管理器中选择 Service1.svc 或 Service1.svc.cs,然后开始调试。
      public class Service1 : IService1
      {
          public string GetData(int value)
          {
              return string.Format("You entered: {0}", value);
          }
      
          public CompositeType GetDataUsingDataContract(CompositeType composite)
          {
              // ...省略部分代码....
          }
      
          public string sayHello(string name)
          {
              return "hello"+ name;
          }
      }
      
  • Web.config : 配置信息

    • : 协议绑定节点
    <!-- Web.config 的部分代码-->
    <system.serviceModel>
      <behaviors>
        <serviceBehaviors>
          <behavior>
            <!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false -->
            <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
            <!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息 -->
            <serviceDebug includeExceptionDetailInFaults="false"/>
          </behavior>
        </serviceBehaviors>
      </behaviors>
      <protocolMapping>
          <add binding="basicHttpsBinding" scheme="https" />
      </protocolMapping>    
      <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    </system.serviceModel>
    <system.webServer>
      <modules runAllManagedModulesForAllRequests="true"/>
      <!--
          若要在调试过程中浏览 Web 应用程序根目录,请将下面的值设置为 True。
          在部署之前将该值设置为 False 可避免泄露 Web 应用程序文件夹信息。
        -->
      <directoryBrowse enabled="true"/>
    </system.webServer>
    

客户端

创建一个 WPF 应用程序( 默认命名 WpfApp1 )

1. 添加服务的引用

  • 右键引用 ---> 选择 “添加服务引用” ---> 将服务程序运行之后生成的地址给复制到这里 ----> 对该引用进行命名(一般选择默认的名称 这里是 ServiceReference1 )---> 确定 ====> 即添加完成

  • 添加完成之后,右侧会多一部分内容:

    Connected Services (目录) ---> ServiceReference1 (前面目录下的文件)

  • 添加完成之后,在 App.config 配置文件里面会增加一部分内容

<!--添加服务引用时候自动添加的内容-->
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
              <!--单向绑定-->
                <binding name="BasicHttpBinding_IService1" />
            </basicHttpBinding>
        </bindings>
        <client>
          <!--终结点-->
          <!--下面的这个 bindingConfiguration 属性的值为 上面我们定义的 绑定的名字-->
          <!--binding 的属性值为 绑定的方式-->
          <endpoint address="http://localhost:50490/Service1.svc" binding="basicHttpBinding"
                bindingConfiguration="BasicHttpBinding_IService1" contract="ServiceReference1.IService1"
                name="BasicHttpBinding_IService1" />
        </client>
    </system.serviceModel>
  • 点击右侧新生成的 ServiceReference1 文件 会看到:服务端的方法都在 客户端代理类的下面:

    (这也是为什么 后文 我们要通过 客户端代理类来调用方法)

屏幕截图 2022-04-18 132947.png

2. 调用服务中的方法

  • 首先需要引入命名空间:

    using WpfApp1.ServiceReference1 ;

    注意:如果我们的服务端和客户端是在同一个解决方案下面的话,这个命名空间的引入,系统会在我们添加引用的时候自动帮我们引入的;但是在不同的解决方案下面的话,就需要我们进行手动引入了

  • 通过 客户端代理类 来调用服务中的方法

    • 客户端代理类是在 我们创建的 引用的命名空间下面的,所以如果我们没有在前面引入命名空间的话,是会报错的
    • 客户端代理类的类名 一般是 我们创建的服务程序的名字加上一个 Client ,就比如说我们这里的 Service1Client

    示例代码如下:


<!-- 图形界面的主要代码 -->

<Grid>
    <TextBox Name="TextBox1"  HorizontalAlignment="Left" Height="66" Margin="81,72,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="375"/>
    <Button Name="btn1" Content="Button" HorizontalAlignment="Left" Height="58" Margin="121,215,0,0" VerticalAlignment="Top" Width="169" Click="Btn1_Click"/>

</Grid>
// 定义 wpf 界面中的 按钮的单击事件
private void Btn1_Click(object sender, RoutedEventArgs e)
{
    //创建客户端代理类的对象
    Service1Client client = new Service1Client();
    // 调用 服务中的 sayHello 方法
    TextBox1.Text = client.sayHello( "aaa");
}

注意事项

  1. 一定要先打开服务程序,再运行 客户端程序(如果服务程序未运行,运行客户端程序,系统会在客户端程序中的调用服务程序的代码的地方报错的!!!)
  2. 我们调用服务中的方法,使用的是 客户端代理类 对象来调用的;在我们使用 代理类对象之前,一定要 添加服务应用和引入对应的命名空间