我正在尝试创建一个Windows服务,当文件到达FTP位置时,通过TCP向相关用户发送消息。我已经设置了所有文件检测部分,但我需要在消息传递方面提供一些帮助。
由于会有多个用户同时订阅此服务,因此需要能够处理多个连接,因此我在服务启动时创建TCPServer服务器,并开始侦听传入连接。当一个人到达时,代码会将连接添加到连接列表中。
到目前为止,这么好。
当传入文件触发向相关客户端发送消息时,会出现问题。尝试访问连接列表失败,因为我必须从一个单独的线程执行它(因为侦听新连接的线程在此期间不能执行任何其他操作)。
在调试模式下运行它,我看到New Connection正确地增加了ClientList的计数,但是当调试器返回到类发送消息时,ClientList变量被重置为0,因为我不得不创建一个新的类实例。任何想法都会非常感激。
我的代码如下:
namespace WindowsService1
{
class MSGServer
{
TcpListener server = null;
Int32 port = 13000;
IPAddress localAddr;
List<ClientConn> ClientList = new List<ClientConn>();
Byte[] data;
private object l_lock = new object();
public void CreateServer()
{
localAddr = IPAddress.Parse("172.26.114.71");
server = new TcpListener(localAddr, port);
server.Start();
NewConnection();
}
public void NewConnection()
{
Debugger.Break();
while (true)
{
ClientConn Client = new ClientConn();
Client.TClient = server.AcceptTcpClient();
NetworkStream stream = Client.TClient.GetStream();
data = new Byte[256];
String MSG = String.Empty;
Int32 bytes = stream.Read(data, 0, data.Length);
Client.ClientUserName = Encoding.ASCII.GetString(data, 0, bytes);
stream.Write(data, 0, bytes);
lock (ClientList)
{
ClientList.Add(Client);
}
}
}
public Boolean SendNotification(string UserName, string FFolder, string FName)
{
Debugger.Break();
NetworkStream Stream;
bool MsgSent = false;
foreach (ClientConn Client in ClientList)
{
if (Client.ClientUserName == UserName)
{
Byte[] MsgByte = Encoding.ASCII.GetBytes(FFolder + "|" + FName);
Stream = Client.TClient.GetStream();
Stream.Write(MsgByte, 0, MsgByte.Length);
MsgSent = true;
}
}
return MsgSent;
}
public void CLoseAllConnections()
{
foreach (ClientConn ConnToClose in ClientList)
{
ConnToClose.TClient.Close();
}
}
}
class ClientConn
{
private string CUser;
TcpClient Client;
public string ClientUserName
{
get { return CUser;}
set { CUser = value; }
}
public TcpClient TClient
{
get { return Client; }
set { Client = value; }
}
}
}
更新:通过将运行CreateServer()的类的实例传递给最终调用SendNotification方法的线程,解决了我在下面讨论的问题。谢谢你的帮助
答案 0 :(得分:2)
您可以使用BlockingCollection(T)
。
class MSGServer
{
TcpListener server = null;
Int32 port = 13000;
IPAddress localAddr;
private readonly BlockingCollection<ClientConn> ClientList = new BlockingCollection<ClientConn>();
Byte[] data;
public void CreateServer()
{
localAddr = IPAddress.Parse("172.26.114.71");
server = new TcpListener(localAddr, port);
server.Start();
NewConnection();
}
public void NewConnection()
{
Debugger.Break();
while (true)
{
ClientConn Client = new ClientConn();
Client.TClient = server.AcceptTcpClient();
NetworkStream stream = Client.TClient.GetStream();
data = new Byte[256];
String MSG = String.Empty;
Int32 bytes = stream.Read(data, 0, data.Length);
Client.ClientUserName = Encoding.ASCII.GetString(data, 0, bytes);
stream.Write(data, 0, bytes);
ClientList.Add(Client);
}
}
public Boolean SendNotification(string UserName, string FFolder, string FName)
{
Debugger.Break();
NetworkStream Stream;
bool MsgSent = false;
foreach (ClientConn Client in ClientList.GetConsumingEnumerable().Where(c => c.ClientUserName == UserName))
{
Byte[] MsgByte = Encoding.ASCII.GetBytes(FFolder + "|" + FName);
Stream = Client.TClient.GetStream();
Stream.Write(MsgByte, 0, MsgByte.Length);
MsgSent = true;
}
return MsgSent;
}
public void CLoseAllConnections()
{
foreach (ClientConn ConnToClose in ClientList)
{
ConnToClose.TClient.Close();
}
}
}