在现代编程实践中,网络编程是一个不可或缺的技能。随着.NET框架的发展,网络通信的首选方式已经转变为使用远程方法调用(Remoting)和Web服务。然而,在某些情况下,可能需要与.NET出现之前编写的原生程序进行通信,或者无法确保所有客户端都运行.NET程序。这时,可以利用较低级别的网络类来构建基于网络的程序。本文将介绍如何使用Managed C++创建一个简单的多线程TCP服务器和客户端,以及它们之间的交互过程。
首先设计一个名为SpookServer
的TCP服务器类,它负责监听端口并接受连接。服务器的功能非常简单:接收一行文本并返回其反转版本。服务器类使用TcpListener
类来监听连接,并为每个连接创建一个新的线程来处理客户端请求。
以下是SpookServer
类的基本实现:
class SpookServer
{
private:
TcpListener* lis;
Thread* t;
ManualResetEvent* mre;
public:
SpookServer(int port)
{
mre = new ManualResetEvent(true);
lis = new TcpListener(port);
t = new Thread(new ThreadStart(this, &SpookServer::ServerThread));
t->Start();
}
void CloseServer()
{
mre->Reset();
lis->Stop();
}
private:
void ServerThread()
{
lis->Start();
while (mre->WaitOne(100, false))
{
try
{
TcpClient* c = lis->AcceptTcpClient();
SpookClient* sc = new SpookClient(c);
}
catch (Exception* e)
{
}
}
}
};
在这个类中,使用ManualResetEvent
对象进行同步,以便调用类或方法可以随时停止服务器。服务器在一个新线程中监听连接,以便可以将控制权返回给调用类。使用TcpListener
类的AcceptTcpClient
方法,该方法返回一个TcpClient
对象,表示已连接的客户端。然后立即实例化一个新的SpookClient
对象,并将返回的TcpClient
对象传递给它的构造函数。这样,可以允许无数客户端同时连接。
接下来,设计一个名为SpookClient
的TCP客户端类,它负责与服务器进行通信。客户端类使用TcpClient
对象连接到服务器,并使用NetworkStream
对象发送和接收数据。
以下是SpookClient
类的基本实现:
class SpookClient
{
private:
TcpClient* m_c;
Thread* t;
public:
SpookClient(TcpClient* c)
{
m_c = c;
t = new Thread(new ThreadStart(this, &SpookClient::StartChat));
t->IsBackground = true;
t->Start();
}
private:
void StartChat()
{
NetworkStream* ns = m_c->GetStream();
unsigned char buffer[] = new unsigned char[128];
String* str = "";
while (true)
{
int d = ns->Read(buffer, 0, 127);
str = String::Concat(str, Encoding::ASCII->GetString(buffer, 0, d));
if (str->LastIndexOf('\n') != -1)
break;
}
str = str->Trim();
str = String::Concat("\n", str);
buffer = Encoding::ASCII->GetBytes(str);
Array::Reverse(buffer);
ns->Write(buffer, 0, buffer->Length);
ns->Flush();
ns->Close();
m_c->Close();
}
};
在这个类中,首先获取TcpClient
对象的NetworkStream
对象,然后使用Write
和Read
方法发送和接收数据。简单地接收一行文本,然后将其反转并发送回服务器。记得在完成后Flush
和Close
NetworkStream
对象,然后调用Close
方法关闭TcpClient
对象。
除了使用Managed C++创建客户端外,还可以利用MFC(Microsoft Foundation Classes)创建一个基于对话框的客户端应用程序。这个客户端使用CSocket
类与Managed C++TCP服务器进行通信。
以下是MFC客户端的基本实现:
void CTcpClientMFCDlg::OnBnClickedButton1()
{
UpdateData(TRUE);
m_text += "\n";
CSocket s;
s.Create();
if (s.Connect("127.0.0.1", 20248))
{
s.Send(m_text, m_text.GetLength());
m_text = "";
char buff[17];
int i;
while (m_text.Find('\n') == -1)
{
i = s.Receive(buff, 16);
buff[i] = 0;
m_text += buff;
}
m_text.Trim();
UpdateData(FALSE);
}
s.Close();
}