使用 C# 构建基于 Linux 的通信服务器,用于 Windows 客户端。






4.73/5 (14投票s)
您可以构建可以在任何支持 Java 的平台上运行的 Java 控制台应用程序。利用这一点以及 System.Net 命名空间(包括 TcpClient 类)的强大功能,您可以创建使用 Linux 服务器和 Windows 窗体客户端进行互操作的分布式应用程序,这得益于 Grasshopper。
引言
您可能拥有一个系统,其中有一个集中的服务器系统为许多客户端应用程序提供服务,整个系统是端到端用 .NET 构建的。在迁移方面,将服务器端软件迁移到 J2EE 或 Linux 是更常见的需求,但客户端则不那么常见。但是,如果您使用的系统是 Windows 窗体客户端通过 Windows 服务器相互通信,您可能会认为您无法迁移服务器——好消息是您错了,因为 Windows 窗体客户端可以使用各种技术非常有效地与迁移的服务器端应用程序通信。
在本文中,您将逐步使用 C# 构建一个简单的 TCP/IP 服务器,该服务器在 Windows 上使用 .NET 运行时运行,然后您将使用 Visual MainWin for J2EE 进行修改,将其迁移到 J2EE,最后将其安装在 Linux 上。此外,您还将创建一个 Windows 窗体客户端,该客户端将在 Windows 上运行,并在不进行任何修改的情况下与基于 Linux 的服务器通信。
入门
首先,您需要获取一份 Visual MainWin for J2EE,可以从 这里 下载。这是一个 Visual Studio .NET 的插件,它允许您将 MSIL 代码重新编译成 Java 字节码,该字节码将在您的目标操作系统(在此案例中为 Linux)上的 JVM 上运行。请务必从下载时指定的电子邮件地址获取您的激活密钥,并使用它激活您的 Visual MainWin for J2EE 安装。
现在您可以构建服务器应用程序了。在 Visual Studio .NET 中创建一个新的 Visual C# 控制台应用程序。您应该将此应用程序命名为“MainsoftChat”。
Visual Studio .NET 将为您创建一个新的项目,其中包含一个名为“Class1.cs”的类。删除此类,并添加一个名为“ChatServer.cs”的新类。下载文件中包含 ChatServer.cs 及其支持的辅助类的完整源代码。
ChatServer
上的 Main
方法如下所示
static void Main(string[] args)
{
if (args.Length<2)
{
System.Console.WriteLine("Please pass 2 arguments:" +
" 1 for IP address, 1 for Port to listen on.");
}
else
{
localHost = Dns.Resolve(args[0]).AddressList[0];
myPort = Convert.ToInt32(args[1]);
// Write out our status
System.Console.WriteLine("Server Started, listening on: " +
localHost.ToString() + ":" + myPort);
// Start the Client Thread.
myThread = new Thread(new System.Threading.ThreadStart(DoListen));
myThread.Start();
}
}
该应用程序被设计为接受两个参数:一个用于服务器运行所在机器的 IP 地址,另一个用于服务器监听的端口。请注意,可以使用 .NET 的 DNS.Resolve
功能自动确定 IP 地址,但这并不总是可靠的,尤其是在 Linux 上运行时,因为它通常会返回机器的 127.0.0.1 地址,而我们想要使用机器暴露的“外部”IP 地址。
然后 Main
例程会启动一个新 Thread
,执行 DoListen()
函数,这是此应用程序的核心。
private static void DoListen()
{
myListener = new TcpListener(localHost, myPort);
// Start off the listener
myListener.Start();
// Local throwaway client variable to put into the hashtable
Client x;
do
{
TcpClient s = myListener.AcceptTcpClient();
String strServerIP =
IPAddress.Parse(((IPEndPoint)myListener.LocalEndpoint).
Address.ToString()).ToString() ;
x = new Client(s);
x.Connected+= new ConnectedHandler(OnConnected);
x.Disconnected+= new DisconnectedHandler(OnDisconnected);
x.IncomingMessage+=
new IncomingMessageHandler(OnIncomingMessage);
tmpClients.Add(x.ID,x);
}
while(true);
}
此函数设置一个新的 TcpListener
,该监听器将在指定的 IP 和端口上进行监听,并开始监听。一旦建立连接,AcceptTcpClient
函数将被触发,并且 TcpClient
“s
”将被初始化。然后设置事件委托来处理来自此客户端的连接、断开连接和传入消息。
该应用程序维护两个客户端的哈希表;有一个临时哈希表,客户端在 TCP 级别建立初始连接与其最终连接之间位于其中,通过向聊天服务器发出其名称(使用 IRC 的“nick:”说法)。一旦它将名称告知服务器,它就被分配到主哈希表中。
每当客户端发送消息时,OnIncomingMessage
函数就会触发,并且会处理各种支持的命令,例如“says”。有关更多详细信息,请参阅下载中的代码。
在 Visual Studio .NET 中,您可以通过右键单击解决方案资源管理器中的项目,然后选择“属性”来指定命令行参数。在“配置属性”文件夹的“调试”条目中,您将看到“命令行参数”条目。在此处输入您的机器的 IP 地址以及您要使用的端口,用空格分隔。请参阅图 2 获取示例。
当您执行应用程序时,您将看到一个窗口,如下所示
将其迁移到 Linux 非常简单。如果您在机器上安装了 Visual MainWin for J2EE,您可以在解决方案资源管理器中右键单击项目,然后选择“生成 J2EE 项目”。这将启动一个向导,为您创建此应用程序的 J2EE 版本。该向导将分析 C# 项目及其引用,并创建一个 J2EE 项目的 Visual MainWin C#。
请参阅图 4 和图 5 查看向导的实际操作
完成后,您将在解决方案中看到两个项目。新项目将以“.J2EE”为前缀,因此它将被称为“MainsoftChat.J2EE”。此 J2EE 项目引用了您的原始 MainsoftChat C# 项目所引用的源文件,因此您可以从该解决方案中同时为 .NET 和 J2EE 编译相同的源文件。这对于维护 .NET 和 J2EE 的单一代码库可能非常有价值。
将此设置为您的启动项目(右键单击并选择“设置为启动项目”)。另外,像之前一样更改此项目的命令行参数。现在按 F5 执行项目。您将在图 6 中看到该应用程序如何在 Java 中运行。
此时,Visual MainWin for J2EE 插件正在将 .NET 编译器生成的 MSIL 代码交叉编译成 Java 字节码。然后,该字节码在您的 Java 虚拟机中使用 Mainsoft 基于 mono 的 .NET 框架依赖项实现来运行。图 6 显示了应用程序的运行情况,并附带完整的 Java 命令行,以便您可以看到其执行方式。要获取执行应用程序时的完整命令行,请查看开发者区域知识库。
现在我们已经在 Java 中运行它了,将其在 Linux 上运行也非常简单。
首先,在您的 Linux 机器上,您必须确保您拥有 Visual MainWin 应用程序所需的所有 JAR 文件。您可以在 Windows 机器上的 \Program Files\Mainsoft\Visual MainWin for J2EE\jgac\vmw4j2ee_110 目录中找到它们。在您的 Linux 机器上创建一个目录(我推荐 /opt/vmwj2ee,因为本文档附带的可下载脚本已配置为使用该目录),并将所有 JAR 文件复制到其中。
如果您还没有,请确保您的 Linux 机器上安装了 JRE 或 JDK,并且 $JAVA_HOME
和 $
CLASSPATH
变量已正确设置。我更喜欢在 /etc/profile.d 中的 java.sh 或 alljava.sh 文件中进行此操作。
将这些行添加到 export JAVA_HOME=/opt/java/j2sdk1.4.2_10 或您安装 SDK 的任何位置的底部。
CLASSPATH=$JAVA_HOME:$JAVA_HOME/lib:/opt/vmwj2ee/
export CLASSPATH=$CLASSPATH
这样,当您登录系统时,它们就会被设置好。
接下来,创建一个名为 chatserver 的文件夹。您可以将其放在任何喜欢的位置,但我更喜欢使用 /opt 文件夹,所以我使用了 /opt/chatserver。
回到您的 Windows 机器,找到 MainsoftChat 应用程序的项目目录。在其 bin 文件夹中,您会找到 MainsoftChat.jar 文件。将其从您的 Windows 机器复制到您刚刚在 Linux 机器上创建的目录。
最后,您将设置一个命令脚本,用于在 Linux 上执行聊天服务器应用程序。使用文本编辑器,创建一个名为 chatserver.sh 的文件,并将以下代码放入其中。
java -cp $JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar
:/opt/vmwj2ee/:/opt/vmwj2ee/System.jar:/opt/vmwj2ee/J2EE.Helpers.jar
:/opt/vmwj2ee/J2SE.Helpers.jar:/opt/vmwj2ee/Microsoft.VisualBasic.jar
:/opt/vmwj2ee/Novell.Directory.Ldap.jar:/opt/vmwj2ee/System.Data.jar
:/opt/vmwj2ee/System.DirectoryServices.jar:/opt/vmwj2ee/System.Drawing.jar
:/opt/vmwj2ee/System.Runtime.Remoting.jar:/opt/vmwj2ee/
System.Runtime.Serialization.Formatters.Soap.jar
:/opt/vmwj2ee/System.Web.Services.jar:/opt/vmwj2ee/System.Web.jar
:/opt/vmwj2ee/System.Xml.jar:/opt/vmwj2ee/jai_imageio.jar
:/opt/vmwj2ee/mscorlib.jar:/opt/vmwj2ee/vmwutils.jar:MainsoftChat.jar
MainsoftChat.ChatServer 192.168.0.6 1234
(或者,命令脚本包含在下载文件中。)
现在,您可以通过切换到 /opt/chatserver 目录并输入以下命令来启动 Linux 上的聊天服务器:
. chatserver.sh
如果一切设置正确,您将在图 7 中看到类似的内容。
Windows 窗体客户端
目前这看起来并不令人兴奋——有一个监听端口的服务器只有在有东西以服务器能理解的语言或协议在该端口上通信时才有意义。这就是 Windows 窗体客户端应用程序的用武之地。完整的窗体可在本文附带的下载中找到。
您可以在图 8 中看到应用程序的运行情况。
此应用程序使用 TcpClient 类库与服务器通信。启动应用程序时,输入用户名以及服务器的 IP 和端口。例如,如果您的 Linux 服务器正在运行在 192.168.0.6,端口 1234,如上面的示例所示,请在此处输入这些值并单击“连接”。
成功连接到服务器后,您应该能够与其他客户端聊天(您可以在您的 PC 上运行多个客户端),而 Linux 服务器则提供应用程序。请参阅图 9 和图 10,了解在 Windows 前端和 Linux 后端上进行此操作。
结论
如果您有一个分布式应用程序,其中有一个集中的系统为多个客户端提供服务,并且您想将服务器迁移到 Linux,您并不局限于基于 Web 的服务器,如 Web 应用程序或 Web 服务。在本文中,您了解了如何迁移 TCP/IP 基于的系统(如聊天应用程序)到 Linux,以及您的基于 Windows 窗体的客户端如何仍然可以与其互操作。