problem with Socket.Available

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Droopy

    problem with Socket.Available

    Hi,

    I try to implement a reusable socket class to send and receive data.
    It seems to work but I have 2 problems :

    1) I rely on Socket.Availabl e to detect that the connection is closed (no
    more data to expect). Sometimes, Socket.Availabl e returns 0 but the other
    end of the connection did not close it !

    2) This class will be used by many other classes so I have to use the
    minimum system resource. I just found that the first parameter for
    Socket.Poll is in microseconds ! I thought it was milliseconds.

    How can I improve/correct this class ?

    Thanks in advance.


    Here below, you will find the code for this class (TcpHelper).
    It is used as following :

    TcpHelper transport = new TcpHelper;
    transport.OnCon nectionFailed += new EventHandler (...);
    transport.Callb ackReceivedData += new EventHandler (...);

    transport.Open (existingSocket , caller);
    or
    transport.Open (hostname, port);

    transport.Start Reading ();


    the code :


    using System;
    using System.Net;
    using System.Net.Sock ets;
    using System.Threadin g;

    namespace IprRouting
    {
    public class TcpEventData : System.EventArg s
    {
    private byte [] _header;
    private byte [] _data;

    public TcpEventData (byte [] header, byte [] data)
    {
    _header = header;
    _data = data;
    }

    public byte [] Header
    {
    get { return _header; }
    }

    public byte [] Data
    {
    get { return _data; }
    }
    }

    public class TcpHelper
    {
    private Socket _socket = null;
    private bool _mustRun = true;
    private string _hostName = string.Empty;
    private IPAddress _ipAddress = IPAddress.IPv6N one;
    private string _caller = string.Empty;

    private const int PollTimeout = 100;

    public event EventHandler CallbackReceive dData;
    public event EventHandler OnConnectionFai led;

    private static string localHostname = string.Empty;
    private static IPAddress [] localIpAddresse s = null;

    public TcpHelper ()
    {
    }

    #region Properties

    public string HostName
    {
    get { return _hostName; }
    }

    public IPAddress IPAddress
    {
    get { return _ipAddress; }
    }

    public string RemoteEndPoint
    {
    get
    {
    if (_socket == null)
    return "Not connected";
    else
    {
    if (! _socket.Connect ed)
    return "Not connected";
    else
    return _socket.RemoteE ndPoint.ToStrin g
    ();
    }
    }
    }

    #endregion // Properties

    // remove domain part in host name (i.e. in "xxx.yyy.zz z",
    // remove ".yyy.zzz"
    private string StandardizeHost name (string hostname)
    {
    int dotIndex = hostname.IndexO f ('.');

    if (dotIndex != -1)
    {
    return hostname.Substr ing (0, dotIndex).ToUpp er ();
    }
    else
    return hostname;
    }

    public void StartReading ()
    {
    Thread handleTcp = new Thread (new ThreadStart
    (ReadTcp));

    if (_caller.Length > 0)
    {
    if (_hostName.Equa ls ("localhost" ))
    handleTcp.Name = "TcpHelper " + _caller;
    else
    handleTcp.Name = String.Format ("TcpHelper {0}
    {1}", _caller, _hostName);
    }
    else
    handleTcp.Name = String.Format ("TcpHelper {0}",
    _hostName);

    if (Log.Current.Is InfoEnabled)
    Log.Current.Inf o ("TcpHelper::St artReading " +
    handleTcp.Name) ;

    handleTcp.Prior ity = ThreadPriority. Normal;
    handleTcp.IsBac kground = true; // thread will be closed
    when application exits
    handleTcp.Start ();
    }

    private void CloseIfActive ()
    {
    if (_socket != null)
    {
    if (Log.Current.Is ErrorEnabled)
    Log.Current.Err or ("TcpHelper::Cl oseIfActive
    closing existing socket " +
    RemoteEndPoint) ;
    Close (false);
    }
    }

    public void Open (Socket socket, string caller)
    {
    IPEndPoint ipEndPoint = (IPEndPoint)
    socket.RemoteEn dPoint;
    _ipAddress = ipEndPoint.Addr ess;

    IPHostEntry hostInfo = TcpHelper.GetHo stByAddress
    (_ipAddress);
    if (hostInfo != null)
    _hostName = StandardizeHost name
    (hostInfo.HostN ame);
    else
    _hostName = _ipAddress.ToSt ring ();

    _caller = caller;

    CloseIfActive ();

    _socket = socket;
    }

    public short Open (string hostName, int port)
    {
    short returnCode = 0;

    _hostName = hostName;

    returnCode = Open (port);

    return returnCode;
    }

    private short Open (int port)
    {
    if (Log.Current.Is InfoEnabled)
    Log.Current.Inf o ("TcpHelper::Op en open " +
    _hostName);

    if (_hostName.Leng th <= 0)
    {
    if (Log.Current.Is ErrorEnabled)
    Log.Current.Err or ("TcpHelper::Op en invalid
    host name " + _hostName);
    return 4;
    }

    CloseIfActive ();

    IPHostEntry hostInfo = TcpHelper.GetHo stInfo (_hostName);

    if (hostInfo == null)
    {
    if (Log.Current.Is ErrorEnabled)
    Log.Current.Err or ("TcpHelper::Op en cannot get
    host info " + _hostName);
    return 5;
    }
    else
    {
    _hostName = StandardizeHost name
    (hostInfo.HostN ame);
    _ipAddress = hostInfo.Addres sList [0];
    }

    if (TcpHelper.IsLo calHost (hostInfo.Addre ssList))
    {
    if (Log.Current.Is InfoEnabled)
    Log.Current.Inf o ("TcpHelper::Op en skip local
    host " + _hostName);
    return 6;
    }

    if (Log.Current.Is InfoEnabled)
    Log.Current.Inf o ("TcpHelper::Op en opening " +
    _hostName +
    ", IP address " + _ipAddress + " port #" +
    port.ToString ());

    IPEndPoint endPoint = new IPEndPoint (_ipAddress, port);
    _socket = new Socket (AddressFamily. InterNetwork,
    SocketType.Stre am, ProtocolType.Tc p);
    _socket.SetSock etOption (SocketOptionLe vel.Socket,
    SocketOptionNam e.SendTimeout, TcpServer.TcpSe ndTimeout);
    _socket.SetSock etOption (SocketOptionLe vel.Socket,
    SocketOptionNam e.ReceiveTimeou t, TcpServer.TcpRe ceiveTimeout);
    _socket.SetSock etOption (SocketOptionLe vel.Socket,
    SocketOptionNam e.KeepAlive, 1);
    _socket.Connect (endPoint);

    return 0;
    }

    private static bool IsLocalHost (IPAddress [] ipAddresses)
    {
    if (localIpAddress es == null)
    {
    localHostname = Dns.GetHostName ();
    localIpAddresse s = Dns.GetHostByNa me
    (localHostname) .AddressList;
    }

    foreach (IPAddress ipaddr in ipAddresses)
    {
    foreach (IPAddress ipaddrLocal in localIpAddresse s)
    {
    if (ipaddrLocal.Eq uals (ipaddr))
    return true;
    }
    }

    return false;
    }


    private IPHostEntry GetHostByName (string hostname)
    {
    IPHostEntry hostInfo = null;

    // try
    // {
    hostInfo = Dns.GetHostByNa me (_hostName);
    /* }
    catch (Exception ex)
    {
    Util.TraceError ("Util::GetHost ByName exception
    catched " + ex);
    }
    */
    return hostInfo;
    }

    private static IPHostEntry GetHostInfo (string host)
    {
    IPHostEntry hostInfo = null;

    try
    {
    hostInfo = Dns.Resolve (host);
    }
    catch (Exception ex)
    {
    if (Log.Current.Is ErrorEnabled)
    Log.Current.Err or
    (String.Format ("TcpHelper::Ge tHostInfo
    {0} exception catched {1}",
    host, ex.ToString ()));
    }

    return hostInfo;
    }

    public static IPHostEntry GetHostByAddres s (IPAddress
    ipAddress)
    {
    IPHostEntry hostInfo = null;

    try
    {
    hostInfo = Dns.GetHostByAd dress (ipAddress);
    }
    catch (Exception ex)
    {
    if (Log.Current.Is ErrorEnabled)
    Log.Current.Err or
    ("TcpHelper::Ge tHostByAddress exception catched " + ex);
    }

    return hostInfo;
    }

    public void ReadTcp ()
    {
    if (Log.Current.Is InfoEnabled)
    Log.Current.Inf o
    (String.Format
    ("TcpHelper::Re adTcp thread started for socket
    {0}",
    RemoteEndPoint) );

    int bytesRead = 0;
    _mustRun = true;
    bool stopReading = false;

    try
    {
    byte [] header = new byte [IprProtocol.Hea derSize];

    while ((_mustRun) && (! stopReading))
    { // read header
    if (_socket.Poll (PollTimeout,
    SelectMode.Sele ctRead))
    {
    if (_socket.Availa ble == 0)
    {
    if (Log.Current.Is InfoEnabled)
    Log.Current.Inf o
    ("TcpHelper::Re adTcp header no available bytes to read, probably
    connection closed by peer");
    stopReading = true;
    break;
    }

    if (_socket.Availa ble >=
    IprProtocol.Hea derSize)
    {
    bytesRead = _socket.Receive
    (header, IprProtocol.Hea derSize, 0);

    if (Log.Current.Is InfoEnabled)
    {
    Log.Current.Inf o
    ("TcpHelper::Re adTcp header " +
    bytesRead.ToStr ing () +
    " bytes received");
    Log.Current.Inf o
    (String.Format ("header 0
    = {0} 1 = {1}",
    header [0].ToString
    ("X2"), header [1].ToString ("X2")));
    }

    if (bytesRead > 0)
    { // read command

    if (bytesRead !=
    IprProtocol.Hea derSize)
    {
    if
    (Log.Current.Is ErrorEnabled)
    Log.Current.Err or

    ("TcpHelper::Re adTcp: invalid header, " + bytesRead + " bytes
    received");
    stopReading = true;
    break ;
    }

    uint commandSize = header [1];

    if (commandSize <= 0)
    {
    if
    (Log.Current.Is ErrorEnabled)
    Log.Current.Err or
    ("TcpHelper::Re adTcp invalid header, commandSize = " + commandSize);
    stopReading = true;
    break;
    }
    else
    {
    //
    byte [] command = new byte [commandSize + 1];
    //
    command [0] = header [0]; // keep SES command
    in command buffer
    byte [] command = new
    byte [commandSize];
    bytesRead = 0;

    while ((_mustRun) && (!
    stopReading))
    {
    if (_socket.Poll
    (PollTimeout, SelectMode.Sele ctRead))
    {
    if
    (_socket.Availa ble == 0)
    {
    if
    (Log.Current.Is InfoEnabled)

    Log.Current.Inf o ("TcpHelper::Re adTcp command no available bytes to
    read, probably connection closed by peer");

    stopReading = true;
    break;
    }

    while
    ((_mustRun) && (_socket.Availa ble >= 0) && (bytesRead < commandSize))
    {
    //
    bytesRead =
    _socket.Receive (command, 1, commandSize, 0);
    bytesRead
    += _socket.Receive

    (command, bytesRead,

    (int) (commandSize - bytesRead),
    0);

    if
    (Log.Current.Is InfoEnabled)

    Log.Current.Inf o ("TcpHelper::Re adTcp command " +

    bytesRead.ToStr ing () + " bytes received");

    if
    (bytesRead == 0)
    {
    if
    (Log.Current.Is InfoEnabled)

    Log.Current.Inf o ("TcpHelper::Re adTcp command no available bytes to
    read, probably connection closed by peer");

    stopReading = true;

    break;
    }

    if
    (bytesRead < commandSize)
    {
    if
    (Log.Current.Is InfoEnabled)

    Log.Current.Inf o

    ("TcpHelper::Re adTcp: not enough bytes available, " +
    bytesRead +

    " bytes received, " + commandSize + " bytes expected");
    }
    }

    if (bytesRead
    == commandSize)
    {
    if
    (CallbackReceiv edData != null)
    {

    CallbackReceive dData (this, new TcpEventData (header, command));
    }
    else
    {
    if
    (Log.Current.Is ErrorEnabled)

    Log.Current.Err or ("TcpHelper::Re adTcp no callback registered");
    }

    break;
    }
    }
    }
    }
    }
    else
    {
    if (Log.Current.Is InfoEnabled)
    Log.Current.Inf o
    ("TcpHelper::Re adTcp header no more bytes to read, probably connection
    closed by peer");
    stopReading = true;
    }
    }
    }
    }
    }
    catch (Exception ex)
    {
    if (ex is SocketException )
    {
    /*
    if (((SocketExcept ion)
    ex).ErrorCode == (int) SocketErrorCode s.InterruptedFu nctionCall)
    Util.TraceOther
    ("TcpHelper::Re adTcp InterruptedFunc tionCall, should be a graceful
    shutdown");
    else
    {
    */
    if (Log.Current.Is ErrorEnabled)
    Log.Current.Err or ("TcpHelper::Re adTcp
    error code = " +
    ((SocketExcepti on) ex).ErrorCode);
    // }
    }
    else
    if (Log.Current.Is ErrorEnabled)
    Log.Current.Err or ("TcpHelper::Re adTcp
    Exception catched " + ex);
    }

    if (_mustRun) // not graceful shutdown (not called by
    Close () )
    {
    CloseConnection ();

    TcpInfoEventArg s tcpInfo =
    new TcpInfoEventArg s (_socket);

    if (OnConnectionFa iled != null)
    OnConnectionFai led (this, tcpInfo);
    else
    if (Log.Current.Is ErrorEnabled)
    Log.Current.Err or ("TcpHelper::Re adTcp no
    callback defined");
    }
    else
    {
    if (Log.Current.Is InfoEnabled)
    Log.Current.Inf o ("TcpHelper::Re adTcp graceful
    shutdown");
    _mustRun = true; // reset flag for new running
    }

    if (Log.Current.Is InfoEnabled)
    Log.Current.Inf o ("TcpHelper::Re adTcp handling
    finished host " + _hostName);
    }

    private void CloseConnection ()
    {
    if (Log.Current.Is InfoEnabled)
    {
    if (_hostName.Leng th > 0)
    Log.Current.Inf o
    (String.Format
    ("TcpHelper::Cl oseConnection closing
    socket {0} on host {1}",
    RemoteEndPoint, _hostName));
    else
    Log.Current.Inf o
    (String.Format
    ("TcpHelper::Cl oseConnection closing
    socket {0}",
    RemoteEndPoint) );
    }

    if (_socket != null)
    {
    if (_socket.Connec ted)
    _socket.Shutdow n (SocketShutdown .Both);
    _socket.Close ();

    _socket = null;
    }
    else
    if (Log.Current.Is ErrorEnabled)
    Log.Current.Err or ("TcpHelper::Cl oseConnection
    socket is null");
    }

    public short Close (bool keepConnected)
    {
    if (Log.Current.Is InfoEnabled)
    {
    if (_hostName.Leng th > 0)
    Log.Current.Inf o ("TcpHelper::Cl ose closing
    host " + _hostName);
    else
    Log.Current.Inf o ("TcpHelper::Cl ose closing
    host " + _socket.RemoteE ndPoint);
    }

    _mustRun = false;

    // allow reading thread to terminate
    Thread.Sleep (PollTimeout);

    // keepConnected: typically happens after OpenCanal is
    received,
    // the MainCommandHand ler closes but the IprSocket that
    has been
    // given the Tcp socket is using it => keep it opened

    if ((! keepConnected) && (_socket != null))
    CloseConnection ();

    return 0;
    }

    public int Send (byte [] data)
    {
    int bytesSent = 0;

    try
    {
    if (Log.Current.Is InfoEnabled)
    Log.Current.Inf o ("TcpHelper::Se nd sending " +
    data.Length +
    " bytes to client " + RemoteEndPoint) ;

    if ((_socket != null) && (_socket.Connec ted))
    bytesSent = _socket.Send (data);
    else
    if (Log.Current.Is ErrorEnabled)
    Log.Current.Err or ("TcpHelper::Se nd TCP socket
    not connected");

    if (bytesSent != data.Length)
    {
    if (Log.Current.Is ErrorEnabled)
    Log.Current.Err or ("TcpHelper::Se nd not
    all bytes sent, " +
    bytesSent + " != " + data.Length);
    return -1;
    }
    }
    catch (Exception ex)
    {
    if (Log.Current.Is ErrorEnabled)
    Log.Current.Err or ("TcpHelper::Se nd Exception
    catched: " + ex);
    return -1;
    }

    return bytesSent;
    }
    }
    }
  • Droopy

    #2
    Re: problem with Socket.Availabl e

    OK no help here ;-(

    I removed all calls to "Available" .
    I wonder now if I should call "Poll" ?
    I mean for better performance.
    I used both "Available" and "Poll" to prevent blocking calls to
    "Receive" but as I am using separate threads ...

    What is best ?

    Thanks in advance for your help

    Droopy <droopytoonnosp am@hotmail.com> wrote in
    news:Xns96BBA9F 069261droopytoo nnospamhotm@195 .129.110.71:
    [color=blue]
    > Hi,
    >
    > I try to implement a reusable socket class to send and receive data.
    > It seems to work but I have 2 problems :
    >
    > 1) I rely on Socket.Availabl e to detect that the connection is closed
    > (no more data to expect). Sometimes, Socket.Availabl e returns 0 but
    > the other end of the connection did not close it !
    >
    > 2) This class will be used by many other classes so I have to use the
    > minimum system resource. I just found that the first parameter for
    > Socket.Poll is in microseconds ! I thought it was milliseconds.
    >
    > How can I improve/correct this class ?
    >
    > Thanks in advance.
    >
    >
    > Here below, you will find the code for this class (TcpHelper).
    > It is used as following :
    >
    > TcpHelper transport = new TcpHelper;
    > transport.OnCon nectionFailed += new EventHandler (...);
    > transport.Callb ackReceivedData += new EventHandler (...);
    >
    > transport.Open (existingSocket , caller);
    > or
    > transport.Open (hostname, port);
    >
    > transport.Start Reading ();
    >
    >
    > the code :
    >
    >
    > using System;
    > using System.Net;
    > using System.Net.Sock ets;
    > using System.Threadin g;
    >
    > namespace IprRouting
    > {
    > public class TcpEventData : System.EventArg s
    > {
    > private byte [] _header;
    > private byte [] _data;
    >
    > public TcpEventData (byte [] header, byte [] data)
    > {
    > _header = header;
    > _data = data;
    > }
    >
    > public byte [] Header
    > {
    > get { return _header; }
    > }
    >
    > public byte [] Data
    > {
    > get { return _data; }
    > }
    > }
    >
    > public class TcpHelper
    > {
    > private Socket _socket = null;
    > private bool _mustRun = true;
    > private string _hostName = string.Empty;
    > private IPAddress _ipAddress = IPAddress.IPv6N one;
    > private string _caller = string.Empty;
    >
    > private const int PollTimeout = 100;
    >
    > public event EventHandler CallbackReceive dData;
    > public event EventHandler OnConnectionFai led;
    >
    > private static string localHostname = string.Empty;
    > private static IPAddress [] localIpAddresse s = null;
    >
    > public TcpHelper ()
    > {
    > }
    >
    > #region Properties
    >
    > public string HostName
    > {
    > get { return _hostName; }
    > }
    >
    > public IPAddress IPAddress
    > {
    > get { return _ipAddress; }
    > }
    >
    > public string RemoteEndPoint
    > {
    > get
    > {
    > if (_socket == null)
    > return "Not connected";
    > else
    > {
    > if (! _socket.Connect ed)
    > return "Not connected";
    > else
    > return _socket.RemoteE ndPoint.ToStrin g
    > ();
    > }
    > }
    > }
    >
    > #endregion // Properties
    >
    > // remove domain part in host name (i.e. in "xxx.yyy.zz z",
    > // remove ".yyy.zzz"
    > private string StandardizeHost name (string hostname)
    > {
    > int dotIndex = hostname.IndexO f ('.');
    >
    > if (dotIndex != -1)
    > {
    > return hostname.Substr ing (0, dotIndex).ToUpp er
    > ();
    > }
    > else
    > return hostname;
    > }
    >
    > public void StartReading ()
    > {
    > Thread handleTcp = new Thread (new ThreadStart
    > (ReadTcp));
    >
    > if (_caller.Length > 0)
    > {
    > if (_hostName.Equa ls ("localhost" ))
    > handleTcp.Name = "TcpHelper " + _caller;
    > else
    > handleTcp.Name = String.Format ("TcpHelper
    > {0}
    > {1}", _caller, _hostName);
    > }
    > else
    > handleTcp.Name = String.Format ("TcpHelper {0}",
    > _hostName);
    >
    > if (Log.Current.Is InfoEnabled)
    > Log.Current.Inf o ("TcpHelper::St artReading " +
    > handleTcp.Name) ;
    >
    > handleTcp.Prior ity = ThreadPriority. Normal;
    > handleTcp.IsBac kground = true; // thread will be
    > closed
    > when application exits
    > handleTcp.Start ();
    > }
    >
    > private void CloseIfActive ()
    > {
    > if (_socket != null)
    > {
    > if (Log.Current.Is ErrorEnabled)
    > Log.Current.Err or ("TcpHelper::Cl oseIfActive
    > closing existing socket " +
    > RemoteEndPoint) ;
    > Close (false);
    > }
    > }
    >
    > public void Open (Socket socket, string caller)
    > {
    > IPEndPoint ipEndPoint = (IPEndPoint)
    > socket.RemoteEn dPoint;
    > _ipAddress = ipEndPoint.Addr ess;
    >
    > IPHostEntry hostInfo = TcpHelper.GetHo stByAddress
    > (_ipAddress);
    > if (hostInfo != null)
    > _hostName = StandardizeHost name
    > (hostInfo.HostN ame);
    > else
    > _hostName = _ipAddress.ToSt ring ();
    >
    > _caller = caller;
    >
    > CloseIfActive ();
    >
    > _socket = socket;
    > }
    >
    > public short Open (string hostName, int port)
    > {
    > short returnCode = 0;
    >
    > _hostName = hostName;
    >
    > returnCode = Open (port);
    >
    > return returnCode;
    > }
    >
    > private short Open (int port)
    > {
    > if (Log.Current.Is InfoEnabled)
    > Log.Current.Inf o ("TcpHelper::Op en open " +
    > _hostName);
    >
    > if (_hostName.Leng th <= 0)
    > {
    > if (Log.Current.Is ErrorEnabled)
    > Log.Current.Err or ("TcpHelper::Op en invalid
    > host name " + _hostName);
    > return 4;
    > }
    >
    > CloseIfActive ();
    >
    > IPHostEntry hostInfo = TcpHelper.GetHo stInfo
    > (_hostName);
    >
    > if (hostInfo == null)
    > {
    > if (Log.Current.Is ErrorEnabled)
    > Log.Current.Err or ("TcpHelper::Op en cannot
    > get
    > host info " + _hostName);
    > return 5;
    > }
    > else
    > {
    > _hostName = StandardizeHost name
    > (hostInfo.HostN ame);
    > _ipAddress = hostInfo.Addres sList [0];
    > }
    >
    > if (TcpHelper.IsLo calHost (hostInfo.Addre ssList))
    > {
    > if (Log.Current.Is InfoEnabled)
    > Log.Current.Inf o ("TcpHelper::Op en skip local
    > host " + _hostName);
    > return 6;
    > }
    >
    > if (Log.Current.Is InfoEnabled)
    > Log.Current.Inf o ("TcpHelper::Op en opening " +
    > _hostName +
    > ", IP address " + _ipAddress + " port #" +
    > port.ToString ());
    >
    > IPEndPoint endPoint = new IPEndPoint (_ipAddress,
    > port); _socket = new Socket
    > (AddressFamily. InterNetwork,
    > SocketType.Stre am, ProtocolType.Tc p);
    > _socket.SetSock etOption (SocketOptionLe vel.Socket,
    > SocketOptionNam e.SendTimeout, TcpServer.TcpSe ndTimeout);
    > _socket.SetSock etOption (SocketOptionLe vel.Socket,
    > SocketOptionNam e.ReceiveTimeou t, TcpServer.TcpRe ceiveTimeout);
    > _socket.SetSock etOption (SocketOptionLe vel.Socket,
    > SocketOptionNam e.KeepAlive, 1);
    > _socket.Connect (endPoint);
    >
    > return 0;
    > }
    >
    > private static bool IsLocalHost (IPAddress [] ipAddresses)
    > {
    > if (localIpAddress es == null)
    > {
    > localHostname = Dns.GetHostName ();
    > localIpAddresse s = Dns.GetHostByNa me
    > (localHostname) .AddressList;
    > }
    >
    > foreach (IPAddress ipaddr in ipAddresses)
    > {
    > foreach (IPAddress ipaddrLocal in
    > localIpAddresse s) {
    > if (ipaddrLocal.Eq uals (ipaddr))
    > return true;
    > }
    > }
    >
    > return false;
    > }
    >
    >
    > private IPHostEntry GetHostByName (string hostname)
    > {
    > IPHostEntry hostInfo = null;
    >
    > // try
    > // {
    > hostInfo = Dns.GetHostByNa me (_hostName);
    > /* }
    > catch (Exception ex)
    > {
    > Util.TraceError ("Util::GetHost ByName exception
    > catched " + ex);
    > }
    > */
    > return hostInfo;
    > }
    >
    > private static IPHostEntry GetHostInfo (string host)
    > {
    > IPHostEntry hostInfo = null;
    >
    > try
    > {
    > hostInfo = Dns.Resolve (host);
    > }
    > catch (Exception ex)
    > {
    > if (Log.Current.Is ErrorEnabled)
    > Log.Current.Err or
    > (String.Format ("TcpHelper::Ge tHostInfo
    > {0} exception catched {1}",
    > host, ex.ToString ()));
    > }
    >
    > return hostInfo;
    > }
    >
    > public static IPHostEntry GetHostByAddres s (IPAddress
    > ipAddress)
    > {
    > IPHostEntry hostInfo = null;
    >
    > try
    > {
    > hostInfo = Dns.GetHostByAd dress (ipAddress);
    > }
    > catch (Exception ex)
    > {
    > if (Log.Current.Is ErrorEnabled)
    > Log.Current.Err or
    > ("TcpHelper::Ge tHostByAddress exception catched " + ex);
    > }
    >
    > return hostInfo;
    > }
    >
    > public void ReadTcp ()
    > {
    > if (Log.Current.Is InfoEnabled)
    > Log.Current.Inf o
    > (String.Format
    > ("TcpHelper::Re adTcp thread started for socket
    > {0}",
    > RemoteEndPoint) );
    >
    > int bytesRead = 0;
    > _mustRun = true;
    > bool stopReading = false;
    >
    > try
    > {
    > byte [] header = new byte
    > [IprProtocol.Hea derSize];
    >
    > while ((_mustRun) && (! stopReading))
    > { // read header
    > if (_socket.Poll (PollTimeout,
    > SelectMode.Sele ctRead))
    > {
    > if (_socket.Availa ble == 0)
    > {
    > if (Log.Current.Is InfoEnabled)
    > Log.Current.Inf o
    > ("TcpHelper::Re adTcp header no available bytes to read, probably
    > connection closed by peer");
    > stopReading = true;
    > break;
    > }
    >
    > if (_socket.Availa ble >=
    > IprProtocol.Hea derSize)
    > {
    > bytesRead = _socket.Receive
    > (header, IprProtocol.Hea derSize, 0);
    >
    > if (Log.Current.Is InfoEnabled)
    > {
    > Log.Current.Inf o
    > ("TcpHelper::Re adTcp header " +
    > bytesRead.ToStr ing () +
    > " bytes received");
    > Log.Current.Inf o
    > (String.Format ("header 0
    > = {0} 1 = {1}",
    > header [0].ToString
    > ("X2"), header [1].ToString ("X2")));
    > }
    >
    > if (bytesRead > 0)
    > { // read command
    >
    > if (bytesRead !=
    > IprProtocol.Hea derSize)
    > {
    > if
    > (Log.Current.Is ErrorEnabled)
    > Log.Current.Err or
    >
    > ("TcpHelper::Re adTcp: invalid header, " + bytesRead + " bytes
    > received");
    > stopReading = true;
    > break ;
    > }
    >
    > uint commandSize = header [1];
    >
    > if (commandSize <= 0)
    > {
    > if
    > (Log.Current.Is ErrorEnabled)
    > Log.Current.Err or
    > ("TcpHelper::Re adTcp invalid header, commandSize = " + commandSize);
    > stopReading = true;
    > break;
    > }
    > else
    > {
    > //
    > byte [] command = new byte [commandSize + 1];
    > //
    > command [0] = header [0]; // keep SES
    > command
    > in command buffer
    > byte [] command = new
    > byte [commandSize];
    > bytesRead = 0;
    >
    > while ((_mustRun) && (!
    > stopReading))
    > {
    > if (_socket.Poll
    > (PollTimeout, SelectMode.Sele ctRead))
    > {
    > if
    > (_socket.Availa ble == 0)
    > {
    > if
    > (Log.Current.Is InfoEnabled)
    >
    > Log.Current.Inf o ("TcpHelper::Re adTcp command no available bytes
    > to
    > read, probably connection closed by peer");
    >
    > stopReading = true;
    > break;
    > }
    >
    > while
    > ((_mustRun) && (_socket.Availa ble >= 0) && (bytesRead < commandSize))
    > {
    > //
    > bytesRead =
    > _socket.Receive (command, 1, commandSize, 0);
    > bytesRead
    > += _socket.Receive
    >
    > (command, bytesRead,
    >
    > (int) (commandSize - bytesRead),
    > 0);
    >
    > if
    > (Log.Current.Is InfoEnabled)
    >
    > Log.Current.Inf o ("TcpHelper::Re adTcp command " +
    >
    > bytesRead.ToStr ing () + " bytes received");
    >
    > if
    > (bytesRead == 0)
    > {
    > if
    > (Log.Current.Is InfoEnabled)
    >
    > Log.Current.Inf o ("TcpHelper::Re adTcp command no available bytes
    > to
    > read, probably connection closed by peer");
    >
    > stopReading = true;
    >
    > break;
    > }
    >
    > if
    > (bytesRead < commandSize)
    > {
    > if
    > (Log.Current.Is InfoEnabled)
    >
    > Log.Current.Inf o
    >
    > ("TcpHelper::Re adTcp: not enough bytes available, " +
    > bytesRead +
    >
    > " bytes received, " + commandSize + " bytes expected");
    > }
    > }
    >
    > if (bytesRead
    > == commandSize)
    > {
    > if
    > (CallbackReceiv edData != null)
    > {
    >
    > CallbackReceive dData (this, new TcpEventData (header, command));
    > }
    > else
    > {
    > if
    > (Log.Current.Is ErrorEnabled)
    >
    > Log.Current.Err or ("TcpHelper::Re adTcp no callback registered");
    > }
    >
    > break;
    > }
    > }
    > }
    > }
    > }
    > else
    > {
    > if (Log.Current.Is InfoEnabled)
    > Log.Current.Inf o
    > ("TcpHelper::Re adTcp header no more bytes to read, probably connection
    > closed by peer");
    > stopReading = true;
    > }
    > }
    > }
    > }
    > }
    > catch (Exception ex)
    > {
    > if (ex is SocketException )
    > {
    > /*
    > if (((SocketExcept ion)
    > ex).ErrorCode == (int) SocketErrorCode s.InterruptedFu nctionCall)
    > Util.TraceOther
    > ("TcpHelper::Re adTcp InterruptedFunc tionCall, should be a graceful
    > shutdown");
    > else
    > {
    > */
    > if (Log.Current.Is ErrorEnabled)
    > Log.Current.Err or ("TcpHelper::Re adTcp
    > error code = " +
    > ((SocketExcepti on) ex).ErrorCode);
    > // }
    > }
    > else
    > if (Log.Current.Is ErrorEnabled)
    > Log.Current.Err or ("TcpHelper::Re adTcp
    > Exception catched " + ex);
    > }
    >
    > if (_mustRun) // not graceful shutdown (not called
    > by
    > Close () )
    > {
    > CloseConnection ();
    >
    > TcpInfoEventArg s tcpInfo =
    > new TcpInfoEventArg s (_socket);
    >
    > if (OnConnectionFa iled != null)
    > OnConnectionFai led (this, tcpInfo);
    > else
    > if (Log.Current.Is ErrorEnabled)
    > Log.Current.Err or ("TcpHelper::Re adTcp no
    > callback defined");
    > }
    > else
    > {
    > if (Log.Current.Is InfoEnabled)
    > Log.Current.Inf o ("TcpHelper::Re adTcp
    > graceful
    > shutdown");
    > _mustRun = true; // reset flag for new running
    > }
    >
    > if (Log.Current.Is InfoEnabled)
    > Log.Current.Inf o ("TcpHelper::Re adTcp handling
    > finished host " + _hostName);
    > }
    >
    > private void CloseConnection ()
    > {
    > if (Log.Current.Is InfoEnabled)
    > {
    > if (_hostName.Leng th > 0)
    > Log.Current.Inf o
    > (String.Format
    > ("TcpHelper::Cl oseConnection closing
    > socket {0} on host {1}",
    > RemoteEndPoint, _hostName));
    > else
    > Log.Current.Inf o
    > (String.Format
    > ("TcpHelper::Cl oseConnection closing
    > socket {0}",
    > RemoteEndPoint) );
    > }
    >
    > if (_socket != null)
    > {
    > if (_socket.Connec ted)
    > _socket.Shutdow n (SocketShutdown .Both);
    > _socket.Close ();
    >
    > _socket = null;
    > }
    > else
    > if (Log.Current.Is ErrorEnabled)
    > Log.Current.Err or ("TcpHelper::Cl oseConnection
    > socket is null");
    > }
    >
    > public short Close (bool keepConnected)
    > {
    > if (Log.Current.Is InfoEnabled)
    > {
    > if (_hostName.Leng th > 0)
    > Log.Current.Inf o ("TcpHelper::Cl ose closing
    > host " + _hostName);
    > else
    > Log.Current.Inf o ("TcpHelper::Cl ose closing
    > host " + _socket.RemoteE ndPoint);
    > }
    >
    > _mustRun = false;
    >
    > // allow reading thread to terminate
    > Thread.Sleep (PollTimeout);
    >
    > // keepConnected: typically happens after OpenCanal is
    > received,
    > // the MainCommandHand ler closes but the IprSocket that
    > has been
    > // given the Tcp socket is using it => keep it opened
    >
    > if ((! keepConnected) && (_socket != null))
    > CloseConnection ();
    >
    > return 0;
    > }
    >
    > public int Send (byte [] data)
    > {
    > int bytesSent = 0;
    >
    > try
    > {
    > if (Log.Current.Is InfoEnabled)
    > Log.Current.Inf o ("TcpHelper::Se nd sending "
    > +
    > data.Length +
    > " bytes to client " + RemoteEndPoint) ;
    >
    > if ((_socket != null) && (_socket.Connec ted))
    > bytesSent = _socket.Send (data);
    > else
    > if (Log.Current.Is ErrorEnabled)
    > Log.Current.Err or ("TcpHelper::Se nd TCP
    > socket
    > not connected");
    >
    > if (bytesSent != data.Length)
    > {
    > if (Log.Current.Is ErrorEnabled)
    > Log.Current.Err or ("TcpHelper::Se nd not
    > all bytes sent, " +
    > bytesSent + " != " + data.Length);
    > return -1;
    > }
    > }
    > catch (Exception ex)
    > {
    > if (Log.Current.Is ErrorEnabled)
    > Log.Current.Err or ("TcpHelper::Se nd Exception
    > catched: " + ex);
    > return -1;
    > }
    >
    > return bytesSent;
    > }
    > }
    > }
    >[/color]

    Comment

    • Droopy

      #3
      Re: problem with Socket.Availabl e

      Droopy <droopytoonnosp am@hotmail.com> wrote in
      news:Xns96BCB21 CFAA95droopytoo nnospamhotm@195 .129.110.71:
      [color=blue]
      > OK no help here ;-(
      >
      > I removed all calls to "Available" .
      > I wonder now if I should call "Poll" ?
      > I mean for better performance.[/color]

      I forgot to mention that I am sending a lot (about 50/sec) of short
      (average 16 bytes, up to 256 bytes) messages.

      Who can help me ?
      [color=blue]
      > I used both "Available" and "Poll" to prevent blocking calls to
      > "Receive" but as I am using separate threads ...
      >
      > What is best ?
      >
      > Thanks in advance for your help
      >
      > Droopy <droopytoonnosp am@hotmail.com> wrote in
      > news:Xns96BBA9F 069261droopytoo nnospamhotm@195 .129.110.71:
      >[color=green]
      >> Hi,
      >>
      >> I try to implement a reusable socket class to send and receive data.
      >> It seems to work but I have 2 problems :
      >>
      >> 1) I rely on Socket.Availabl e to detect that the connection is closed
      >> (no more data to expect). Sometimes, Socket.Availabl e returns 0 but
      >> the other end of the connection did not close it !
      >>
      >> 2) This class will be used by many other classes so I have to use the
      >> minimum system resource. I just found that the first parameter for
      >> Socket.Poll is in microseconds ! I thought it was milliseconds.
      >>
      >> How can I improve/correct this class ?
      >>
      >> Thanks in advance.
      >>
      >>
      >> Here below, you will find the code for this class (TcpHelper).
      >> It is used as following :
      >>
      >> TcpHelper transport = new TcpHelper;
      >> transport.OnCon nectionFailed += new EventHandler (...);
      >> transport.Callb ackReceivedData += new EventHandler (...);
      >>
      >> transport.Open (existingSocket , caller);
      >> or
      >> transport.Open (hostname, port);
      >>
      >> transport.Start Reading ();
      >>
      >>
      >> the code :
      >>
      >>
      >> using System;
      >> using System.Net;
      >> using System.Net.Sock ets;
      >> using System.Threadin g;
      >>
      >> namespace IprRouting
      >> {
      >> public class TcpEventData : System.EventArg s
      >> {
      >> private byte [] _header;
      >> private byte [] _data;
      >>
      >> public TcpEventData (byte [] header, byte [] data)
      >> {
      >> _header = header;
      >> _data = data;
      >> }
      >>
      >> public byte [] Header
      >> {
      >> get { return _header; }
      >> }
      >>
      >> public byte [] Data
      >> {
      >> get { return _data; }
      >> }
      >> }
      >>
      >> public class TcpHelper
      >> {
      >> private Socket _socket = null;
      >> private bool _mustRun = true;
      >> private string _hostName = string.Empty;
      >> private IPAddress _ipAddress = IPAddress.IPv6N one;
      >> private string _caller = string.Empty;
      >>
      >> private const int PollTimeout = 100;
      >>
      >> public event EventHandler CallbackReceive dData;
      >> public event EventHandler OnConnectionFai led;
      >>
      >> private static string localHostname = string.Empty;
      >> private static IPAddress [] localIpAddresse s = null;
      >>
      >> public TcpHelper ()
      >> {
      >> }
      >>
      >> #region Properties
      >>
      >> public string HostName
      >> {
      >> get { return _hostName; }
      >> }
      >>
      >> public IPAddress IPAddress
      >> {
      >> get { return _ipAddress; }
      >> }
      >>
      >> public string RemoteEndPoint
      >> {
      >> get
      >> {
      >> if (_socket == null)
      >> return "Not connected";
      >> else
      >> {
      >> if (! _socket.Connect ed)
      >> return "Not connected";
      >> else
      >> return _socket.RemoteE ndPoint.ToStrin g
      >> ();
      >> }
      >> }
      >> }
      >>
      >> #endregion // Properties
      >>
      >> // remove domain part in host name (i.e. in "xxx.yyy.zz z",
      >> // remove ".yyy.zzz"
      >> private string StandardizeHost name (string hostname)
      >> {
      >> int dotIndex = hostname.IndexO f ('.');
      >>
      >> if (dotIndex != -1)
      >> {
      >> return hostname.Substr ing (0, dotIndex).ToUpp er
      >> ();
      >> }
      >> else
      >> return hostname;
      >> }
      >>
      >> public void StartReading ()
      >> {
      >> Thread handleTcp = new Thread (new ThreadStart
      >> (ReadTcp));
      >>
      >> if (_caller.Length > 0)
      >> {
      >> if (_hostName.Equa ls ("localhost" ))
      >> handleTcp.Name = "TcpHelper " + _caller;
      >> else
      >> handleTcp.Name = String.Format ("TcpHelper
      >> {0}
      >> {1}", _caller, _hostName);
      >> }
      >> else
      >> handleTcp.Name = String.Format ("TcpHelper {0}",
      >> _hostName);
      >>
      >> if (Log.Current.Is InfoEnabled)
      >> Log.Current.Inf o ("TcpHelper::St artReading " +
      >> handleTcp.Name) ;
      >>
      >> handleTcp.Prior ity = ThreadPriority. Normal;
      >> handleTcp.IsBac kground = true; // thread will be
      >> closed
      >> when application exits
      >> handleTcp.Start ();
      >> }
      >>
      >> private void CloseIfActive ()
      >> {
      >> if (_socket != null)
      >> {
      >> if (Log.Current.Is ErrorEnabled)
      >> Log.Current.Err or ("TcpHelper::Cl oseIfActive
      >> closing existing socket " +
      >> RemoteEndPoint) ;
      >> Close (false);
      >> }
      >> }
      >>
      >> public void Open (Socket socket, string caller)
      >> {
      >> IPEndPoint ipEndPoint = (IPEndPoint)
      >> socket.RemoteEn dPoint;
      >> _ipAddress = ipEndPoint.Addr ess;
      >>
      >> IPHostEntry hostInfo = TcpHelper.GetHo stByAddress
      >> (_ipAddress);
      >> if (hostInfo != null)
      >> _hostName = StandardizeHost name
      >> (hostInfo.HostN ame);
      >> else
      >> _hostName = _ipAddress.ToSt ring ();
      >>
      >> _caller = caller;
      >>
      >> CloseIfActive ();
      >>
      >> _socket = socket;
      >> }
      >>
      >> public short Open (string hostName, int port)
      >> {
      >> short returnCode = 0;
      >>
      >> _hostName = hostName;
      >>
      >> returnCode = Open (port);
      >>
      >> return returnCode;
      >> }
      >>
      >> private short Open (int port)
      >> {
      >> if (Log.Current.Is InfoEnabled)
      >> Log.Current.Inf o ("TcpHelper::Op en open " +
      >> _hostName);
      >>
      >> if (_hostName.Leng th <= 0)
      >> {
      >> if (Log.Current.Is ErrorEnabled)
      >> Log.Current.Err or ("TcpHelper::Op en invalid
      >> host name " + _hostName);
      >> return 4;
      >> }
      >>
      >> CloseIfActive ();
      >>
      >> IPHostEntry hostInfo = TcpHelper.GetHo stInfo
      >> (_hostName);
      >>
      >> if (hostInfo == null)
      >> {
      >> if (Log.Current.Is ErrorEnabled)
      >> Log.Current.Err or ("TcpHelper::Op en cannot
      >> get
      >> host info " + _hostName);
      >> return 5;
      >> }
      >> else
      >> {
      >> _hostName = StandardizeHost name
      >> (hostInfo.HostN ame);
      >> _ipAddress = hostInfo.Addres sList [0];
      >> }
      >>
      >> if (TcpHelper.IsLo calHost (hostInfo.Addre ssList))
      >> {
      >> if (Log.Current.Is InfoEnabled)
      >> Log.Current.Inf o ("TcpHelper::Op en skip local
      >> host " + _hostName);
      >> return 6;
      >> }
      >>
      >> if (Log.Current.Is InfoEnabled)
      >> Log.Current.Inf o ("TcpHelper::Op en opening " +
      >> _hostName +
      >> ", IP address " + _ipAddress + " port #" +
      >> port.ToString ());
      >>
      >> IPEndPoint endPoint = new IPEndPoint (_ipAddress,
      >> port); _socket = new Socket
      >> (AddressFamily. InterNetwork,
      >> SocketType.Stre am, ProtocolType.Tc p);
      >> _socket.SetSock etOption (SocketOptionLe vel.Socket,
      >> SocketOptionNam e.SendTimeout, TcpServer.TcpSe ndTimeout);
      >> _socket.SetSock etOption (SocketOptionLe vel.Socket,
      >> SocketOptionNam e.ReceiveTimeou t, TcpServer.TcpRe ceiveTimeout);
      >> _socket.SetSock etOption (SocketOptionLe vel.Socket,
      >> SocketOptionNam e.KeepAlive, 1);
      >> _socket.Connect (endPoint);
      >>
      >> return 0;
      >> }
      >>
      >> private static bool IsLocalHost (IPAddress [] ipAddresses)
      >> {
      >> if (localIpAddress es == null)
      >> {
      >> localHostname = Dns.GetHostName ();
      >> localIpAddresse s = Dns.GetHostByNa me
      >> (localHostname) .AddressList;
      >> }
      >>
      >> foreach (IPAddress ipaddr in ipAddresses)
      >> {
      >> foreach (IPAddress ipaddrLocal in
      >> localIpAddresse s) {
      >> if (ipaddrLocal.Eq uals (ipaddr))
      >> return true;
      >> }
      >> }
      >>
      >> return false;
      >> }
      >>
      >>
      >> private IPHostEntry GetHostByName (string hostname)
      >> {
      >> IPHostEntry hostInfo = null;
      >>
      >> // try
      >> // {
      >> hostInfo = Dns.GetHostByNa me (_hostName);
      >> /* }
      >> catch (Exception ex)
      >> {
      >> Util.TraceError ("Util::GetHost ByName exception
      >> catched " + ex);
      >> }
      >> */
      >> return hostInfo;
      >> }
      >>
      >> private static IPHostEntry GetHostInfo (string host)
      >> {
      >> IPHostEntry hostInfo = null;
      >>
      >> try
      >> {
      >> hostInfo = Dns.Resolve (host);
      >> }
      >> catch (Exception ex)
      >> {
      >> if (Log.Current.Is ErrorEnabled)
      >> Log.Current.Err or
      >> (String.Format ("TcpHelper::Ge tHostInfo
      >> {0} exception catched {1}",
      >> host, ex.ToString ()));
      >> }
      >>
      >> return hostInfo;
      >> }
      >>
      >> public static IPHostEntry GetHostByAddres s (IPAddress
      >> ipAddress)
      >> {
      >> IPHostEntry hostInfo = null;
      >>
      >> try
      >> {
      >> hostInfo = Dns.GetHostByAd dress (ipAddress);
      >> }
      >> catch (Exception ex)
      >> {
      >> if (Log.Current.Is ErrorEnabled)
      >> Log.Current.Err or
      >> ("TcpHelper::Ge tHostByAddress exception catched " + ex);
      >> }
      >>
      >> return hostInfo;
      >> }
      >>
      >> public void ReadTcp ()
      >> {
      >> if (Log.Current.Is InfoEnabled)
      >> Log.Current.Inf o
      >> (String.Format
      >> ("TcpHelper::Re adTcp thread started for socket
      >> {0}",
      >> RemoteEndPoint) );
      >>
      >> int bytesRead = 0;
      >> _mustRun = true;
      >> bool stopReading = false;
      >>
      >> try
      >> {
      >> byte [] header = new byte
      >> [IprProtocol.Hea derSize];
      >>
      >> while ((_mustRun) && (! stopReading))
      >> { // read header
      >> if (_socket.Poll (PollTimeout,
      >> SelectMode.Sele ctRead))
      >> {
      >> if (_socket.Availa ble == 0)
      >> {
      >> if (Log.Current.Is InfoEnabled)
      >> Log.Current.Inf o
      >> ("TcpHelper::Re adTcp header no available bytes to read, probably
      >> connection closed by peer");
      >> stopReading = true;
      >> break;
      >> }
      >>
      >> if (_socket.Availa ble >=
      >> IprProtocol.Hea derSize)
      >> {
      >> bytesRead = _socket.Receive
      >> (header, IprProtocol.Hea derSize, 0);
      >>
      >> if (Log.Current.Is InfoEnabled)
      >> {
      >> Log.Current.Inf o
      >> ("TcpHelper::Re adTcp header " +
      >> bytesRead.ToStr ing () +
      >> " bytes received");
      >> Log.Current.Inf o
      >> (String.Format ("header 0
      >> = {0} 1 = {1}",
      >> header [0].ToString
      >> ("X2"), header [1].ToString ("X2")));
      >> }
      >>
      >> if (bytesRead > 0)
      >> { // read command
      >>
      >> if (bytesRead !=
      >> IprProtocol.Hea derSize)
      >> {
      >> if
      >> (Log.Current.Is ErrorEnabled)
      >> Log.Current.Err or
      >>
      >> ("TcpHelper::Re adTcp: invalid header, " + bytesRead + " bytes
      >> received");
      >> stopReading = true;
      >> break ;
      >> }
      >>
      >> uint commandSize = header [1];
      >>
      >> if (commandSize <= 0)
      >> {
      >> if
      >> (Log.Current.Is ErrorEnabled)
      >> Log.Current.Err or
      >> ("TcpHelper::Re adTcp invalid header, commandSize = " + commandSize);
      >> stopReading = true;
      >> break;
      >> }
      >> else
      >> {
      >> //
      >> byte [] command = new byte [commandSize + 1];
      >> //
      >> command [0] = header [0]; // keep SES
      >> command
      >> in command buffer
      >> byte [] command = new
      >> byte [commandSize];
      >> bytesRead = 0;
      >>
      >> while ((_mustRun) && (!
      >> stopReading))
      >> {
      >> if (_socket.Poll
      >> (PollTimeout, SelectMode.Sele ctRead))
      >> {
      >> if
      >> (_socket.Availa ble == 0)
      >> {
      >> if
      >> (Log.Current.Is InfoEnabled)
      >>
      >> Log.Current.Inf o ("TcpHelper::Re adTcp command no available bytes
      >> to
      >> read, probably connection closed by peer");
      >>
      >> stopReading = true;
      >> break;
      >> }
      >>
      >> while
      >> ((_mustRun) && (_socket.Availa ble >= 0) && (bytesRead < commandSize))
      >> {
      >> //
      >> bytesRead =
      >> _socket.Receive (command, 1, commandSize, 0);
      >> bytesRead
      >> += _socket.Receive
      >>
      >> (command, bytesRead,
      >>
      >> (int) (commandSize - bytesRead),
      >> 0);
      >>
      >> if
      >> (Log.Current.Is InfoEnabled)
      >>
      >> Log.Current.Inf o ("TcpHelper::Re adTcp command " +
      >>
      >> bytesRead.ToStr ing () + " bytes received");
      >>
      >> if
      >> (bytesRead == 0)
      >> {
      >> if
      >> (Log.Current.Is InfoEnabled)
      >>
      >> Log.Current.Inf o ("TcpHelper::Re adTcp command no available bytes
      >> to
      >> read, probably connection closed by peer");
      >>
      >> stopReading = true;
      >>
      >> break;
      >> }
      >>
      >> if
      >> (bytesRead < commandSize)
      >> {
      >> if
      >> (Log.Current.Is InfoEnabled)
      >>
      >> Log.Current.Inf o
      >>
      >> ("TcpHelper::Re adTcp: not enough bytes available, " +
      >> bytesRead +
      >>
      >> " bytes received, " + commandSize + " bytes expected");
      >> }
      >> }
      >>
      >> if (bytesRead
      >> == commandSize)
      >> {
      >> if
      >> (CallbackReceiv edData != null)
      >> {
      >>
      >> CallbackReceive dData (this, new TcpEventData (header, command));
      >> }
      >> else
      >> {
      >> if
      >> (Log.Current.Is ErrorEnabled)
      >>
      >> Log.Current.Err or ("TcpHelper::Re adTcp no callback registered");
      >> }
      >>
      >> break;
      >> }
      >> }
      >> }
      >> }
      >> }
      >> else
      >> {
      >> if (Log.Current.Is InfoEnabled)
      >> Log.Current.Inf o
      >> ("TcpHelper::Re adTcp header no more bytes to read, probably connection
      >> closed by peer");
      >> stopReading = true;
      >> }
      >> }
      >> }
      >> }
      >> }
      >> catch (Exception ex)
      >> {
      >> if (ex is SocketException )
      >> {
      >> /*
      >> if (((SocketExcept ion)
      >> ex).ErrorCode == (int) SocketErrorCode s.InterruptedFu nctionCall)
      >> Util.TraceOther
      >> ("TcpHelper::Re adTcp InterruptedFunc tionCall, should be a graceful
      >> shutdown");
      >> else
      >> {
      >> */
      >> if (Log.Current.Is ErrorEnabled)
      >> Log.Current.Err or ("TcpHelper::Re adTcp
      >> error code = " +
      >> ((SocketExcepti on) ex).ErrorCode);
      >> // }
      >> }
      >> else
      >> if (Log.Current.Is ErrorEnabled)
      >> Log.Current.Err or ("TcpHelper::Re adTcp
      >> Exception catched " + ex);
      >> }
      >>
      >> if (_mustRun) // not graceful shutdown (not called
      >> by
      >> Close () )
      >> {
      >> CloseConnection ();
      >>
      >> TcpInfoEventArg s tcpInfo =
      >> new TcpInfoEventArg s (_socket);
      >>
      >> if (OnConnectionFa iled != null)
      >> OnConnectionFai led (this, tcpInfo);
      >> else
      >> if (Log.Current.Is ErrorEnabled)
      >> Log.Current.Err or ("TcpHelper::Re adTcp no
      >> callback defined");
      >> }
      >> else
      >> {
      >> if (Log.Current.Is InfoEnabled)
      >> Log.Current.Inf o ("TcpHelper::Re adTcp
      >> graceful
      >> shutdown");
      >> _mustRun = true; // reset flag for new running
      >> }
      >>
      >> if (Log.Current.Is InfoEnabled)
      >> Log.Current.Inf o ("TcpHelper::Re adTcp handling
      >> finished host " + _hostName);
      >> }
      >>
      >> private void CloseConnection ()
      >> {
      >> if (Log.Current.Is InfoEnabled)
      >> {
      >> if (_hostName.Leng th > 0)
      >> Log.Current.Inf o
      >> (String.Format
      >> ("TcpHelper::Cl oseConnection closing
      >> socket {0} on host {1}",
      >> RemoteEndPoint, _hostName));
      >> else
      >> Log.Current.Inf o
      >> (String.Format
      >> ("TcpHelper::Cl oseConnection closing
      >> socket {0}",
      >> RemoteEndPoint) );
      >> }
      >>
      >> if (_socket != null)
      >> {
      >> if (_socket.Connec ted)
      >> _socket.Shutdow n (SocketShutdown .Both);
      >> _socket.Close ();
      >>
      >> _socket = null;
      >> }
      >> else
      >> if (Log.Current.Is ErrorEnabled)
      >> Log.Current.Err or ("TcpHelper::Cl oseConnection
      >> socket is null");
      >> }
      >>
      >> public short Close (bool keepConnected)
      >> {
      >> if (Log.Current.Is InfoEnabled)
      >> {
      >> if (_hostName.Leng th > 0)
      >> Log.Current.Inf o ("TcpHelper::Cl ose closing
      >> host " + _hostName);
      >> else
      >> Log.Current.Inf o ("TcpHelper::Cl ose closing
      >> host " + _socket.RemoteE ndPoint);
      >> }
      >>
      >> _mustRun = false;
      >>
      >> // allow reading thread to terminate
      >> Thread.Sleep (PollTimeout);
      >>
      >> // keepConnected: typically happens after OpenCanal is
      >> received,
      >> // the MainCommandHand ler closes but the IprSocket that
      >> has been
      >> // given the Tcp socket is using it => keep it opened
      >>
      >> if ((! keepConnected) && (_socket != null))
      >> CloseConnection ();
      >>
      >> return 0;
      >> }
      >>
      >> public int Send (byte [] data)
      >> {
      >> int bytesSent = 0;
      >>
      >> try
      >> {
      >> if (Log.Current.Is InfoEnabled)
      >> Log.Current.Inf o ("TcpHelper::Se nd sending "
      >> +
      >> data.Length +
      >> " bytes to client " + RemoteEndPoint) ;
      >>
      >> if ((_socket != null) && (_socket.Connec ted))
      >> bytesSent = _socket.Send (data);
      >> else
      >> if (Log.Current.Is ErrorEnabled)
      >> Log.Current.Err or ("TcpHelper::Se nd TCP
      >> socket
      >> not connected");
      >>
      >> if (bytesSent != data.Length)
      >> {
      >> if (Log.Current.Is ErrorEnabled)
      >> Log.Current.Err or ("TcpHelper::Se nd not
      >> all bytes sent, " +
      >> bytesSent + " != " + data.Length);
      >> return -1;
      >> }
      >> }
      >> catch (Exception ex)
      >> {
      >> if (Log.Current.Is ErrorEnabled)
      >> Log.Current.Err or ("TcpHelper::Se nd Exception
      >> catched: " + ex);
      >> return -1;
      >> }
      >>
      >> return bytesSent;
      >> }
      >> }
      >> }
      >>[/color]
      >
      >[/color]

      Comment

      Working...