我一直在使用c#中的TCP套接字在客户端/服务器应用程序中消耗慢客户端消息。每当慢客户端连接到服务器时,它都会影响其他客户端的处理。
在c#中阅读了一些关于tcp / ip堆栈的文献后,我得出结论,由于客户端RCV_BUFFER已满,服务器端SND_BUFFER已满,其他客户端正在影响。
虽然我无法在真实环境中制作场景,所以这就是我为模拟慢速客户端消息处理所做的工作。
我看到那个没有睡眠时间的客户正在影响,但我无法确定这个问题的模式。
以下是一些疑问,我想清除我的困惑。 1.如何在将数据发送到服务器端的TCP SEND_WINDOW之前确定SND_BUFFER的大小。 2.我应该采取哪些步骤来确定问题的模式。所以我可以继续解决。
以下是服务器端的代码段。
public bool Start()
{
try
{
_listener.Bind(new IPEndPoint(IPAddress.Any, _port));
_listener.Listen(2000);
_listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 5000);
_listener.BeginAccept(ConnectionReady, null);
LogHelper.ErrorLogger.Debug("Listening started");
return true;
}
catch
{
return false;
}
}
public void createSession(object obj)
{
Socket conn = (Socket)obj;
try
{
LogHelper.ErrorLogger.Debug("Creating Session");
ConnectionState st = new ConnectionState(conn); // Custom class for maintaining the socket object
st._server = this;
st._provider = _provider;
st._buffer = new byte[4];
st._provider.OnAcceptConnection(st);
AcceptConnection.BeginInvoke(st, null, st);
LogHelper.ErrorLogger.Debug("Session Created");
}
catch (Exception ex)
{
try
{
conn.Close();
}
catch { }
LogHelper.ErrorLogger.Debug("Session aborted - >" + ex.ToString());
}
}
private void AcceptConnection_Handler(object state)
{
try
{
ConnectionState st = state as ConnectionState;
try
{
st.AuthenticateSocket();
//Starts the ReceiveData callback loop
if (st._conn.Connected)
st._conn.BeginReceive(st._buffer, 0, 0, SocketFlags.None, ReceivedDataReady, st);
}
catch
{
DropConnection(st);
}
}
catch { }
}
private void ReceivedDataReady_Handler(IAsyncResult ar)
{
try
{
ConnectionState st = ar.AsyncState as ConnectionState;
try
{
try
{
int bytesRcv = st._conn.EndReceive(ar);
//Encoding.UTF8.GetString(buffer, 0, readBytes);
//state.msgBuffer.Append(_receivedStr);
}
catch
{
DropConnection(st); return;
}
//Im considering the following condition as a signal that the
//remote host droped the connection.
if (st._conn.Available == 0)
{
DropConnection(st);//@@SHARIQ
return;
}
else
{
try
{
st._provider.OnReceiveData(st);
}
catch
{
return;
}
//Resume ReceivedData callback loop
if (st._conn.Connected)
st._conn.BeginReceive(st._buffer, 0, 0, SocketFlags.None, ReceivedDataReady, st);
}
}
catch { DropConnection(st); return; }
}
catch { }
}
从MSMQ获取消息(一个线程正在运行以通过接收器对象从MSMQ获取消息),并且在触发事件后提取消息并从消息中提取IP地址并将一条消息发送到套接字。
private void m_broker_OnMessage(object obj)
{
try
{
Message m = (Message)obj;
m.Formatter = new BinaryMessageFormatter();
ConnectionState tstate = null;
bool containststate = false;
string TempLabels = string.Empty;
string BodyMessage = string.Empty;
if (m.Body.ToString().StartsWith("="))
{
BodyMessage = (string)m.Body;
TempLabels = BodyMessage.Substring(1, BodyMessage.IndexOf('#') - 1);
BodyMessage = BodyMessage.Substring(BodyMessage.IndexOf('#') + 1);
}
if (!string.IsNullOrEmpty(TempLabels))
{
string[] labels = TempLabels.Split(',');
foreach (string label in labels)
{
lock (cons)
{
containststate = cons.Contains(label);
if (containststate)
{
tstate = (ConnectionState)cons[label];
}
}
if (containststate)
{
ConnectionState state = tstate;
if (!state.WriteLine(BodyMessage + "1057=" + label + "#"))
{
OnDropConnection(state);
continue;
}
if (ConfigurationSettings.AppSettings["FullLog"] == "1")
{
eventLogger.Debug("OUT " + label + " " + BodyMessage);
}
}
else
{
long result;
if (!lastResolve.Contains(label))
{
if ((!string.IsNullOrEmpty(label)) && long.TryParse(label, out result))
{
if (ConfigurationSettings.AppSettings["FullLog"] == "1")
{
eventLogger.Info("Label not found: " + label);
}
string msg = "8=EXX.1.0#35=C7#1057=" + label + "#";
this.Send(msg, label, "0.0.0.0");
eventLogger.Info("Connection Disconnected: " + label);
//Nothing to clean here
lock (cons)
{
if (cons.Contains(label))
{
try
{
string ipaddress = ((ConnectionState)cons[label]).RemoteEndPoint.ToString().Split(':')[0];
connectionGroups[ipaddress]--;
}
catch { }
}
cons.Remove(label);
lastResolve.Add(label);
}
}
}
continue;
}
}
}
else
{
lock (cons)
{
containststate = cons.Contains(m.Label);
if (containststate)
{
tstate = (ConnectionState)cons[m.Label];
}
}
if (containststate)
{
ConnectionState state = tstate;
if (!state.WriteLine((string)m.Body + "1057=" + m.Label + "#"))
{
OnDropConnection(state);
return;
}
if (ConfigurationSettings.AppSettings["FullLog"] == "1")
{
eventLogger.Debug("OUT " + m.Label + " " + m.Body.ToString());
}
}
else
{
long result;
if (!lastResolve.Contains(m.Label))
{
if ((!string.IsNullOrEmpty(m.Label)) && long.TryParse(m.Label, out result))
{
if (ConfigurationSettings.AppSettings["FullLog"] == "1")
{
eventLogger.Info("Label not found: " + m.Label);
}
string msg = "8=EXX.1.0#35=C7#1057=" + m.Label + "#";
this.Send(msg, m.Label, "0.0.0.0");
eventLogger.Info("Connection Disconnected: " + m.Label);
//Nothing to clean here
lock (cons)
{
if (cons.Contains(m.Label))
{
try
{
string ipaddress = ((ConnectionState)cons[m.Label]).RemoteEndPoint.ToString().Split(':')[0];
connectionGroups[ipaddress]--;
}
catch { }
}
cons.Remove(m.Label);
lastResolve.Add(m.Label);
}
}
}
return;
}
}
}
catch (Exception e)
{
errorLogger.Error(e.Message, e);
}
}
以阻止方式发送
public int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags)
{
lock (sendObject)
{
try
{
if (_innerSocketStream.IsUsingSsl)
{
myStream.Write(buffer, offset, size);
}
else
{
_innerSocketStream.Socket.Send(buffer, offset, size, SocketFlags.None);
}
}
catch (SocketException)
{
return 0;
}
return size;
}
}