2013年12月6日星期五

C# socket编程实践——支持广播的简单socket服务器 - dolphinX

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
C# socket编程实践――支持广播的简单socket服务器 - dolphinX  阅读原文»

在上篇博客简单理解socket写完之后我就希望写出一个websocket的服务器了,但是一路困难重重,还是从基础开始吧,先搞定C# socket编程基本知识,写一个支持广播的简单server/client交互demo,然后再拓展为websocket服务器。想要搞定这个需要一些基本知识

线程与进程

进程与线程对CS的同学来说肯定耳闻能像了,再�嗦两句我个人的理解,每个运行在系统上的程序都是一个进程,进程就是正在执行的程序,把编译好的指令放入特定一块内存,顺序执行,这就是一个进程,我们平时写的if-else,for循环都按照我们预期,一步步顺序执行,这是因为我们写的是单线程的程序,所谓线程是一个进程的执行片段,我们写的单线程程序,整个进程就一个主线程,所有代码在这个线程内顺序执行,但一个进程可以有多个线程同时执行,这就是多线程程序,利用多线程支持我们可以让程序一边监听客户端请求,一边广播消息。

同步与异步

熟悉web开发的同学肯定了解这个概念,在使用ajax中我们就会用到异步的请求,同步与异步正好和我们生活中的理解相反(我尝试问过学管理的女朋友)

同步:下一个调用在上一个调用返回结果后执行,也可以理解为事情必须一件做完再去做另一件,我们经常编写的语句都是同步调用

int a=dosomething();
a
+=1;

a+=1; 这条指令必须在dosomething()方法执行完毕返回结果后才可以执行,否则就乱了套

异步:异步概念和同步相对,当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者(百度上抄的)。理解了同步概念后异步也就不难理解了,以javascript的ajax为例

ajax(arg1,arg2,function(){
//回调函数
  a=3;

});
a=4;

这个代码段执行完成后一般情况会把a赋值为3而不是4,因为在ajax方法调用后,a=4;这条语句并没有等待ajax()返回结果就执行了,也就是在ajax()执行完成调用回调函数之前,a=4;已经执行了,回调函数再把a赋值为3使之成为最后结果,为此在ajax调用中我们经常会使用回调函数,其实在很多异步处理中我们都会使用到回调函数。

阻塞

阻塞操作是指,在执行设备操作时,若不能获得资源,则进程挂起直到满足可操作的条件再进行操作。

步骤

了解了上面知识我们就可以按照下图来写我们的服务器了

整体结构

关于怎么具体一步步使用socket我就不说了,有兴趣同学可以看看你得学会并且学得会的Socket编程基础知识,看看我们服务器的结构,我写了一个TcpHelper类来处理服务器操作

首先定义 一个ClientInfo类存放Client信息

public class ClientInfo
{
public byte[] buffer;
public string NickName { get; set; }
public EndPoint Id { get; set; }
public IntPtr handle { get; set; }
public string Name
{
get
{
if (!string.IsNullOrEmpty(NickName))
{
return NickName;
}
else
{
return string.Format("{0}#{1}", Id, handle);
}
}
}
}

然后是一个SocketMessage类,记录客户端发来的消息

public class SocketMessage
{
public bool isLogin { get; set; }
public ClientInfo Client { get; set; }
public string Message { get; set; }
public DateTime Time { get; set; }
}

然后定义两个全局变量记录所有客户端及所有客户端发来的消息

private Dictionary<Socket, ClientInfo> clientPool = new Dictionary<Socket, ClientInfo>();
private List<SocketMessage> msgPool = new List<SocketMessage>();

然后就是几个主要方法的定义

/// <summary>
/// 启动服务器,监听客户端请求
/// </summary>
/// <param name="port">服务器端进程口号</param>
public void Run(int port);

/// <summary>
/// 在独立线程中不停地向所有客户端广播消息
/// </summary>
private void Broadcast();

/// <summary>
/// 把客户端消息打包处理(拼接上谁什么时候发的什么消息)
/// </summary>
/// <returns>The message.</returns>
/// <param name="sm">Sm.</param>
private byte[] PackageMessage(SocketMessage sm);

/// <summary>
/// 处理客户端连接请求,成功后把客户端加入到clientPool
/// </summary>
/// <param name="result">程序员之歌 - 杨传东  阅读原文»

诗人写的是诗、画家作的是画、而我们写的是代码。
农民耕作的是土地、工人操作的是机器、而我们编作的是代码。
将军指挥的是士兵、企业家指挥的是员工、而我们指挥的是代码。
别人称呼我们是程序员、开发者、程序猿/媛、软件攻城狮,码农
只因我们的工作是写代码。
世界越来越离不开代码、世界越来越需要代码。
有码走遍天下、无码寸步难行。
世界在被代码改变着、而我们在创造着代码。
让我们在代码世界中风雨同舟、让我们在代码世界中尽享码伦之乐。
让我们一起用代码改变世界!
祝大家程序员节快乐!

本文链接:http://www.cnblogs.com/yanghonker/p/3462565.html,转载请注明。

阅读更多内容

没有评论:

发表评论