Click here to Skip to main content
15,917,329 members
Home / Discussions / Design and Architecture
   

Design and Architecture

 
GeneralRe: Wrong forum Pin
Pathetic Logic2-Apr-08 22:05
Pathetic Logic2-Apr-08 22:05 
GeneralRe: Wrong forum Pin
Pete O'Hanlon6-Apr-08 9:02
mvePete O'Hanlon6-Apr-08 9:02 
JokeRe: Wrong forum Pin
Leslie Sanford7-Apr-08 18:17
Leslie Sanford7-Apr-08 18:17 
QuestionNot sure if this makes sense, but.... what 'kind' of systems are there? Pin
SimonH7629-Mar-08 15:58
SimonH7629-Mar-08 15:58 
GeneralRe: Not sure if this makes sense, but.... what 'kind' of systems are there? Pin
led mike31-Mar-08 4:57
led mike31-Mar-08 4:57 
GeneralRe: Not sure if this makes sense, but.... what 'kind' of systems are there? Pin
SimonH761-Apr-08 4:31
SimonH761-Apr-08 4:31 
GeneralRe: Not sure if this makes sense, but.... what 'kind' of systems are there? Pin
led mike1-Apr-08 5:52
led mike1-Apr-08 5:52 
GeneralNetwork Communication Library Pin
Ri Qen-Sin29-Mar-08 13:26
Ri Qen-Sin29-Mar-08 13:26 

I'm designing a class library to facilitate communications over TCP/IP. It has ease of use in mind and is event-oriented. Despite the departure from the base class library's way of exposing the networking functionality (synchronous and asynchronous methods), the class library I’m writing is based on a couple of classes from the base class library—the TcpListener and TcpClient classes in particular. It doesn't derive from it, but the API is very similar:



public class CorruptDataException : ApplicationException
  • public CorruptDataException()
  • public CorruptDataException(string message);
  • public CorruptDataException(string message, Exception innerException)
  • protected CorruptDataException(SerializationInfo info, StreamingContext context)

public sealed class ConnectCompletedEventArgs : EventArgs
  • internal ConnectCompletedEventArgs(object userToken)
  • public object UserState { get; }

public sealed class DisconnectedEventArgs : EventArgs
  • internal DisconnectedEventArgs(DisconnectReason reason, object userToken)
  • public DisconnectReason Reason { get; }
  • public object UserState { get; }

public enum DisconnectReason : int
  • DisconnectCall = 1
  • None = 0
  • RemoteDeviceDisconnected = -1

public sealed class ReceiveCompletedEventArgs : EventArgs
  • internal ReceiveCompletedEventArgs(Exception ex, IList<byte[]> data, object userToken)
  • public IList<byte[]> Data { get; }
  • public Exception Error { get; }
  • public object UserState { get; }

public sealed class SendCompletedEventArgs : EventArgs
  • internal SendCompletedEventArgs(Exception ex, object userToken)
  • public Exception Error { get; }
  • public object UserState { get; }

public sealed class SlipClient : IDisposable
  • public SlipClient()
  • public void Connect(EndPoint remoteEP)
  • public void Connect(IPAddress[] addresses, int port)
  • public void Connect(IPAddress address, int port)
  • public void Connect(string host, int port)
  • public void ConnectAsync(EndPoint remoteEP, object userToken)
  • public void ConnectAsync(IPAddress[] addresses, int port, object userToken)
  • public void ConnectAsync(IPAddress address, int port, object userToken)
  • public void ConnectAsync(string host, int port, object userToken)
  • public void Disconnect()
  • public void DisconnectAsync(object userToken)
  • public override void Dispose()
  • public IList<byte[]> Receive()
  • public void ReceiveAsync(object userToken)
  • public void Send(IList<byte[]> data)
  • public void SendAsync(IList<byte[]> data, object userToken)
  • public event EventHandler<ConnectCompletedEventArgs> ConnectCompleted
  • public event EventHandler<DisconnectedEventArgs> Disconnected
  • public event EventHandler<ReceiveCompletedEventArgs> ReceiveCompleted
  • public event EventHandler<SendCompletedEventArgs> SendCompleted
  • public bool Connected { get; }
  • public EndPoint LocalEndPoint { get; }
  • public bool NoDelay { get; set; }
  • public int ReceiveTimeout { get; set; }
  • public EndPoint RemoteEndPoint { get; }
  • public int SendTimeout { get; set; }


public sealed class SlipClientAcceptedEventArgs : EventArgs
  • internal SlipClientAcceptedEventArgs()
  • public SlipClient Client { get; }
  • public Exception Error { get; }
  • public object UserState { get; }


public sealed class SlipListener
  • public SlipListener(IPEndPoint localEP)
  • public SlipListener(IPAddress localaddr, int port)
  • public void AcceptSlipClientAsync(object userToken)
  • public bool Pending()
  • public void Start()
  • public void Start(int backlog)
  • public void Stop()
  • public event EventHandler<SlipClientAcceptedEventArgs> SlipClientAccepted
  • public bool Active { get; }

With the exception of CorruptDataException, which happens to be under the first level (root) namespace, all the other classes are under a third level namespace company.Net.Sockets. As you can see, the two main classes are SlipListener and SlipClient. "SLiP" happens to stand for serialized list protocol. In its current incarnation, it only serves to facilitate the transmission of messages with parameters. I won’t get too deep into the format of the byte stream right now. I’ll save that for an upcoming article.


Okay, I’ve been babbling on long enough. Now for the questions (which concerns the SlipClient class for the most part):


  1. The SlipClient class has two internal AutoResetEvent fields. One controls access to the send methods, and the other controls access to the receive methods. In effect, one send method must return (or the SendCompleted event raised) before another send method can proceed. The logic is similar for the receive methods. Should I scrap the wait handles and allow calls to the send and receive methods to be uncontrolled by the class?
  2. For the SlipClient class, the synchronous Receive method returns null if the remote machine disconnects before all the necessary bytes (the ones needed to reconstruct the IList<byte[]> that was sent) are received. In conjunction, it raises a Disconnected event using a ThreadPool thread (so the event handler can’t block the rest of the Receive method from executing). Should I throw an exception instead of returning null?
  3. All the networking-related classes are sealed because I’m not sure how to open up the classes to extension. If you were extending the class, what would you like to be able to do?
  4. You’ll notice that the ReceiveCompletedEventArgs class has a Data property that returns an IList<byte[]>. Yet, I’d like to be able to add other classes like SlipClient and SlipListener, but have them work with something other than IList<byte[]>. In other words, I might have other classes sharing the same namespace. I’m aware of four options I can go along with:
    1. Return an Object object for the Data property so all my other classes can use it.
    2. Create another class to encapsulate the data to be sent and work with that class instead of IList<byte[]>. The class will have the necessary properties and methods to allow for flexibility.
    3. Rename the class to something like SlipClientReceiveCompletedEventArgs so it is exclusive to the SlipClient class’s events. I think it’s a bit long, but I could deal with that.
    4. Scrap the current class and make a new one that can work for any new classes. I’m not sure how to go about this route, but it sounds nice.
  5. Should I have the Receive and ReceiveAsync methods at all? I mean, I could have the class automatically fire events as the data comes in, but I feel this will make it very chaotic. Besides, SlipClient is returned by SlipListener, and if the SlipClient class starts firing events before the application can add its event handler, data will be lost. I already know what to do to solve it, but the ideas seem very inelegant, and I’m left thinking it’s better to keep the Receive and ReceiveAsync methods there so the application can control when and how fast it receives data.

It’s been a long message and a big headache trying to make the API conform to .NET standards and conventions—even more so than writing the actual code. I’d be very grateful for input.


GeneralRe: Network Communication Library Pin
Luc Pattyn29-Mar-08 15:05
sitebuilderLuc Pattyn29-Mar-08 15:05 
GeneralRe: Network Communication Library Pin
Ri Qen-Sin30-Mar-08 2:45
Ri Qen-Sin30-Mar-08 2:45 
GeneralReordering Components in the Container Pin
sanicra27-Mar-08 15:23
sanicra27-Mar-08 15:23 
GeneralRe: Reordering Components in the Container Pin
Cedric Moonen30-Mar-08 23:12
Cedric Moonen30-Mar-08 23:12 
GeneralRe: Reordering Components in the Container Pin
sanicra31-Mar-08 1:03
sanicra31-Mar-08 1:03 
GeneralCursory Review: Technical Spec Outline Pin
Brady Kelly27-Mar-08 5:57
Brady Kelly27-Mar-08 5:57 
QuestionAccessing Win32 handles in C# Pin
pinhigh2k25-Mar-08 16:22
pinhigh2k25-Mar-08 16:22 
GeneralRe: Cross-post Pin
Luc Pattyn25-Mar-08 17:05
sitebuilderLuc Pattyn25-Mar-08 17:05 
GeneralRe: Accessing Win32 handles in C# Pin
Stephen Hewitt25-Mar-08 21:24
Stephen Hewitt25-Mar-08 21:24 
GeneralRe: Classes and Composition Pin
led mike26-Mar-08 7:57
led mike26-Mar-08 7:57 
GeneralNamespaces naming policy (English vs. native language) Pin
Oshtri Deka25-Mar-08 12:11
professionalOshtri Deka25-Mar-08 12:11 
GeneralRe: Namespaces naming policy (English vs. native language) Pin
Pete O'Hanlon25-Mar-08 12:28
mvePete O'Hanlon25-Mar-08 12:28 
GeneralRe: Namespaces naming policy (English vs. native language) Pin
Oshtri Deka25-Mar-08 21:09
professionalOshtri Deka25-Mar-08 21:09 
GeneralRe: Namespaces naming policy (English vs. native language) Pin
Pete O'Hanlon25-Mar-08 22:41
mvePete O'Hanlon25-Mar-08 22:41 
GeneralRe: Namespaces naming policy (English vs. native language) Pin
Oshtri Deka26-Mar-08 3:32
professionalOshtri Deka26-Mar-08 3:32 
GeneralRe: Namespaces naming policy (English vs. native language) Pin
Pete O'Hanlon26-Mar-08 3:55
mvePete O'Hanlon26-Mar-08 3:55 
GeneralRe: Namespaces naming policy (English vs. native language) Pin
Brady Kelly26-Mar-08 7:23
Brady Kelly26-Mar-08 7:23 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.