C#TCP服务器等待2个客户端响应
我目前正在做一个服务器/客户端项目。 我的问题是,服务器如何等待两个特定连接的响应 服务器:C#TCP服务器等待2个客户端响应,c#,multithreading,tcp,client,server,C#,Multithreading,Tcp,Client,Server,我目前正在做一个服务器/客户端项目。 我的问题是,服务器如何等待两个特定连接的响应 服务器: private TcpListener tcpListener; private Thread listenThread; private List<Connection> ConList = new List<Connection>(); Queue queue = new Queue(); public struct Connection { public Str
private TcpListener tcpListener;
private Thread listenThread;
private List<Connection> ConList = new List<Connection>();
Queue queue = new Queue();
public struct Connection
{
public Stream stream;
public StreamWriter streamw;
public StreamReader streamr;
public TcpClient tcpC;
}
private void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
try
{
Connection c = new Connection();
c.tcpC = this.tcpListener.AcceptTcpClient();
c.stream = c.tcpC.GetStream();
c.streamr = new StreamReader(c.stream);
c.streamw = new StreamWriter(c.stream);
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(c);
queue.Enqueue(c);
}
catch()
{
break;
}
}
}
private void HandleClientComm(Object client)
{
Connection con;
con = (Connection)client;
ConList.Add(con);
byte[] message = new byte[4096];
int bytesRead;
while (true)
{
bytesRead = 0;
try
{
bytesRead = con.stream.Read(message, 0, 4096);
string s = Encoding.UTF8.GetString(message, 0, message.Length);
}
catch
{
//Socket error
break;
}
if (bytesRead == 0)
{
//Client lost connection
con.stream.Close();
con.tcpC.Close();
ConList.Remove(con);
con = null;
break;
}
}
}
private void QueueTimer_Tick(object sender, EventArgs e)
{
if (queue.count >= 2)
{
Connection c1;
Connection c2;
c1 = new Connection();
c1 = (Connection)queue.Dequeue();
c2 = new Connection();
c2 = (Connection)queue.Dequeue();
//Start thread which waits for a response from both connections
}
}
私有TcpListener TcpListener;
私有线程listenThread;
私有列表ConList=新列表();
队列=新队列();
公共结构连接
{
公共溪流;
公共河流;
公共图书馆;
公共tcpC客户端tcpC;
}
私有void listenforcients()
{
这个.tcpListener.Start();
while(true)
{
尝试
{
连接c=新连接();
c、 tcpC=this.tcpListener.AcceptTcpClient();
c、 stream=c.tcpC.GetStream();
c、 streamr=新的StreamReader(c.stream);
c、 streamw=新的StreamWriter(c.stream);
Thread clientThread=新线程(新的参数化ThreadStart(HandleClientCommand));
clientThread.Start(c);
排队。排队(c);
}
捕获()
{
打破
}
}
}
私有void HandleClientCommand(对象客户端)
{
连接con;
con=(连接)客户端;
ConList.Add(con);
字节[]消息=新字节[4096];
int字节读取;
while(true)
{
字节读取=0;
尝试
{
bytesRead=con.stream.Read(消息,04096);
string s=Encoding.UTF8.GetString(message,0,message.Length);
}
接住
{
//套接字错误
打破
}
如果(字节读==0)
{
//客户端失去连接
con.stream.Close();
con.tcpC.Close();
ConList.Remove(con);
con=null;
打破
}
}
}
private void QueueTimer_Tick(对象发送方,事件参数e)
{
如果(queue.count>=2)
{
连接c1;
连接c2;
c1=新连接();
c1=(连接)queue.Dequeue();
c2=新连接();
c2=(连接)queue.Dequeue();
//启动等待两个连接响应的线程
}
}
每个连接都被放置在队列中,如果queue.count>=2(计时器每20秒检查一次),则应启动一个新线程,该线程将等待来自两个客户端的10秒超时响应。我花了三天时间想办法解决问题,但找不到好办法。你们有什么建议吗?这里是一个简单的基于TPL的侦听器/响应器,无需专门为该过程编写线程
private TcpListener _listener;
public void OnStart(CommandLineParser commandLine)
{
_listener = new TcpListener(IPAddress.Any, commandLine.Port);
_listener.Start();
Task.Run((Func<Task>) Listen);
}
private async Task Listen()
{
IMessageHandler handler = MessageHandler.Instance;
while (true)
{
var client = await _listener.AcceptTcpClientAsync().ConfigureAwait(false);
// Without the await here, the thread will run free
var task = ProcessMessage(client);
}
}
public void OnStop()
{
_listener.Stop();
}
public async Task ProcessMessage(TcpClient client)
{
try
{
using (var stream = client.GetStream())
{
var message = await SimpleMessage.DecodeAsync(stream);
_handler.MessageReceived(message);
}
}
catch (Exception e)
{
_handler.MessageError(e);
}
finally
{
(client as IDisposable).Dispose();
}
}
}
专用TcpListener\u侦听器;
public void OnStart(CommandLineParser commandLine)
{
_侦听器=新的TcpListener(IPAddress.Any、commandLine.Port);
_listener.Start();
Task.Run((Func)Listen);
}
专用异步任务侦听()
{
IMessageHandler=MessageHandler.Instance;
while(true)
{
var client=await\u listener.AcceptTcpClientAsync().ConfigureAwait(false);
//如果没有此处的等待,线程将自由运行
var task=ProcessMessage(客户端);
}
}
公共void OnStop()
{
_listener.Stop();
}
公共异步任务ProcessMessage(TcpClient客户端)
{
尝试
{
使用(var stream=client.GetStream())
{
var message=wait SimpleMessage.decodeAxync(流);
_handler.MessageReceived(message);
}
}
捕获(例外e)
{
_handler.MessageError(e);
}
最后
{
(客户端作为IDisposable.Dispose();
}
}
}
首先谈谈QueueTimer\u Tick()函数。其中包含以下代码:
c1 = new Connection();
c1 = (Connection)queue.Dequeue();
第一行不需要,它创建了一个新的连接对象,该对象立即被从队列中拉出的任何内容覆盖。Alos什么东西不能像使用类型化列表一样使用类型化队列
要回答你的问题,我认为你追求的是方法。它将获取套接字列表并检查它们的可读性,还允许指定超时
要实现您想要的,您需要在循环中调用Select(),每次检查尚未变得可读的客户机的可读性时,都要在循环中调用Select()。您还需要计算出每个要选择的调用使用了多少10秒延迟,并相应地调整超时
因此,在psuedo代码中:
create L1 a list of sockets that are to be readable
set the timeout T to 10 seconds
while L1 is not empty
copy L1 to a tempory list L2
Socket.Select(L2,T)
If a timeout then exit loop
Remove the socket(s) that are readable from L1
recalculate T based on how long the Select took
End While
注意:TcpClient.Client()方法获取TcpClient的套接字