我正在构建一个C#套接字服务器。我的代码目前有效,但我不确定这是否是正确的方法。
当连接TcpClient
时,我将其放入一个具有以下方法的新对象中,然后调用Init()
开始检查数据是否可用,数据何时可用我调用的事件是I听取我使用我创建的方法(如ReadInt32(), ReadByte(), ReadString() ReadObject<T>()
public void Init()
{
ThreadPool.QueueUserWorkItem(Read);
}
private void Read(object state)
{
if (IsClientConnected())
{
if (_connected.Available > 0)
{
OnDataAvailable(_connected.Available);
}
Init();
}
}
我应该在这里使用While
循环,还是应该像我目前一样重启Init()
?那么我应该使用BackgroundWorker
,Thread
或Task
代替ThreadPool
吗?
我还在考虑将Init()
更改为BeginWait(some sort of callback here)
并删除Init()
中的Read()
,然后再根据需要再次致电BeginWait
我的目的是听取命令并回复命令。同时连接x个客户端。
所以场景如下:
我有一个连接到服务器的应用程序。
然后,服务器使用TcpClient初始化一个新对象作为构造函数中的参数。然后,服务器将连接的客户端添加到与另一个客户端的房间。这个房间听取每个客户的事件DataAvailable
,看看下面的
private void Client_DataAvailable(ClientWrapper sender, int data)
{
var command = (Commands)Client.ReadByte();
switch (command)
{
case Commands.RequestConnectId: // 1
var buffer = new WriteBuffer(Commands.RequestConnectId);
buffer.WriteInt32(sender.ConnectId);
sender.Reply(buffer);
break;
case Commands.WriteText: //2
var buffer = new WriteBuffer(Commands.WriteText);
buffer.WriteString(sender.ReadString());
BroadCast(sender.ConnectId,buffer);//Send to the other client
break;
}
}
答案 0 :(得分:1)
读取套接字的正确方法是从中读取。在数据准备好之前,呼叫将无法完成。没有必要举办活动。 Available
属性几乎总是一个bug,所以不要使用它。
执行:
var command = (Commands)Client.ReadByte();
立即。可以在后台线程上运行它(与注释中建议的相反)。一旦你有太多的线程,线程就成了问题。如果只保留几十个套接字连接,那就没有问题了。
您也可以使用异步IO,最好使用await
。同样的想法适用:只需阅读。
如果要处理命令流,只需将其包装在一个循环中:
while (true) {
ReadCommand();
WriteResponse();
}