C# TCP套接字BeginReceive在收到少量消息后停止
这是我的设想: 客户: 全天候连续发送xml数据(工作正常,不在我的控制范围内)。 服务器-我的代码: 1.不断地听。 2.接收传入消息,对其进行缓冲,并从缓冲区中创建有效的xml。 3.将其发送到MSMQ(主机将执行此操作) 我编写了一个tcp服务器代码(添加了来自google的代码片段),它将托管在windows服务中。当我在本地运行该服务时,一切正常,但当我将其置于PROD时,它会侦听多达73K条消息,并停止接收。它没有抛出任何异常。它只是在开始接收功能时阻塞。我也尝试过使用ReceiveTimeOut。我也看到了netstat,连接仍然处于已建立状态。 当我重新启动服务时,它再次正常工作。这里我张贴我的服务器代码。请帮忙C# TCP套接字BeginReceive在收到少量消息后停止,c#,sockets,tcp,C#,Sockets,Tcp,这是我的设想: 客户: 全天候连续发送xml数据(工作正常,不在我的控制范围内)。 服务器-我的代码: 1.不断地听。 2.接收传入消息,对其进行缓冲,并从缓冲区中创建有效的xml。 3.将其发送到MSMQ(主机将执行此操作) 我编写了一个tcp服务器代码(添加了来自google的代码片段),它将托管在windows服务中。当我在本地运行该服务时,一切正常,但当我将其置于PROD时,它会侦听多达73K条消息,并停止接收。它没有抛出任何异常。它只是在开始接收功能时阻塞。我也尝试过使用Receive
StringBuilder content = new StringBuilder();
public event MessageReceiveEventHandler MessageReceived;
// An ArrayList is used to keep track of worker sockets that are designed
// to communicate with each connected client. Make it a synchronized ArrayList
// For thread safety
private System.Collections.ArrayList workerSocketList =
ArrayList.Synchronized(new System.Collections.ArrayList());
private int m_clientCount = 0;
private Socket m_mainSocket = null;
private AsyncCallback ReadCallback;
private AsyncCallback ConnectionCallback;
public MedDeviceListener(string ipAddress, int port, int maxConnections=100)
{
ProfileProvider.Instance.LogInformationIf(_debug);
this._port = port;
this._ipAddress = ipAddress;
this._maxConnections = maxConnections;
ReadCallback = new AsyncCallback(Receive_handler);
ConnectionCallback = new AsyncCallback(Connection_handler);
lenghtofStartMsg = header.Length;
lengthOfEndMsg = footer.Length;
}
public void Start()
{
ProfileProvider.Instance.LogInformationIf(_debug);
// Data buffer for incoming data.
byte[] bytes = new Byte[_bufferSize];
// Establish the local endpoint for the socket.
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse(_ipAddress), _port);
// Create a TCP/IP socket.
m_mainSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
m_mainSocket.Bind(localEndPoint);
m_mainSocket.Listen(100);
InstrumentationProvider.Instance.LogInformation("MedDeviceListener successfully connected to IP:" + _ipAddress+"\nPort :"+_port);
m_mainSocket.BeginAccept(ConnectionCallback, m_mainSocket);
}
catch (Exception e)
{
InstrumentationProvider.Instance.LogException("MedDeviceListener.Start", e);
throw e;
}
}
private void Connection_handler(IAsyncResult ar)
{
try
{
ProfileProvider.Instance.LogInformationIf(_debug);
Socket listener = (Socket)ar.AsyncState;
Socket workerSocket = listener.EndAccept(ar);
// Now increment the client count for this client
// in a thread safe manner
Interlocked.Increment(ref m_clientCount);
// Add the workerSocket reference to our ArrayList
workerSocketList.Add(workerSocket);
SendConnectedAck(_clientConnectAckMessage, m_clientCount);
WaitForData(workerSocket, m_clientCount);
//Resume the listening callback loop
listener.BeginAccept(Connection_handler, listener);
}
catch (ObjectDisposedException)
{
InstrumentationProvider.Instance.LogInformation("The listener socket has been closed");
}
catch (Exception ex)
{
InstrumentationProvider.Instance.LogException("Connection_handler", ex);
throw;
}
}
private void Receive_handler(IAsyncResult ar)
{
ProfileProvider.Instance.LogInformationIf(_debug);
StateObject state = (StateObject)ar.AsyncState;
try
{
// Retrieve the state object and the handler socket
// from the asynchronous state object.
Socket workSocket = state.workSocket;
// Read data from the client socket.
int bytesRead = workSocket.EndReceive(ar);
if (bytesRead > 0)
{
//InstrumentationProvider.Instance.LogInformationIf(_debug, bytesRead+" read..");
// There might be more data, so parse the data received so far.
string data= Encoding.ASCII.GetString(state.buffer, 0, bytesRead);
try
{
ParseIncomingMessage(data, workSocket);
}
catch(Exception parseEx)
{
content.Clear();
InstrumentationProvider.Instance.LogException("ParseIncomingMessage", parseEx);
}
}
WaitForData(state.workSocket, state.clientNumber);
}
catch (ObjectDisposedException)
{
InstrumentationProvider.Instance.LogInformation("Receive_handler: The listener socket has been closed");
}
catch (SocketException se)
{
//close the existing connection
CloseSockets();
//restart it again
this.Start();
}
}
private void WaitForData(Socket workerSocket, int clientNumber)
{
ProfileProvider.Instance.LogInformationIf(_debug);
try
{
StateObject theSocPkt = new StateObject(workerSocket, clientNumber);
workerSocket.ReceiveTimeout = 2000;
workerSocket.BeginReceive(theSocPkt.buffer, 0,
theSocPkt.buffer.Length,
SocketFlags.None,
Receive_handler,
theSocPkt);
}
catch(TimeoutException ex)
{
InstrumentationProvider.Instance.LogException("WaitForData - TimeOutException", ex);
}
catch (SocketException se)
{
InstrumentationProvider.Instance.LogException("MedDeviceListener.WaitForData", se);
//close the existing connection
CloseSockets();
//restart it again
this.Start();
}
catch (Exception ex)
{
InstrumentationProvider.Instance.LogException("WaitForData",ex);
//close the existing connection
CloseSockets();
//restart it again
this.Start();
}
}
private void ParseIncomingMessage(string msg,Socket wrkSocket)
{
Socket workSocket = wrkSocket;
bool hasStartTag = isMsgContainsStartTag(msg);
bool hasEndTag = isMsgContainsEndTag(msg);
int startTagIndex = indexOfStartTag(msg);
int endTagIndex = indexOfEndTag(msg);
// If the incomming message dont have either start or end tag
if (hasStartTag == false && hasEndTag == false)
{
content.Append(msg);
}
//check for the starttag first
//if message contains startTag
else if (hasStartTag)
{
if (startTagIndex != 0)//there is something before starttag
{
string subStr = msg.Substring(0, startTagIndex);
content.Append(subStr);
//Check and send the content
CheckSendMessage(workSocket);
//Parse the remaining message from start tag to end of the message
ParseIncomingMessage(msg.Substring(startTagIndex, msg.Length - subStr.Length), wrkSocket);
}
else if (startTagIndex == 0)
{
content.Clear();
if (hasEndTag)
{
int endOfEndTag = endTagIndex + lengthOfEndMsg;
string subStr = msg.Substring(0, endOfEndTag); //message statrs with start tag and ends contains full end tag so first get that string and send that.
content.Append(subStr);
CheckSendMessage(workSocket);
//Parse the remaining message from endtag+1 to end
ParseIncomingMessage(msg.Substring(endOfEndTag, msg.Length - endOfEndTag), wrkSocket);
}
else
{
content.Append(msg);
}
}
}
//if message contains EndTag ALONE
else if (hasEndTag)
{
int endOfEndTag = endTagIndex + lengthOfEndMsg;
string subStr = msg.Substring(0, endOfEndTag);
content.Append(subStr);
CheckSendMessage(workSocket);
//Parse remaining message after end tag
ParseIncomingMessage(msg.Substring(endOfEndTag, msg.Length - endOfEndTag), wrkSocket);
}
}
private void CheckSendMessage(Socket workSocket)
{
string msg=content.ToString().Trim();
//if content contains both start and end tag then send the content
if (isMsgContainsStartTag(msg) && isMsgContainsEndTag(msg) &&
indexOfStartTag(msg) == 0 && indexOfEndTag(msg) + lengthOfEndMsg == msg.Length)
{
//Send the message
using (MedDeviceListenerEventArgs e = new MedDeviceListenerEventArgs(msg))
{
OnReceiveComplete(e);
SendReceiveAck(workSocket, _receiveAckMessage);
}
}
}
private void SendReceiveAck(Socket handler, String data)
{
try
{
ProfileProvider.Instance.LogInformationIf(_debug);
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
handler.Send(byteData);
InstrumentationProvider.Instance.LogInformationIf(_debug, "Message received acknowledgement:" + _receiveAckMessage + " has been sent successfully");
}
catch (Exception ex)
{
InstrumentationProvider.Instance.LogException("SendReceiveAck", ex);
}
}
private void SendConnectedAck(string msg, int clientNumber)
{
ProfileProvider.Instance.LogInformationIf(_debug);
try
{
// Convert the reply to byte array
byte[] byData = System.Text.Encoding.ASCII.GetBytes(msg);
Socket workerSocket = (Socket)workerSocketList[clientNumber - 1];
workerSocket.Send(byData);
InstrumentationProvider.Instance.LogInformationIf(_debug, "Client Connected acknowledgement:" + _clientConnectAckMessage + " has been sent successfully");
}
catch (Exception ex)
{
InstrumentationProvider.Instance.LogException("SendConnectedAck", ex);
throw;
}
}
public void CloseSockets()
{
try
{
ProfileProvider.Instance.LogInformationIf(_debug);
if (m_mainSocket != null)
{
if (m_mainSocket.Connected)
{
m_mainSocket.Shutdown(SocketShutdown.Both);
m_mainSocket.Close();
m_mainSocket = null;
}
}
Socket workerSocket = null;
for (int i = 0; i < workerSocketList.Count; i++)
{
workerSocket = (Socket)workerSocketList[i];
if (workerSocket != null)
{
workerSocket.Shutdown(SocketShutdown.Both);
workerSocket.Close();
workerSocket = null;
}
}
}
catch(Exception ex)
{
InstrumentationProvider.Instance.LogException("CloseSockets",ex);
}
}
protected virtual void OnReceiveComplete(MedDeviceListenerEventArgs e)
{
if (MessageReceived != null)
{
MessageReceived(this, e);
}
}
private int indexOfStartTag(string msg)
{
return msg.IndexOf(header);
}
private int indexOfEndTag(string msg)
{
return msg.IndexOf(footer);
}
private bool isMsgContainsStartTag(string msg)
{
return msg.Contains(header);
}
private bool isMsgContainsEndTag(string msg)
{
return msg.Contains(footer);
}
public delegate void MessageReceiveEventHandler(object sender,MedDeviceListenerEventArgs e);
public class MedDeviceListenerEventArgs : EventArgs,IDisposable
{
private string _receivedData;
public MedDeviceListenerEventArgs(string receivedData)
{
_receivedData = receivedData;
}
public string ReceivedData
{
get
{
return _receivedData;
}
}
public void Dispose()
{ }
}
StringBuilder内容=新建StringBuilder();
公共事件MessageReceiveEventHandler MessageReceived;
//ArrayList用于跟踪设计的工作套接字
//与每个连接的客户端通信。使其成为同步的ArrayList
//为了螺纹安全
private System.Collections.ArrayList workerSocketList=
Synchronized(new System.Collections.ArrayList());
private int m_clientCount=0;
私有套接字m_mainSocket=null;
私有异步回调ReadCallback;
私有异步回调连接回调;
public MedDeviceListener(字符串ipAddress,int-port,int-maxConnections=100)
{
ProfileProvider.Instance.LogInformationIf(_debug);
这个。_port=port;
这是。_ipAddress=ipAddress;
这是.\u maxConnections=maxConnections;
ReadCallback=新的异步回调(接收\处理程序);
ConnectionCallback=新的异步回调(连接\处理程序);
lenghtofStartMsg=标题。长度;
lengthOfEndMsg=footer.Length;
}
公开作废开始()
{
ProfileProvider.Instance.LogInformationIf(_debug);
//输入数据的数据缓冲区。
字节[]字节=新字节[_bufferSize];
//为套接字建立本地端点。
IPEndPoint localEndPoint=新的IPEndPoint(IPAddress.Parse(\u IPAddress),\u port);
//创建TCP/IP套接字。
m_mainSocket=新套接字(AddressFamily.InterNetwork,
流,ProtocolType.Tcp);
//将套接字绑定到本地端点并侦听传入连接。
尝试
{
m_mainSocket.Bind(localEndPoint);
m_mainSocket.监听(100);
InstrumentationProvider.Instance.LogInformation(“MedDeviceListener已成功连接到IP:+\u ipAddress+”\n端口:+\u端口);
m_mainSocket.beginacept(ConnectionCallback,m_mainSocket);
}
捕获(例外e)
{
InstrumentationProvider.Instance.LogException(“MedDeviceListener.Start”,e);
投掷e;
}
}
专用无效连接\u处理程序(IAsyncResult ar)
{
尝试
{
ProfileProvider.Instance.LogInformationIf(_debug);
套接字侦听器=(套接字)ar.AsyncState;
套接字workerSocket=listener.EndAccept(ar);
//现在增加此客户机的客户机计数
//以线程安全的方式
联锁。增量(参考m_客户端计数);
//将workerSocket引用添加到ArrayList
workerSocketList.Add(workerSocket);
SendConnectedAck(_clientConnectAckMessage,m_clientCount);
WaitForData(workerSocket,m_clientCount);
//恢复侦听回调循环
beginacept(连接处理程序,侦听器);
}
捕获(ObjectDisposedException)
{
InstrumentationProvider.Instance.LogInformation(“侦听器套接字已关闭”);
}
捕获(例外情况除外)
{
InstrumentationProvider.Instance.LogException(“连接处理程序”,ex);
投掷;
}
}
私有无效接收处理程序(IAsyncResult ar)
{
ProfileProvider.Instance.LogInformationIf(_debug);
StateObject状态=(StateObject)ar.AsyncState;
尝试
{
//检索状态对象和处理程序套接字
//从异步状态对象。
套接字工作组=state.workSocket;
//从客户端套接字读取数据。
int bytesRead=workSocket.EndReceive(ar);
如果(字节读取>0)
{
//InstrumentationProvider.Instance.LogInformationIf(_debug,bytesRead+“read..”);
//可能会有更多的数据,因此请解析到目前为止收到的数据。
字符串数据=Encoding.ASCII.GetString(state.buffer,0,bytesRead);
尝试
{
解析输入消息(数据、工作组);
}
catch(异常parsex)
{
content.Clear();
InstrumentationProvider.Instance.LogException(“ParseIncomingMessage”,parseEx);
}
}
WaitForData(state.workSocket、state.clientNumber);
}
捕获(ObjectDisposedException)
{
InstrumentationProvider.Instance.LogInformation(“接收处理程序:侦听器套接字已关闭”);
}
捕获(SocketException se)
{
//关闭现有连接
闭合插座();
//重新启动它
这个。Start();
}
}
私有void WaitForData(套接字workerSocket,int clientNumber)
{
ProfileProvider.Instance.LogInformationIf(_debug);
尝试
{
StateObject theSocPkt=新的StateObject(workerSocket,ClientNumber)