科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件Visual C#建立简单消息传递系统

Visual C#建立简单消息传递系统

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

本文讨论了基于套接字的体系结构以及怎样建立可同时在PC和Pocket PC上运行的消息传递系统

作者:陶刚编译 来源:yesky 2007年11月13日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
面向对象设计vs.实用主义

  这种方法的缺点之一是你必须使用一个大的switch语句结束,但是前辈一直教导我们大的switch语句是较差的设计的表现。通常的面向对象(Object Oriented,OO)的途径是使用多态性(polymorphism)的。为了达到这个目的,我们先建立一个抽象的基类(base class),接着从该类衍生出所有的消息对象。每个类需要执行串行化、并行化和处理消息等多个方法,主要的代码是:

  · 读取消息类型

  · 建立实例(使用反射)

  · 调用虚HandleMessage()函数

  这样做是可以实现的,但是效果很差,我并不喜欢。首先,编写建立实例的代码很难,并且由于它使用了反射,它的速度更慢。更重要的是,消息的处理过程并不在HandleMessage()函数之内,这意味着它必须是共享库的一部分。这是不宜使用的,因为消息的处理过程与消息如何传递没有什么关系。由于这些问题的存在,我依然决定使用较少面向对象但是更加容易编写的途径。

  前面的示例只处理了单个消息。在现实世界中,我们需要同时处理多个消息。

  服务器端的多线程

  我的最终的目标是把该服务器程序的功能添加到一个已有的应用程序中。因为不希望修改已有的应用程序的代码,我就必须在某个线程上运行服务器程序。同样,我希望可以同时接受多个连接。

  上面的例子在端口9999上监听,但是由于一个客户端只能与一个端口对话,我需要为每个连接使用不同端口的途径。SocketListener类将在9999端口上监视,当新的连接请求到达的时候,它将查找一个未使用的端口并把它发送回给客户端。下面是这个类的大致情形:

public class SocketListener
{
int port;
Thread thread;

public SocketListener(int port)
{
this.port = port;
ThreadStart ts = new ThreadStart(WaitForConnection);
thread = new Thread(ts);
thread.IsBackground = true;
thread.Start();
}

public void WaitForConnection()
{
// 主要的代码
}
}

  WaitForConnection()是执行所有这些操作的方法。这个类的构造函数执行建立新线程的任务,这个线程将运行WaitForConnection()。打开套接字并接受连接与前面的例子相似。下面是该线程的主循环:

while (true)
{
Console.WriteLine("Waiting for initial connection");
listener.Start();
Socket socket = listener.AcceptSocket();
NetworkStream stream = new NetworkStream(socket);
BinaryReader reader = new BinaryReader(stream);
BinaryWriter writer = new BinaryWriter(stream);

Console.WriteLine("Connection Requested");

int userPort = port + 1;
TcpListener specificListener;
while (true)
{
try
{
specificListener =
new TcpListener(localAddr, userPort);
specificListener.Start();
break;
}
catch (SocketException)
{
userPort++;
}
}
//远程用户应该使用specificListener。
//把该端口发送回给远程用户,并为我们在该端口上建立服务器应用程序。
SocketServer socketServer = new SocketServer(specificListener);

writer.Write(userPort);
writer.Close();
reader.Close();
stream.Close();
socket.Close();
}

  我希望能够支持多个连接,因此使用一个端口以便于客户端表明它们希望建立一个连接,接着服务器程序找到一个空的端口并把该端口发送回给客户端,该端口用于特定客户端的连接。

  我没有找到查找未使用端口的方法,因此该While循环用于找出未使用的端口。接着它把该端口号发送回客户端并清除对象。

  此处还有需要指出的一点点微妙之处。SocketServer的原始版本把端口号作为一个参数。不幸的是,这意味着在该端口上建立监听器之前客户端不能作出请求,这是很不好的。为了防止出现这种情况,我在给客户端发送端口号之前建立了TcpListener,它确保不会出现这种紧急情况。

  SocketServer类建立了额外的线程,并使用了下面的主循环:

try
{
while (true)
{
MessageType messageType = (MessageType) reader.ReadInt32();

switch (messageType)
{
case MessageType.RequestEmployee:
Employee employee =
new Employee("Eric Gunnerson", "One Microsoft Way");
employee.Send(writer);
break;
}
}
}
catch (IOException)
{

}
finally
{
socket.Close();
}

  这个主循环是一个简单的获取请求/处理请求的循环。try-catch-finally在此处用于当客户端断开连接的时候从异常中恢复过来。
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章