我有一个Windows服务C#4.0套接字程序从一块硬件接收连接,然后接收消息并发回一个确认
如果我在开始接收回调中失败,我发现除非我再次调用beginaccept,否则我无法接受另一个接受回调。这是可接受的错误处理吗?
不确定我是否会耗尽资源
在我的代码中搜索BeginAccept。感谢。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Data;
using System.Threading;
namespace Company.BusinessLogic
{
public class VconnReceive : abstractReceiveClass
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private InfoSocket infoSocket;
public override void StartListening(ConnectionsManager.ConnectionConfig configReceive)
{
// Data buffer for incoming data.
try
{
// Establish the local endpoint for the socket.
// The DNS name of the computer
//IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = IPAddress.Parse(configReceive.connectionIP);//ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, Convert.ToInt32(configReceive.Port));
// Create a TCP/IP socket.
infoSocket = new InfoSocket(new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp), configReceive);
// Bind the socket to the local endpoint and listen for incoming connections.
//available for outside, specifically to close if shutdown
configReceive.AcceptSocket = infoSocket.socket;
infoSocket.socket.Bind(localEndPoint);
infoSocket.socket.Listen(1000);
// Start an asynchronous socket to listen for connections.
//Console.WriteLine("Waiting for a connection...");
infoSocket.socket.BeginAccept(new AsyncCallback(AcceptCallback), infoSocket);
}
catch (Exception e)
{
string strErrorMsg =
"\r\n--------------------------------------------\r\n" +
"\r\nError in socket startlistening ConfigReceive Connection Name\r\n" + configReceive.ConnectionName + "\r\n";
log.Error(strErrorMsg, e);
}
}
public void AcceptCallback(IAsyncResult ar)
{
InfoSocket infoSocket = null;
Socket handler = null;
log.Info("In AcceptCallback");
try
{
try
{
// Get the socket that handles the client request.
infoSocket = (InfoSocket)ar.AsyncState;
log.Info("In AcceptCallback, got socket, config connect-" + infoSocket.config.ConnectionName);
}
catch (Exception e1)
{
string strErrorMsg =
"\r\n--------------------------------------------\r\n" +
"\r\nError in socket accept callback getting socket!\r\n" +
"\r\nConnection Name not known.\r\n";
log.Error(strErrorMsg, e1);
}
// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
state.config = infoSocket.config;
IAsyncResult result = handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
log.Info("Leaving AcceptCallback, config connect-" + infoSocket.config.ConnectionName);
}
catch (Exception e)
{
try
{
string strErrorMsg =
"\r\n--------------------------------------------\r\n" +
"\r\nError2 in socket accept callback! Config Connection Name not known\r\n";
log.Error(strErrorMsg, e);
}
finally
{
try
{
//Do I call beginaccept again?
infoSocket.socket.BeginAccept(new AsyncCallback(AcceptCallback), infoSocket);
//close the socket
if (handler != null)
{
try
{
handler.Shutdown(SocketShutdown.Both);
}
catch (Exception e1)
{
log.Info(e1);
}
}
if (handler != null)
{
try
{
handler.Close();
}
catch (Exception e1)
{
log.Info(e1);
}
}
}
catch(Exception e3)
{
try
{
string strErrorMsg2 =
"\r\n--------------------------------------------\r\n" +
"\r\nError in socket accept callback calling beginaccept! Interface cannot accept connections!\r\n";
log.Error(strErrorMsg2, e3);
}
catch
{
}
}
}
}
return;
}
public void ReadCallback(IAsyncResult ar)
{
Socket handler = null;
StateObject state = null;
try
{
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
state = (StateObject)ar.AsyncState;
handler = state.workSocket;
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
//first check for header only
if ((bytesRead == 1) && state.buffer[0] == '\v')
{
if (ConnectionsManager.ConnectionConfig.StopCheck(Runnable.StopCheckCaller.Socket))
return;
state.buffer = new byte[StateObject.BufferSize];
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
return;
}
state.sb.Append(Encoding.ASCII.GetString(
state.buffer, 0, bytesRead));
//debug purposes
StringBuilder v1 = new StringBuilder();
v1.Append(Encoding.ASCII.GetString(
state.buffer, 0, bytesRead));
//Check for end of file
string vNewBufferObtained = v1.ToString();
// Check for end-of-file tag. If it is not there, read
// more data.
content = state.sb.ToString();
//We're going to split full buffer
//into individual messages
string t = String.Copy(content);
//string[] msgs = Regex.Split(t, "\u001c");//\r\u001c\r\v");
string[] msgs = t.Split('\u001c');//\r\u001c\r\v");
bool bCompleteEnd = false;
//test for partial message, have to exit to get the rest
//if (msgs[msgs.Count() - 1].Substring(msgs[msgs.Count() - 1].Length - 2, 2) == "\x1C\x0D")
//the actual check for end of transmission
if (vNewBufferObtained.Substring(vNewBufferObtained.Length - 2, 2) == "\x1C\x0D")
bCompleteEnd = true;
//process the individual messages
for (int v = 0; v < msgs.Count(); v++)
{
//if we're on the last message and it's not complete
//get the rest by breaking out of here and doing
//another receive
if ((v == (msgs.Count() - 1)) && !bCompleteEnd)
{
state.buffer = new byte[StateObject.BufferSize];
break;
}//last message check for nothing there and if so
//break out of here for another receive
else if ((msgs[v].Length == 0) || (msgs[v] == "\r"))//last record null string or cr
{
state.buffer = new byte[StateObject.BufferSize];
state.sb.Clear();
break;
}
else
{ //trim any trailing stuff
msgs[v] = msgs[v].Trim();// new Char[] { '\r', '\v' });
}
InfoSocket infoSocketSend = new InfoSocket(handler, state.config);
Send(infoSocketSend, msgs[v]);
}
state.sb.Clear();
//if we don't have a complete message put what we have in
//the buffer to concatenate the next time
if (!bCompleteEnd)
state.sb.Append(msgs[msgs.Count() - 1]);
//Set up for next receive
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
else
{
//we received zero bytes. something's wrong.
//set up to accept another connection
//and close the socket.
//Do I call beginaccept again????
infoSocket.socket.BeginAccept(new AsyncCallback(AcceptCallback),
infoSocket);
//close the socket
if (handler != null)
{
try
{
handler.Shutdown(SocketShutdown.Both);
}
catch (Exception e1)
{
log.Info(e1);
}
}
if (handler != null)
{
try
{
handler.Close();
}
catch (Exception e1)
{
log.Info(e1);
}
}
}
}
catch (Exception e)
{
try
{
try
{
log.Error("error", e);
}
catch
{
string strErrorMsg =
"inner error";
log.Error(strErrorMsg, e);
}
//Do I call beginaccept again?
infoSocket.socket.BeginAccept(new AsyncCallback(AcceptCallback),
infoSocket);
}
catch (Exception e2)
{
string strErrorMsg =
"\r\n--------------------------------------------\r\n" +
"\r\nE2 Error in socket read callback! Interface cannot accept connections!\r\n";
log.Error(strErrorMsg, e2);
}
if (handler != null)
{
try
{
handler.Shutdown(SocketShutdown.Both);
}
catch (Exception e1)
{
log.Info(e1);
}
}
if (handler != null)
{
try
{
handler.Close();
}
catch (Exception e1)
{
log.Info(e1);
}
}
}
}
private void Send(InfoSocket infoSocket, String data)
{
string sProcedure;
string[] fields = null;
try
{
string strMessage = "test";
byte[] byteData = Encoding.ASCII.GetBytes(strMessage);
// Begin sending the ack or nak data to the remote device.
infoSocket.socket.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), infoSocket);
}
catch (Exception e)
{
log.Error("Inner error", e1);
}
}
private void SendCallback(IAsyncResult ar)
{
InfoSocket infoSocket = null;
try
{
// Retrieve the socket from the state object.
infoSocket = (InfoSocket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = infoSocket.socket.EndSend(ar);
}
catch (Exception e)
{
//error handling
}
}
}
}