对最近求学WCF的下结论——唔聊的劳务

http://blog.csdn.net/silenceburn/article/details/6083375

当二〇一九年初应届毕业生,找工作的下压力实在蛮死,貌似二〇一九年之就业形势不是特意的好,虽然博友们发出部手机客户端的地方,请帮忙自己推荐一下,津京地区windows
phone,ios,android皆可。

===========================================

好了,言归正传。前几天待总计的是最近套的WCF服务编程,这个是本身的毕业设计。因为刚学,如若和被起什么错误,还请求多指正。

*
*

率先介绍一下,整个应用之业务逻辑。我的毕业设计是一个大抵客户端平台的人身自由交友应用,起名叫做唔聊,有硌类似于omegle.com,就是随机匹配有陌生人举办拉,不过不像陌陌这样主动去采纳符合条件的用户,因为性与头像总会影响我们的采用,但在omegle的根底及出席了用户信息,仍然不带加好友效用。假诺起衍的时日,还汇合参与一个按照用户常聊关键词举行匹配的职能,这间便涉及到了自然语言处理的算法,一时半会儿搞不必然。

*
*

图片 1

比方有摩擦漏请不吝拍砖指正,转载请注明出处,万分感谢

同一据《WCF服务编程》就要700差不多页,当一随字典不错,不过其实看不下去了。后来拘留了CSDN上老周的WCF体系,感觉相比较吻合入门在此地推荐一下。http://blog.csdn.net/column/details/wcf-example-come.html

 

本人事先说说作为一个入门者,要先期由杀地点动手。我们得了然几样相比较基本的东西:终结点、契约、宿主、客户端调用,其他东西得以暂时先不随便,知道就三类,就足以先勾勒来单东西来了。


终结点(Endpoint):终结点需要精通三样东西:Address、Binding、Contract,简称ABC。

 

  1. Address是凭借服务之Uri地址,
  2. Binding是绑定情势,绑定模式基本为5栽,BasicHttpBinding、NetTcpBinding、NetNamePipeBinding、WSHttpBinding、NetMsmqBinding
  3. Contract为契约,指向也客户端提供劳务之接口

出一个题目,在网上给反复的问到,就是干吗从定义之Receiver总是力不从心吸纳至SD卡插拔的事件。

      老周的终结点基本依旧为此编程情势写的,所以一下所以config的办法来呈现一下:

假诺以此问题大部分景观下足经过扩充一句代码解决:
filter.addDataScheme(“file”);  // filter是IntentFilter对象

<endpoint address="http://169.254.80.80/WuChatServer/HostSvc.svc" binding="wsHttpBinding" bindingConfiguration="WcfMode.WSHttpBinding"
                  name="HostSvc" contract="WuChatServer.IHost"/>

 

 

那么为什么多这词代码就可以化解了吧?这一个问题即便有人提问到,可是却从未太好之作答。

契约(Contract):WCF定义了季种植契约:服务契约、数据契约、错误契约、音信契约。契约说白了,就是供客户端调用的劳动,比如客户端需要调用服务端的加法方法,就定义一个接口,标为服务契约,在接口中的加法方法齐标上操作契约。假设需要采用一个数据结构去通信,就由此数据契约定义一个结构体,或者一个近乎。

也许是为对会IntentFilter策略的能人们来说,这从算不齐问题,是一个还显明不过的真情而已。

如下:

假定对此未极端掌握IntentFilter策略的我们新家的话,那些题材而少有点太为难了解吧。

    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        int AddMethod(int a,int b);
    }
    public class MyService : IService 
  { 
    public int AddMethod(int a, int b) 
    { 
      return a + b; 
    }
  }

 

自家呢唔聊定义的IHost暂时为这样的:

故而,本文试着通过对android的波过滤策略举办介绍与剖析,结合示例程序举办验证,

    [ServiceContract(SessionMode = SessionMode.NotAllowed)]
    interface IHost
    {
        [OperationContract]
        bool ConnectCumm(string commId);//连接服务,加入在线列表
        [OperationContract]
        bool DisConnectCumm(string commId);//断开服务
        [OperationContract]
        bool ClientSend(string commId, List<byte[]> msg);//客户端发送消息
        [OperationContract]
        List<List<byte[]>> GetHostMessage(string id);//获取服务端消息
        [OperationContract]
        string GetStrangerId(string commId);//获取聊天对象的id
        [OperationContract]
        bool CheckConnect(string id);//检查是否在线
        [OperationContract]
        string GetChattingNum();//获取在线人数
        [OperationContract]
        bool GetIsChatting(string commId);//获取是否为聊天状态,或者等待状态
    }

来解答之题材,并起首的牵线android事件过滤策略。

 

 

宿主(Host):以WCF服务不克凭空存在,每个WCF服务要托管在Windows进程中,所以我们须为WCF服务提供一个宿主。这个宿主可以是asp.net、Winform、WPF、Silverlight等。我在唔聊中少用了一个WPF的窗体程序来开为宿主,你得一直引用WCF的动态库来实现。


客户端调用(Client):客户端怎样调用WCF服务是我们相比关心的,作为可过平台的劳务框架,WCF可使用Restful来提供客户端调用的方法,通过HTTP的GET、PUT、POST

DELETE等办法举办操作。目前唔聊仅实现而每当.net客户端(WPF、windows phone)的一致局部功效,所以仍旧言语一下.net之调用形式。

1. 编示例程序,创立一个自定义的布罗德(Broad)castReceiver

第一我们创制一个android工程自名叫也SdCardTester,作为示范程序。

为便于于继承手续中拟SD卡插拔,提议以对象平台设定为2.3本子,使用2.3本子的模拟器。

其它要注意,运行此示例程序的AVD模拟器需要扩大SD卡效率支撑。

 

接下来为SdCardTester类扩展一个布罗德(Broad)castReceiver类型的积极分子变量 mReceiver。

在onCreate中,使用匿名类的技术,为 mReceiver
赋值一个布罗德(Broad)castReceiver子类实例。

[java] view
plain
copy

  1.      mReceiver = new BroadcastReceiver() {  
  2. @Override  
  3. public void onReceive(Context context, Intent intent) {  
  4.         Log.i(“myLoger”,” Receive SDCard Mount/UnMount!”);  
  5. }  
  6. ;  

顾代码中重复写的onRecevie函数里只有发平等句代码,用于记录日志。以证实我们真收到了轩然大波。

 

接下来创造一个IntentFilter,用于过滤SD卡插拔事件。

终极将咱由定义的Receiver和编好之IntentFilter注册到网遭到

[java] view
plain
copy

  1. IntentFilter filter = new IntentFilter();  
  2. filter.addAction(Intent.ACTION_MEDIA_MOUNTED);  
  3. filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);  
  4. registerReceiver(mReceiver, filter);  

 

最后之末梢不要遗忘了当onDestory中裁撤我们的自定义Receiver,

时至前几天完成了示范程序的代码编写,SdCardTester的圆代码如下:

[java] view
plain
copy

  1. package com.silenceburn;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.BroadcastReceiver;  
  5. import android.content.Context;  
  6. import android.content.Intent;  
  7. import android.content.IntentFilter;  
  8. import android.os.Bundle;  
  9. import android.util.Log;  
  10.   
  11. public class SdCardTester extends Activity {  
  12.       
  13.     BroadcastReceiver mReceiver;  
  14.       
  15.     /** Called when the activity is first created. */  
  16.     @Override  
  17.     public void onCreate(Bundle savedInstanceState) {  
  18.         super.onCreate(savedInstanceState);  
  19.         setContentView(R.layout.main);  
  20.           
  21.         mReceiver = new BroadcastReceiver() {  
  22.             @Override  
  23.             public void onReceive(Context context, Intent intent) {  
  24.                     Log.i(“myLoger”,” Receive SDCard Mount/UnMount!”);  
  25.             }  
  26.         };  
  27.           
  28.         IntentFilter filter = new IntentFilter();  
  29.         filter.addAction(Intent.ACTION_MEDIA_MOUNTED);  
  30.         filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);  
  31.         registerReceiver(mReceiver, filter);  
  32.          
  33.     }  
  34.       
  35.     @Override  
  36.     protected void onDestroy() {  
  37.         // TODO Auto-generated method stub  
  38.         super.onDestroy();  
  39.         unregisterReceiver(mReceiver);  
  40.     }  
  41. }  

 


于客户端的工达标右键引用服务

2. 测试示例程序

运作SdCardTester,等相hello World
字样,表达onCreate完成,也就表示我们从定义之Receiver也已启动了。

 

日后,不要由此BACK退出,按HOME按钮重临主屏幕,(也不怕是只要包大家的自定义Receiver仍旧在运转)

跻身手机设定,接纳Storage (如若系统语言采纳为粤语了凡“存储”),

慎选 Unmount SD card / mount SD card
选项,就可学SD卡插拔的动作了。如下图所示:

图片 2

 

就算我们的自定义Receiver收到了有关事件,遵照代码实现,就会师用 TAG
“myLoger” 输出日志到logCat。

所以我们通过观看logCat输出确定是不是出连锁事件时有暴发,在cmd窗口被运行 ” adb
logcat -s myLoger:i ” ,即可持续监控日志输出。

依旧选取Eclipse ADT插件扩大的DDMS视图,在logCat
的View中加进一个filter,如下图所示:

图片 3

 

只顾,依照我们当下底代码实现,无论我们哪插拔SD卡,都无晤面见到日志窗口监控到事件时有暴发。

 

OK,大家本长这行神奇之代码:“   filter.addDataScheme(“file”);   ”,

连在onCreate中益一个日记输出监控程序上。修改未来的代码如下:

[java] view
plain
copy

  1. package com.silenceburn;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.BroadcastReceiver;  
  5. import android.content.Context;  
  6. import android.content.Intent;  
  7. import android.content.IntentFilter;  
  8. import android.os.Bundle;  
  9. import android.util.Log;  
  10.   
  11. public class SdCardTester extends Activity {  
  12.       
  13.     BroadcastReceiver mReceiver;  
  14.       
  15.     /** Called when the activity is first created. */  
  16.     @Override  
  17.     public void onCreate(Bundle savedInstanceState) {  
  18.         super.onCreate(savedInstanceState);  
  19.         setContentView(R.layout.main);  
  20.         Log.i(“myLoger”,” onCreate ……”);  
  21.           
  22.         mReceiver = new BroadcastReceiver() {  
  23.             @Override  
  24.             public void onReceive(Context context, Intent intent) {  
  25.                     Log.i(“myLoger”,” Receive SDCard Mount/UnMount!”);  
  26.             }  
  27.         };  
  28.           
  29.         IntentFilter filter = new IntentFilter();  
  30.         filter.addAction(Intent.ACTION_MEDIA_MOUNTED);  
  31.         filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);  
  32.           
  33.         filter.addDataScheme(“file”);  
  34.           
  35.         registerReceiver(mReceiver, filter);  
  36.          
  37.     }  
  38.       
  39.     @Override  
  40.     protected void onDestroy() {  
  41.         // TODO Auto-generated method stub  
  42.         super.onDestroy();  
  43.         unregisterReceiver(mReceiver);  
  44.     }  
  45. }  

 

改完还运行程序,不要为此BACK退出,按HOME按钮重临主屏幕,进入Setting模拟SD卡插拔,

然后观看logCat日志监控窗口,神奇之作业发了,我们可收到及事件了!如下图所示:

图片 4

 


图片 5

3.事件(Intent)的分类:显式 和 隐式

这,为啥加上 filter.addDataScheme(“file”); 就足以了吧?

为化解之问题,大家只要先行学Intent的分类。Intent分为两百般接近,显式和隐式。

 

显式事件,就是靠经 component Name 属性,明确指定了靶组件的轩然大波。

比如我们新建一个Intent,指名道姓的说,此事件用于启动名也”com.silenceburn.XXXX”的Activity,那么就就是是一个显式事件。

 

隐式事件,就是依没有 component Name 属性,没有领会指定目标组件的风波。

依系统于有监控通话状态的次序发送的“来电话了!”的波,由于系统非确定什么人会处理这波,

为此系统未会面肯定指定目的组件,也就是说没有目的组件,那么这便是单隐式的事件。

 

那里只是简介显式和隐式事件,更确切详细的叙述请查阅SDK文档,

大家一味需要牢记一点,两栽事件之极致充足区别是 component Name
属性是否为空。

 


然后点击发现,能够寻找到与解决方案下之WCF服务,也得以一直输入WCF服务的位置举行引用。在高级页面中我们好选是否提供异步的调用形式,WPF客户端默认为唯有同调用格局,而WP8客户端为免程序假死就提供异步调用情势。

4.波过滤策略 和 IntentFilter

网以传递显式事件频仍大有益,因为倘若管Intent比作同样封闭信,那么component
Name就是一个详实的收件人地址,

系统可以确切的管显式事件送达目标组件。

 

使传送隐式事件时,就相比较累了。因为即刻封信的封皮上,没有写收信地址!

那么怎么惩罚为?系统做了一个费力的决定,就是把信拆开看看。通过信件内容里的头脑,去找寻适合的收件人。

论信中之端倪描述到:“收信人是阳,快30年份了,未婚,喜欢嬉水游戏”,那么网就是在小区内去找寻这么的人头。

 

这多少个值得庆幸的事务是,这么些小区的丁素质非凡强,每户人家还写了点自我介绍在门口,

仍张三写道:“我是阳,90晚,未婚,喜欢嬉水游戏”,李四写道:“我是女性,快30春了,未婚,喜欢逛街”等等等等。

起矣户人家的自我介绍,系统就是可以怪快之定点真正的收件人了!

 

点是一个类比的事例,但是android系统处理隐式事件之策略,基本上就是是上述这种模式了。

 

率先系统会因此观测Intent的情节(打开信件看内容),取得异常线索,系统所要的端倪是之类三栽

 action

 data (both URI and data type)

 category

 

从,系统面临每个组件,要是想吸收隐式事件,则必须表明自己的IntentFilter(自我介绍,我本着安的信件感兴趣)。

有关怎么写IntentFilter,已经分外清楚了了,这固然是理所应当是如此写:

“我是组件XXXX,我牵挂要吸收这样的隐式事件:它的ACTION必须是 XXX,它的
category 必须是 YYYY ,它包含的data必须是ZZZZ “

假使组件不表明IntentFilter,那么富有的隐式事件还不会晤发送给该零件。(注意,这并无影响为该零件发送显式事件。)

 

于系面临出的每个隐式事件,系统都汇合尝试以 action, data , category
和系受逐一零部件讲明的 IntentFilter 去举办匹配,

以寻找到当的收信人。

 

上述是android系统的轩然大波过滤策略的大概原理,实际境况颇为较当下要复杂,考虑本文的目标,此处不再举办,SDK文档中都发出详细描述。

 


下一场在客户端的ViewModel中修代码:

5. 分析SD卡插拔事件

由上节亦可,对于显式事件,系统可以准确送达。对于隐式事件,系统分析事件的
action, data , category 内容,

并同顺序零部件声明的IntentFilter举行匹配,找来万分的零部件举办送达。

 

据此SD卡插拔事件是否给大家打定义的Recevier收到就取决于如下子问题了:

  1. SD卡插拔事件是显式事件,如故隐式事件

  2. SD卡插拔事件之action, data , category 的始末是啊

  3. 咱由定义之Receiver组件的IntentFilter是什么阐明的

 

为缓解上述3单问题,我们修改一下代码,将SD卡插拔事件的情打印至logcat中开展考察。

改后底代码如下:(注意这里我们要增补加好 filter.addDataScheme(“file”);
以保险事件可以让吸收至)

[java] view
plain
copy

  1. package com.silenceburn;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.BroadcastReceiver;  
  5. import android.content.Context;  
  6. import android.content.Intent;  
  7. import android.content.IntentFilter;  
  8. import android.os.Bundle;  
  9. import android.util.Log;  
  10.   
  11. public class SdCardTester extends Activity {  
  12.       
  13.     BroadcastReceiver mReceiver;  
  14.       
  15.     /** Called when the activity is first created. */  
  16.     @Override  
  17.     public void onCreate(Bundle savedInstanceState) {  
  18.         super.onCreate(savedInstanceState);  
  19.         setContentView(R.layout.main);  
  20.         Log.i(“myLoger”,” onCreate ……”);  
  21.           
  22.         mReceiver = new BroadcastReceiver() {  
  23.             @Override  
  24.             public void onReceive(Context context, Intent intent) {  
  25.                   
  26.                 Log.i(“myLoger”, “Component: ” + intent.getComponent());  
  27.                   
  28.                 Log.i(“myLoger”, “Aciton: ” +  intent.getAction());  
  29.                 Log.i(“myLoger”, “Categories: ” +  intent.getCategories());  
  30.   
  31.                 Log.i(“myLoger”, “Data: ” + intent.getData());  
  32.                 Log.i(“myLoger”, “DataType: ” + intent.getType());  
  33.                 Log.i(“myLoger”, “DataSchema: ” + intent.getScheme());  
  34.                   
  35.                 Log.i(“myLoger”,” Receive SDCard Mount/UnMount!”);  
  36.             }  
  37.         };  
  38.           
  39.         IntentFilter filter = new IntentFilter();  
  40.         filter.addAction(Intent.ACTION_MEDIA_MOUNTED);  
  41.         filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);  
  42.           
  43.         filter.addDataScheme(“file”);  
  44.           
  45.         registerReceiver(mReceiver, filter);  
  46.          
  47.     }  
  48.       
  49.     @Override  
  50.     protected void onDestroy() {  
  51.         // TODO Auto-generated method stub  
  52.         super.onDestroy();  
  53.         unregisterReceiver(mReceiver);  
  54.     }  
  55. }  

 

OK,让咱重新运行程序,通过Setting模拟插拔SD卡,寓目logCat的出口意况。

生图是挂载SD卡时底日记输出情形:

图片 6

 

经过日记输出我们得识破挂载SD卡事件的 Componet
是null ,因而它们是一个隐式事件。

因此能否送达,需要看事件的 action, data , category 和
IntentFilter是否配合。

 

它的ACTION是 android.intent.action.MEDIA_MOUNTED,

暨我们定义之IntentFilter的
filter.addAction(Intent.ACTION_MEDIA_MOUNTED); 语词相兼容。

据此action部分是匹配的。

 

其的Categories是null,而我辈定义之 IntentFilter
也没采纳addCategory方法增添category定义,

null ==  null,由此 categories也是配合的。

 

action, data , category 中之片独要素就万分,那么是否配合成功之重点,就是看data是否匹配了。

 


new HostSvc.HostClient().ConnectCumm(id);//同步
var hostclient = new HostClient.HostClient();//异步
                            hostclient.ConnectCummCompleted += new EventHandler<HostClient.ConnectCummCompletedEventArgs>(ConnectResult);
                            hostclient.ConnectCummAsync(id);

void ConnectResult(object sender, HostClient.ConnectCummCompletedEventArgs e)
        {

        }

6. data匹配规则

首先必须认识及,data是一个针锋相对复杂的要素。
data由URI来叙述和一定,URI由三有组成,

 

scheme://host:port/path      模式://主机:端口/路径

 

像大家收获的挂载SD卡事件,它的data的URI是 file:///mnt/sdcard

里格局有是 file , 主机:端口部分凡拖欠的, path部分是 mnt/sdcard

另外在事变受到,还是可以设置data的MIME类型,作为事件之datatype属性。

 

综上所述,data是一个比复杂的因素,由此该匹配规则吧坏复杂,

 

先是肯定一个匹原则,就是对于URI的配合,只相比filter中阐明的局部。

局部匹配原则:只要filter中宣示的一部分匹配成功,就觉着满门URI匹配成功。

举例来说来说,           content://com.silenceburn.SdCardTester:1000/mydata/private/

及filter定义为  content://com.silenceburn.SdCardTester:1000/     是可兼容的。

留神filter中并没有定义path部分,不过仍旧可兼容成功,因为filter不注解的片段未进行相比较。

转移句话讲,任何称content://com.silenceburn.SdCardTester:1000/的轩然大波,无论path是呀,都足以兼容成功。

 

连下去是真正的data部分的,也就是URI的匹配规则如下:

 

1. 倘使data的URI和datatype为空,则 filter
的URI和type也务必为空,才可以匹配成功

2. 万一data的URI不为空,不过datatype为空,则 filter
必须定义URI并配合成功,且type为空,才会配合成功

3. 设data的URI为空,可是datatype不呢空,则 filter
必须URI为空,定义type并配合成功,才会匹配成功

4. 假设data的URI和data都非也空,则 filter
的URI和type都必须定义并配合成功,才会配合成功。

   
对于URI部分,有一个独特处理,就是即使filter没有定义URI,content和file两栽URI也作为既存的URI存在。

   (举个例子,对于 content 和 file
二种植形式之data,只要filter定义的datatype可以和事件十分,就觉着分外成功,

     filter不待显式的增 content 和 file 两栽格局,这半种植格局内置帮助)

 

有矣平整,有了针对SD卡插拔事件的情节之辨析,大家固然可依照图索骥照章办事了。


WP8客户端倘若当调用服务中发出甚,请检查服务地点是否为localhost,倘诺是,按是方案解决:http://msdn.microsoft.com/zh-CN/library/windowsphone/develop/jj684580%28v=vs.105%29.aspx

7.SD卡插拔事件之匹配

先是使第6省所陈述,SD卡插拔是一个隐式事件,而且 action 和 category
部分和大家的 filter 均好配合成功。

 

其data部分的URI为 file:///mnt/sdcard ,datatype为 null
,由此采取第6节省于规则中的 2 号规则:

    2. 使data的URI不为空,然则datatype为空,则 filter
必须定义URI并配合成功,且type也空,才会配合成功

 

大家的filter中无下 addtype 方法 ,由此 filter 的type为空,
datatype部分匹配成功。

data的URI为file:///mnt/sdcard ,我们下 filter.addDataScheme(“file”);
语句定义 schema 为 file,

依据部分匹配规则,data匹配成功。

 

时至今天,整个事件很是成功,至此,我们就是知道了文初的问题,为啥必须补偿加  filter.addDataScheme(“file”);
语句子才能接收事件!

 

大家得尝尝把 filter.addDataScheme(“file”); 前边扩张语句

[c-sharp] view
plain
copy

  1. filter.addDataPath(“mnt/sdcard”, PatternMatcher.PATTERN_LITERAL);  

仍可以配合成功,收到SD卡插拔事件。因为这么尽管成了一个URI的了配合。

 

咱俩可尝尝将给 filter 扩展 datatype 属性,

[java] view
plain
copy

  1. try {  
  2.     filter.addDataType(“text/*”);  
  3. } catch (MalformedMimeTypeException e) {  
  4.     // TODO Auto-generated catch block  
  5.     e.printStackTrace();  
  6. }  

这般即使无法配合成功了。因为SD卡插拔事件之datatype是null,

假诺我辈定义之filter的datatype是MIME”text/*” 。

 


android调用WCF服务可参见:http://www.cnblogs.com/davidgu/archive/2012/05/16/2504182.html

总结

至今文初的题目分析了。老生常谈,事实上android平台的intentFilter处理机制远远复杂于本文所述范围。

专门是本文对action和category二种植因素的议论分外少几从未,实际上就有限栽素的处理为是比较复杂的。

 

本文只是冰山一角的叙说了了一部分基本原理和基本准则。

IntentFilter机制作为android平台的首要性基础知识之一,我们我们要同步连续努力学习,和我们一齐勉
🙂

差不多通过编制终结点、契约接口、服务宿主、客户端引用这么几步,一个WCF服务就搭建好了。

过简单龙我会具体介绍客户端着之有的故事,稍微讲述一下MVVM和android的编程。

图片 7

分享同摆放WP8客户端的规划图,P的生接触次,请见谅吧。

 

感阅读倾剑飞经的博客

正文地址:http://www.cnblogs.com/jacklandrin/archive/2013/04/20/3033248.html

联系我:jacklandrin@hotmail.com

正文版权归作者所有,欢迎转载,演绎或用于商业目标,然而要表明本文出处(包含链接)。

 

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图