刚开始接触CS架构,没用过socket,大神能否快速科普一下。

失落的code 2012-07-05 01:01:35
百度过,不过感觉不能快速上手,需求:移动平台请求数据(crud都有),求一个DEMO,当然描述一下也行,用socket实现,不用webservice,我也说一下我的疑点吧,其实我也就看了一晚上,server端和client端直接和socket交互的是那一层?他们具体的职能是什么。。。大神们最好能给我个代码的框架,只有接口即可,实现可以不要,例如client实现一个最简单的crud。
好吧,我说一下我认为的逻辑(一直做bs开发,理解的不对请无视):UI→Controller(client端)→socket共通类(arg1:指令类型,arg2[]:参数列表)→Socket通信→Controller?(server端)[→BLL(Action,不知道有没有这一层)]→DAL(service)→DB Server
BLL(Action)这一层是不是 应该放在client对请求的数据进行编辑用的?我想知道socket通信实现方法应该在client和server的哪一层来调用?
...全文
712 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
失落的code 2012-07-08
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 的回复:]

以下或许是相当重要的入门知识,以免你以后对于通讯程序设计望洋兴叹。



知识层之一:
首先先要理解最基本的命令模式:C# code
public interface ICommand
{
object parameter { get; set; }
object Execute();
}

public abstrac……
[/Quote]
首先非常感谢大神的回复,顺便也让我学会了如何使用命令模式,我还有一点疑问,命令模式是把一个请求封装为一个对象,也就是说这个BLL服务不同于以往的三层,是不是只要是不同的请求就要定义一个类,因为只能有一个execute方法?以往的三层中,基本上是一个DAL对应一个BLL(是以模块划分的),而命令模式中的BLL是以动作(请求)划分的?
  • 打赏
  • 举报
回复
实际上这里的parameter的类型,你可以看作是常说的所谓“model”。而ICommand(的实际的子类)本身,你可以看作常说的所谓“BLL”。客户端只需要有最简单最低级的、关于model和BLL类型的代理类型,例如这里的Hello就是一个BLL服务。

通讯的目的如是为了实现什么crud,那么层次也太低了。谁也不敢真正把crud随便暴露在网络上让客户端随便修改删除你的数据吧!通讯的目的,就好象比如说我们通过网络下订单,通过它给火星上的异性发个情书,总之真正的信令内容越是贴近业务才越真正能够体现强大的服务端实用性、体现出可以将少数api激发出千变万化的前端交互界面程序。而不是什么数据库“增删改查”那种东西。

因此才有了BLL设计。去分析和设计BLL,要深入业务,而不是什么数据库增删改查。
  • 打赏
  • 举报
回复
使用socket,特别是使用长连接异步处理,你会发现要比http通讯快许多倍,特别是输入参数和返回对象是比较复杂的自定义类型时。比WCF快多少倍我都懒的去比较了。

当然长连接异步异步处理在最基本的信令设计上要稍微复杂一点。简单说一下长连接:


例如这样的格式(序列号为ulong类型):

命令类型|发送端会话id|接收端会话id|序列号|json

这样当服务器端刚刚解析到“接收端会话id”不是自己时,就简单地发消息发送给对应的客户端就行了。而当消息确实是发送给自己的,它异步地执行json,然后将返回结果以格式
返回数据类型|服务器端id|客户端id|-序列号|json的格式返回。

比如说客户端与服务器端建立了连接之后,它可能按照次序1、2、3、4、5的次序发送了5命令,然后异步地以3、5、2、1、4的次序收到了返回结果(因为服务器端是异步执行这些命令的,这些命令所用时间长短不同,所以返回的次序不定),那么客户端需要一个异步机制,在收到命令返回时才去回调相应的命令的下一步处理程序。
YapingXin 2012-07-06
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 的回复:]
这可是相当于一本入门书啊。
[/Quote]

很好的分享。

Thanks.
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 的回复:]
sp1234老大不是拷贝的吧
没见你写过这么长的代码啊
[/Quote]

这可是相当于一本入门书啊。
YapingXin 2012-07-06
  • 打赏
  • 举报
回复
我喜欢直接用ASP.Net HTTP Handler,轻量,我往.ashx这样的一个地址POST一个request class的json字符串,再接收一个response class的json序列化后的字符串,再反序列化得到response的内容。其实这就是个轻量级的service。
  • 打赏
  • 举报
回复
上面

ConsoleApplication1.Hello|{\"parameter\":\"baby\"}

应该写为

ConsoleApplication1.Hello|{"parameter":"baby"}

这是socket消息传送内容,因此没有反斜杠。



并且我会默认地在客户端和服务器端使用UTF8编码方式。
SocketUpEx 2012-07-06
  • 打赏
  • 举报
回复
sp1234老大不是拷贝的吧
没见你写过这么长的代码啊
YapingXin 2012-07-06
  • 打赏
  • 举报
回复
P哥威武。。。总结了这么多。
  • 打赏
  • 举报
回复
以下或许是相当重要的入门知识,以免你以后对于通讯程序设计望洋兴叹。



知识层之一:
首先先要理解最基本的命令模式:
    public interface ICommand
{
object parameter { get; set; }
object Execute();
}

public abstract class Command<T, S> : ICommand
{
public abstract S Execute(T parameter);

public object Execute()
{
return Execute((T)parameter);
}

public object parameter{get;set;}
}

这就是服务器端处理命令网关的基础。假设我们写个简单的BLL服务
    public class Hello : Command<string, string>
{
public override string Execute(string parameter)
{
return "hello, " + parameter + "!";
}
}

然后写个简单的本地测试:
            var cmd = new Hello();
cmd.parameter="baby";
var result = cmd.Execute();
你可以看到,这个封装为独立对象的BLL命令被执行了,并且返回了期望的值。


知识层之二:
实际上你的服务器端可能有多达十几个工程,每一个都实现了数量不等的ICommand。而你的服务器架构当然是预先开发的,它不知道将来会有哪些BLL需要经过它来进行解析。也就是说服务器都能够提接口一致的BLL服务给客户端,而你可能需要首先使用MEF技术或者就是原始的反射技术来将所有的ICommand收集起来备用。例如这里我随便写一个demo,它反射当前应用程序启动域中的所有程序
    private static Dictionary<string, Type> _commands = null;

public static Dictionary<string, Type> Commands
{
get
{
if (_commands == null)
{
_commands = AppDomain.CurrentDomain
.GetAssemblies()
.SelectMany(asm => asm.GetTypes())
.Where(type => typeof(ICommand).IsAssignableFrom(type))
.Where(type => type.IsClass && !type.IsAbstract)
.ToDictionary(x => x.FullName, x => x);
}
return Program._commands;
}
}
测试一下你能得到什么结果?你会看到你的程序可以将以 ConsoleApplication1.Hello 为键,在词典中收集了它所对应的ICommand实际实现类型Hello类型。这就是BLL扩展的基础。


知识层之三:
我们可以使用间接反射的方法从一个json字符串中得到一个Hello测试实例,然后计算结果,并且也输出为一个json字符串。例如(这里需要引用json.net类库)
var commandType = "ConsoleApplication1.Hello";
var input="{\"parameter\":\"baby\"}";
var cmd = JsonConvert.DeserializeObject(input, Commands[commandType]) as ICommand ;
var result = cmd.Execute();
var output = JsonConvert.SerializeObject(result);
执行它,你可以看到output里边已经准备好了返回给客户端的json字符串了。

知识层之四:
客户端可以随便定义一个class以便轻松地使用json.net产生这个json字符串。例如
namespace ConsoleApplication1
{
public class Hello
{
public string parameter;
}

.....
你可以看到,我这里使用了field而不是property。这完全没有关系!客户端对Hello命令的定义完全不必跟服务器端完全一致,甚至客户端多一些属性、少一些属性也无所谓,因为json都可以将其反序列化为服务器端的Hello命令。

知识层之五:
要有一个基本的信令设计。例如我们用 类型|json 这样的简单格式表达客户端的消息内容,那么就是客户端要通过socket发送给服务器这样的字符串:

ConsoleApplication1.Hello|{\"parameter\":\"baby\"}

而服务器在将竖线“|”之前的内容解析为commandType ,再将竖线之后的内容(直到换行或者回车符号之前的内容)解析为input,于是它就能计算出output,返回给客户端了!此时客户端自然知道用什么类型将返回的json字符串反序列出来。




以上是最基本的一种通讯机制demo。只有第一个命令模式有点技术含量,剩下的都是知识经验问题,而没有多么的技术。如果你深入理解和熟练使用这个简单的demo,就不会对设计复杂的命令通讯程序有什么疑惑,不至于只会拖拉鼠标来使用wcf而不敢自己来设计更加专业(以及比WCF要高效和方便很多)的通讯程序了!!
SocketUpEx 2012-07-06
  • 打赏
  • 举报
回复
序列化不就一个函数就行了吗?
  • 打赏
  • 举报
回复
sp老大,顺便问一下,凭你之前做过的socket项目,如果用socket来通信的话,各种指令,传递的业务数据是不是都需要按照自己的需求去序列化?
这个序列化是自己去制定规约还是有现成的框架呀?
gengchenhui 2012-07-06
  • 打赏
  • 举报
回复
难得sp这样有代码,有解释地回复,多学习学习吧。
zhangxuyu1118 2012-07-06
  • 打赏
  • 举报
回复
"server端和client端直接和socket交互的是那一层?他们具体的职能是什么。。。大神们最好能给我个代码的框架,只有接口即可,实现可以不要,例如client实现一个最简单的crud。"

1,server端和client端直接和socket交互的是那一层:通信层,一般有流和文本两种通信函数接口。2,代码:http://download.csdn.net/detail/zhangxuyu1118/260015
3、client实现crud,你要根据需要自己设计协议,比如:收到 "ADD 1 ZXYU " 你就做新增 1 ZXYU的 操作。
zhangxuyu1118 2012-07-06
  • 打赏
  • 举报
回复
"...(一直做bs开发,理解的不对请无视):..."有很好的基础耶,我们就拿browser和webserver来讨论。

browser和webserver之间的通讯也是SOCKET通讯,应用层使用HTTP协议(HTTP协议是基于TCP的,文本的),简单点你可以这样理解:browser向webserver发送字符串,一般80端口,TCP/IP通讯,webserver收到消息后给browser应答,然后挂机不里你了。深入点你研究下HTTP协议,用FIREFOX浏览器安装HTTP插件观察下GET、POST、RESPONSE时的内容。

OK,然后我们来说你的“CS架构”。其实,前面那段 browser和webserver之间的通讯 就是“CS架构”。他和你这里要求的“CS架构”差别在于BS传输时使用了HTTP协议,而你的DEMO想用你自创的武功。
说句废话,绝顶的高手们(注意们字)创建功夫流派,真正高手喜欢使用某流派,一般人喜欢使用自创的流派。

怎么个自创法呢,TCP通讯,服务器在某个端口侦听外面的电话(把客户端比喻成电话),你拨通了服务热线,服务器就建立了一条通信的管道(SOCKET)为您服务,他自己则继续侦听。。。你在热线中的通话,可以自由地和接线员打情骂俏,发送图片、病毒、EXE等都可以(一切数据皆文件或者01010101,这个不用我再说了吧),只要这些内容遵循你自创的协议。TCP保证你们的通信是传输内容正确、顺序正确的。当前通话怎样挂机呢,3种情况:1、我拍拍屁股挂了;2、受不了你的骚扰对方把你挂了;3、电话线被人断了。BS是接了电话,根据你的请求,发个回应就马上把你挂了。你认为这样比BS爽多了吗?其实不然,维护这么条通信管道太昂贵了,这个话费我吃不消。另外,分机号如果不是80端口也很难拨通(路由器、防火墙。。。),所以在大规模的系统中我不喜欢这样的模式(个人喜好)。
另外,
UI→Controller(client端)→socket共通类(arg1:指令类型,arg2[]:参数列表))→(遵循HTTP协议的字符串)→Socket通信→Controller?(server端))→(遵循HTTP协议的字符串)→[→BLL(Action,不知道有没有这一层)]→DAL(service)→DB Server

每个层,其实都是一门武林门派,有没有这层不要紧。郭靖可能先用HTTP报文进行收发,自己解析报文,分析出报文数据,然后他发现,哦报文接收有专门的流派、报文内容的解析有流派。。。根据所需学习流派吧,博采众长,祝您事业有成!
失落的code 2012-07-05
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

不过如果要这样做,还不如用http协议做,用http传输xml文件更为简单,如果用http协议,就和用webservice没多少差别,呵呵,

不管用什么方式,socket也好,http也好,只要你用xml文件做请求和应答,那么你可以决定在任何一个层次上做网络通讯,你可以把业务逻辑层放在服务器,然后client用xml调用服务器上的业务逻辑层,client只做界面,也可以把业务逻辑层放在cl……
[/Quote]
用socket不用webservice主要是考虑到性能的问题,client肯定是不会直接访问服务器的,因为手机平台塞班、安卓、WP、IOS要公用这一个server。
失落的code 2012-07-05
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 的回复:]

引用 6 楼 的回复:

用socket不用webservice主要是考虑到性能的问题,client肯定是不会直接访问服务器的,因为手机平台塞班、安卓、WP、IOS要公用这一个server。




你需要传输大量数据吗?如果不需要用webservice性能不差,如果共用server,那么最好用http协议传输xml指令的方式实现,因为各种系统对http协议支持都比较好,

……
[/Quote]
数据量挺小的吧,类似手机人人网客户端,企业级开发也会用webservice么,那么你觉得手机人人网服务器是什么形式的。
stonespace 2012-07-05
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]

用socket不用webservice主要是考虑到性能的问题,client肯定是不会直接访问服务器的,因为手机平台塞班、安卓、WP、IOS要公用这一个server。


[/Quote]

你需要传输大量数据吗?如果不需要用webservice性能不差,如果共用server,那么最好用http协议传输xml指令的方式实现,因为各种系统对http协议支持都比较好,

不过这样做会很辛苦,

即使是用http协议,也会比直接用socket要容易得多,服务器你可以用java的servlet实现,或者用asp.net也可以,服务器要容易得多,客户端就麻烦,
stonespace 2012-07-05
  • 打赏
  • 举报
回复
不过如果要这样做,还不如用http协议做,用http传输xml文件更为简单,如果用http协议,就和用webservice没多少差别,呵呵,

不管用什么方式,socket也好,http也好,只要你用xml文件做请求和应答,那么你可以决定在任何一个层次上做网络通讯,你可以把业务逻辑层放在服务器,然后client用xml调用服务器上的业务逻辑层,client只做界面,也可以把业务逻辑层放在client,用xml去调用服务器上的数据库,

但如果你用client直接访问数据层,那还不如就直接用ado.net直接从客户端访问数据库服务器,这也是最普通的cs结构程序的做法,也是最容易实现的做法,

devmiao 2012-07-05
  • 打赏
  • 举报
回复
所谓套接字,很多人说的只是指Windows Socket API以及在此之上封装的库函数(比如.net TCPClient UDPClient,mfc的CSocket,Delphi的Indy).
加载更多回复(3)

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧