我写这个TCP通信库。问题是。当客户端连接时。 CPU使用率增加到最大值......这会导致其他应用程序变慢...
请看一下代码并纠正我错误的地方..
我的TCP库的主要代码是
TCP服务器类
public class TCPServerEndPoint : ICommunication
{
private string channelName;
private string localIP;
private int localPort;
private string remoteIP;
private int remotePort;
private TcpListener tcpListenter;
/// <summary>
/// Accept the incomming connection and pass it to a thread to handle communication.
/// </summary>
private TCPServerWorker worker;
/// <summary>
/// List of threads created for connected clients.
/// </summary>
List<TCPServerWorker> workerThreads;
/// <summary>
/// Thread to keep listening process in seperate thread.
/// </summary>
private Thread serverThread;
/// <summary>
/// Flag to keep status of Endpoint.
/// </summary>
private bool keepRunning;
public TCPServerEndPoint()
{
this.keepRunning = false;
Guid guid = Guid.NewGuid();
channelName = guid.ToString();
workerThreads = new List<TCPServerWorker>();
}
public TCPServerEndPoint(string localIP, int localPort, string remoteIP, int remotePort)
{
this.localIP = localIP;
this.localPort = localPort;
this.remoteIP = remoteIP;
this.remotePort = remotePort;
workerThreads = new List<TCPServerWorker>();
this.keepRunning = false;
}
public event EventHandler<CommEventArgs> OnCommReceive;
public int CommStart()
{
if (this.IsStarted == true)
{
Console.WriteLine("TCP Server is already running");
return -1;
}
serverThread = new Thread(new ThreadStart(StartListening));
serverThread.IsBackground = true;
serverThread.Start();
return 0;
}
private void StartListening()
{
try
{
IPAddress localAddress = IPAddress.Parse(this.localIP);
tcpListenter = new TcpListener(localAddress, this.localPort);
tcpListenter.Start();
Console.WriteLine("TCP Server started");
Console.WriteLine("Server is listening on port : {0}", this.localPort);
this.keepRunning = true;
// look for incomming connections
while (this.keepRunning)
{
// connection received
TcpClient client = tcpListenter.AcceptTcpClient();
// create a new WorkerThread and pass the connected client to handle.
worker = new TCPServerWorker(client);
worker.dataReceived += new EventHandler<CommEventArgs>(worker_dataReceived);
workerThreads.Add(worker);
worker.Start();
}
tcpListenter.Stop();
Console.WriteLine("TCP Server stopped");
this.keepRunning = false;
}
catch
{
return;
}
}
void worker_dataReceived(object sender, CommEventArgs e)
{
if (this.OnCommReceive != null)
{
e.commChannel = this;
this.OnCommReceive(this, e);
}
}
public int CommStop()
{
if (this.IsStarted == false)
return -1;
// Close all worker threads created for connected clients.
foreach (TCPServerWorker item in workerThreads)
{
item.KeepRunning = false;
}
// break the listening loop
this.keepRunning = false;
// clear the worker thread list
workerThreads.Clear();
// force server to receive message to break while(keepRunning) loop
byte[] data = new byte[4];
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse(this.localIP), localPort);
Socket tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
tcpClient.Connect(ipEndPoint);
tcpClient.SendTo(data, ipEndPoint);
tcpClient.Close();
return 0;
}
public int CommSend(CommEventArgs obj)
{
obj.destAddress = this.remoteIP;
obj.destPort = this.remotePort;
return CommSendTo(obj);
}
public int CommSendTo(CommEventArgs obj)
{
int n;
byte[] buf;
try
{
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse(obj.destAddress), obj.destPort);
buf = (byte[])obj.data;
Socket tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
tcpClient.Connect(ipEndPoint);
n = tcpClient.SendTo(buf, ipEndPoint);
tcpClient.Close();
}
catch (Exception ex)
{
Console.WriteLine("Exception :: {0}", ex.Message);
return -1;
}
if (n == buf.Length)
{
if (OnCommSendComplete != null)
{
OnCommSendComplete(this, obj);
}
Console.WriteLine("Sent {0} bytes to {1}:{2}", n, obj.destAddress, obj.destPort);
}
else
{
return -1;
}
return n;
}
}
}
TCPServerWorker.cs
class TCPServerWorker
{
private TcpClient client;
private bool keepRunning;
public event EventHandler<CommEventArgs> dataReceived;
private const int MAX_TCP_DATA = 64000;
public bool KeepRunning
{
get
{
return this.keepRunning;
}
set
{
this.keepRunning = value;
}
}
public TCPServerWorker(TcpClient client)
{
this.client = client;
this.keepRunning = false;
}
public void Start()
{
Thread thread = new Thread(new ThreadStart(Process));
thread.IsBackground = true;
thread.Start();
}
private void Process()
{
if (client.Connected == true)
{
Console.WriteLine("Client connected :: {0}", client.Client.RemoteEndPoint);
this.keepRunning = true;
while (this.keepRunning)
{
// in my view. here is the main problem. this loop run for infinite time and causes CPU to reach at 100
byte[] buffer = new byte[MAX_TCP_DATA];
NetworkStream stream = client.GetStream();
StreamWriter writer = new StreamWriter(client.GetStream());
if (stream.DataAvailable == true)
{
int receivedBytesCount = stream.Read(buffer, 0, buffer.Length);
byte[] receivedBuffer = new byte[receivedBytesCount];
Array.Copy(buffer, receivedBuffer, receivedBytesCount);
String msg = Encoding.UTF8.GetString(receivedBuffer);
Console.WriteLine("Received MSG ::: " + msg);
writer.WriteLine("Server : Received {0} bytes", receivedBytesCount);
CommEventArgs comEventArg = new CommEventArgs();
comEventArg.data = (byte[])receivedBuffer;
IPEndPoint remoteIPEndPoint = (IPEndPoint)client.Client.RemoteEndPoint;
comEventArg.srcAddress = remoteIPEndPoint.Address.ToString();
comEventArg.srcPort = remoteIPEndPoint.Port;
comEventArg.length = receivedBytesCount;
this.OnDataReceived(comEventArg);
writer.Flush();
}
}
client.Close();
}
}
protected void OnDataReceived(CommEventArgs e)
{
if (this.dataReceived != null)
{
this.dataReceived(this, e);
}
}
}
}
答案 0 :(得分:1)
您正在使用非阻塞I / O,这会导致客户端(至少)循环
while (this.keepRunning) {...}
通过忙碌等待消耗所有CPU资源。
您应该考虑使用阻塞I / O或Socket.Select
查看第一句话here
有关select
的详细信息答案 1 :(得分:0)
有一点需要注意的是,你从未设置过IsStarted ..你只需要它._。也许你正在产生数百个线程= /我在谈论TCPServerEndPoint类= /
答案 2 :(得分:0)
是的,您正忙着等待连接。我不知道套接字编程所以我不能给你详细信息,但你需要做的是等待使用阻塞系统调用的连接。
答案 3 :(得分:0)
我在修改TCPServerWorker.cs的Process方法后解决了这个问题
这是更改
private void Process()
{
if (client.Connected == true)
{
Console.WriteLine("Client connected :: {0}", client.Client.RemoteEndPoint);
Byte[] bytes = new Byte[MAX_TCP_DATA];
String data = null;
NetworkStream stream = client.GetStream();
int i;
try
{
// Loop to receive all the data sent by the client.
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
// bytes contains received data in byte[].
// Translate data bytes to a UTF-8 string.
byte[] receivedBuffer = new byte[i];
Array.Copy(bytes, receivedBuffer, i);
data = System.Text.Encoding.UTF8.GetString(receivedBuffer);
Console.WriteLine("Received MSG ::: " + data);
// Process the data sent by the client.
byte[] msg = System.Text.Encoding.UTF8.GetBytes(data);
// Send back a response.
stream.Write(msg, 0, msg.Length);
CommEventArgs comEventArg = new CommEventArgs();
comEventArg.data = receivedBuffer;
IPEndPoint remoteIPEndPoint = (IPEndPoint)client.Client.RemoteEndPoint;
comEventArg.srcAddress = remoteIPEndPoint.Address.ToString();
comEventArg.srcPort = remoteIPEndPoint.Port;
comEventArg.length = i;
this.OnDataReceived(comEventArg);
}
}
catch (Exception ex)
{
Console.WriteLine("Exception : " + ex.Message);
}
finally
{
client.Close();
}
}
}