Use asynchronous sockets to program the communication architecture of CS for TCP network services in C # (1) ---- Basic Class Ba

xiaoxiao2021-03-06  16

/// *

Title: Use asynchronous socket to program the communication architecture of the C / S of the TCP network service in C # (1) ---- Basic Class Bank section

When I saw TCPLISTENER and TCPCPClient, I was very happy, that is, I want's communication mode but found that their power is too thin, we need a better class library to replace them.

Below, some classes are provided, which can complete TCP C / S communication mode. In the second part of this article, I will introduce you how to use them.

Mainly through events, the entire function: the server's events include:

The events that the server fully new client connection client shuts down the receipt of the data client includes:

The connected server receives the data connection to close

In addition, in order to flexibly handle demand changes, it also provides a method of implementation of encoders and packet parsers. Note: This class has not been tested by strict testing, if a bug, please send it to me, I will feel that your entire behavior is Encourage and support for me.

* ///

///

/// (c) 2003-2005 C2217 Studio /// Reserved // // file name: tcpcsframework.cs /// file ID: /// programming language: c # // / Document Description: Communication framework base class /// (using an asynchronous socket programming implementation) /// // Current version: 1.0 ////// author: Deng Yang were /// EMail: dyj057@gmail.com/// creation date: 2005-3-9 /// last modified: 2005-3-17 /// /// history records: // / /// Time: 2005-3-14 // / Modified Content: /// 1. Create IBMS.NET.TCPCSFramework Namespace and Add Session Object ./// 2. Modify the NetEventargs class to accommodate new add objects. /// 3. Added a session exit type, more suitable for the actual situation ./// Note: /// * Forced exit type is the direct end of the application, such as end ////rries or programs to exit by the task manager, etc. No normal exit method is generated ./// * Normal exit type is the key to the application execution of normal exit, and then call Socket.ShutDown (SocketShutDown.both) to call /// Socket .Close () method, not directly call socket.close () method, // if that call will produce a forced exit type. / / / / / / / / // 1. Create TCPCLI, CODER, DataGramResover objects, separated abstract and implementation part //// / 2. File version is modified to 1.1,1.0 is still retained, renamed: /// tcpcsframework_v1.0.cs //// 3. Modify custom HashTable in TCPServer is system HashTable Type // / / / /

Using system.net.sockets; using system.net; using system.diagnostics; using system.collections;

Namespace ibms.net.tcpcsframework {

///

/// network communication event model commission /// public delegate void NetEvent (Object sender, NetEventArgs e); /// /// Provides a server class / // /// version: 1.1 /// Replace version: 1.0 // /// Features: /// 1. Use the Hash table to save all the status of the connected client, you can achieve quick lookup when you receive the data. Whenever /// There is a new session that will generate a new session. This session represents a passenger ///-house object. /// 2. Use asynchronous Socket events as the foundation, complete the network communication function . /// 3. Support for identification of tagged data packets to complete the transmission of big data packets and adapt to bad networks /////////////bit environment, initially stipulate the maximum data packet supported by this class (ie The size of a packet cannot be greater than ///640K, otherwise the server program will automatically delete the packet data, and it is considered to be illegal data) to prevent the server crash because of the data packet /// unlimited growth. // 4. Format The encoding.default format can be used by default. You can /// // /// /// ////// ///// ///-8 communication method of U-16 and U-8 can also be used. You can inherit the //// inheritance class The medium load encoding and decoding functions, custom encryption formats are communicating. In summary, the client and service /// server use the same communication format /// 5. Use C # Native Code, future considerations can be considered in efficiency Can C The 32-bit DLL written by the code is instead /// c # core code, but does this lack of portability, and is the unsafe code (the C code of this class also exists) /// 6. The number of maximum login clients that can limit the server /// 7. With more fine control and more powerful asynchronous data transfer than using TCPListener, it can be used as an alternate class /// 8 for // TCPListener, using asynchronous communication mode, completely do not worry about communication blocking and thread problems, No need to consider the details of communication ///// Note: /// 1. The part of the code is generated by the Rational XDE, possibly with the coding specification /// /// Principle: // / / / / //////// Use usage : // /// Example: ///// public class tcpsvr {#R EGION Definition Field /// /// The default server maximum connection client data /// public const in defaultmaxclient = 100; /// /// Receive data buffer size 64K /// public const Int defaultBuffersize = 64 * 1024;

///

/// Maximum data packet size /// public const Int maxdatagramsize = 640 * 1024;

///

/// packet parser /// private damramresolver_resolver;

///

/// Communication format codec /// private coder _coder;

///

/// server program used port /// private usort _port;

///

/// server program allowed maximum client connections /// private ushort _maxclient;

///

/// server running status /// private bool _srun; /// /// Receive data buffer /// private byte [] _recvdataBuffer;

///

/// server uses asynchronous socket classes, /// private socket _svrsock;

///

/// Save all client sessions /// ;;

///

/// The number of clients currently connected /// private ushort _clientcount;

#ndregion

#REGON event definition ///

/// Client Establish connection event /// public event NetEvent ClientConn;

///

/// Client Close Event /// public evenet NetEvent ClientClose;

///

/// server is full of events /// public event NetEvent ServerFull;

///

/// server receives data event /// public evenet NetEvent Recvdata;

#endregion #Region constructor

///

/// Structure /// /// server-side port number /// The server can accommodate the maximum capabilities of the client /// Communication code public tcpsvr (ushort port, ushort maxclient, coder code) {_port = port; _maxclient = maxclient ; _CODER = CODER;}

///

/// Constructor (default use default encoding mode) /// /// server-side port number /// < param name = "maxClient"> the server can accommodate the maximum capabilities of the client's public TcpSvr (ushort port, ushort maxClient) {_port = port; _maxClient = maxClient; _coder = new Coder (Coder.EncodingMothord.Default);}

//

/// Constructor (default use default encoding method and defaultmaxclient (100) client capacity) /// /// server-side port number Public TCPSVR (Ushort Port): this (port, defaultmaxclient) {} #ENDREGON

#region attribute

///

/// server Socket object /// public socket serversocket {get {return_svrsock;}}

///

/// Data Packet Analyzer /// Public DataGramresolver resovlver {get {return_resolver;} set {_resolver = value;}}

///

/// client session array, save all clients, do not allow the content of the array /// public hashtable sessionTable {Get {Return_SessionTableTable;}}

///

/// server can accommodate the maximum capabilities of the client /// public int Capacity {get {return_maxclient;}}

///

/// Current client connection number /// public int sessioncount {get {return_clientcount;}}

///

// / server running status /// public bool isrun {get {return_ismun;}}

#endregion #Region public method

///

/// Start the server program, start listening to the client request /// public virtual void start () {if (_ _RUN) {throw ("TCPSVR is already running.") );} _SessionTable = new hashtable (53); _RECVDATABUFFER = New byte [defaultBuffersize];

// Initialize Socket_svrsock = New Socket (AddressFamily.internetwork, Sockettype.Stream, ProtocolType.tcp);

// Bind port IpendPoint IEP = New IpendPoint (ipaddress.any, _port); _svrsock.bind (IEP);

// Start listening _SVRSock.Listen (5);

// Set asynchronous method Accept client connection _svrsock.beginAccept (new asyncCallback (acconn), _svrsock;

_ismun = true;

} ///

/// Stop server program, all connections to the client will close /// public virtual void stop () {if (! _ _RUN) {throw ("TCPSVR has stopped "));} // This condition statement must be called before all clients, otherwise error occurs in EndConn_sRun = False;

// Turn off the data connection, responsible for the client considered to force the connection if (_svrsock.connected) {_svrsock.shutdown (socketshutdown.both);

CloseallClient ();

// Clean up resources _svrsock.close (); _SESSIONTABLE = NULL;}

///

/// Close all client sessions, disconnect /// public virtual viid closeallclient () {Client (Session Client in _SessionTable.Values) {Client .Close ();

_SESSIONTABLE.CLEAR ();

///

/// Close a session with the client /// /// Required client session object public virtual void CloseSession (session closeclient) {debug.assert (closeclient! = Null);

IF (CloseClient! = null) {closeclient.datagram = null;

_SESSIONTABLE.Remove (CloseClient.id);

_clientcount--; // Client Force Close Link IF (ClientClose! = null) {ClientClose (this, New NetEventArgs (CloseClient);}

CloseClient.close ();}}

///

/// Send data /// /// Client session of the data /// Data Packet Public Virtual Void Send (SESSION RECVDATACLIENT, STRING DATAGRAM) {// Get Data Coding Byte [] Data = _Coder.GetencodingBytes (DataGram);

Recvdataclient.ClientSocket.Beginsend (Data, 0, Data.Length, Socketflags.none, New AsyncCallback (SendDataEnd), Recvdataclient.ClientSocket;

}

#ndregion

#Region Protection Method ///

/// Turmary Socket, first need to close session /// /// Target Socket Object / // The type of client exits protected virtual void closeclient (socket client, session.exittype exittype) {debug.assert (client! = null); / / Find whether the client is Presented, if there is no existence, throw an exception session closeclient = FindSession (client); closeclient.typeofexit = exittype;

IF (CloseClient! = null) {CloseSession (CloseClient);} else {throw ("New ApplicationException (" The Socket Objects that need to be closed do not exist ");}}

///

/// Client connection processing function /// /// Socket object to establish a server connection Protected Virtual Void Acceptconn (IasyncResulti ) {// If the server stops the service, it is no longer necessary to receive new client IF (! _Srun) {return;}

/ / Accept a client's connection request socket ildserver = (socket) IAR.AsyncState;

Socket Client = Old Server.ndAccept (IAR);

/ / Check if the maximum allowable client number IF (_clientcount == _maxclient) {// server is full, issue notification if (ServerFull! = Null) {ServerFull (this, New NetEventArgs (New session (client))) }} Else {session newsession = new session (client);

_SessionTable.Add (newssion.id, newsession); // Client reference count 1 _clientcount ;

// Start accepting data from the client Client.BeginReceive (_RecvdataBuffuffer, 0, _RecvdataBuffer.length, SocketFlags.none, New AsyncCallback (receiveData), Client);

// New customer segment connection, send a notification if (ClientConn! = Null) {ClientConn (this, new neteventargs (newsession));}}

// Continue to accept the client _svrsock.beginaccept (new asyncCallback (acconn), _svrsock);

///

/// Find session objects /// /// found by Socket object NULL, the description does not exist private session FindSession (Socket Client) {sessionid ID = New sessionID ((int) client.handle; return (session) _SessionTable [ID];}

///

/// Accept data completion processing function, asynchronous features are reflected in this function, /// After receiving the data, automatically resolve to string packet /// // / Target Client Socket Protected Virtual Void ReceiveData (IASYNCRESULT IAR) {socket client = (socket) IAR.ASYNCSTATE

Try {// If the asynchronous reception is started twice, the endReceive int RECV = Client.Endreceive (IAR) is executed twice when the client exits.

IF (RECV == 0) {// Normal Close CloseClient (Client, Session.exitType.NormaleXit); Return;}

String receiveddata = _Coder.Getencodingstring (_RecvdataBuffer, RECV);

// Release the event IF (Recvdata! = Null) {session (client); debug.assert (SendDataSession! = NULL);

/ / If you define the tail mark of the message, you need to handle multiple cases of information IF (_Resolver! = Null) {if (sendDatasession.DataGram! = Null && senddatassion.DataGram.length! = 0) {// plus The last message of the last message ReceivedData = SendDataSession.DataGram receivedData;}

String [] Recvdatagrams = _Resolver.Resolve (Ref receiveddata);

Foreach (String NewDataGram in Recvdatagram) {// Deep copy, in order to keep DataGram confrontation acloneable copyspace;

Session ClientSession = (session) CopySession.Clone ();

ClientSession.DataGram = newDatagram; // Release a message message Recvdata (this, new neteventargs (clients);}

// The remaining code snippet uses SendDatasession.DataGram = receiveddata; if (sendDatasession.DataGram.length "{sendDatasession.DataGram = null;}} // without defined packets Use else {iCloneable Copysession = (iCloneable) denddatassion;

Session ClientSession = (session) CopySession.Clone ();

ClientSession.DataGram = ReceiveData;

Recvdata (this, New NetEventArgs (ClientSession));}} // end of if (recvdata! = NULL)

/ / Continue to receive data from the client client (_RecvdataBuffer, 0, _RecvdataBuffer.Length, SocketFlags.None, New AsyncCallback (receiveData), client);

} Catch (socketexception ex) {// client exits if (10054 == ex. errorcode) {// Client Force Close CloseClient (Client, Session.exittype.exceptionExit);}} catch (ObjectdisposedException EX) {// Here The implementation is not elegant // When the closesession () is called, the data is received, but int RECV = Client.EndReceive (IAR) is called in the data reception // process; // Access the CloseSession () has been disposed of objects / / I think this is also a non-harmful. If (ex! = Null) {EX = null; // Donothing;}}}

///

/// Send data completion processing function /// /// Target client socket protected virtual void senddatand (IasyncResult IAR) {socket Client = (socket) IAR.ASYNCSTATE;

INT Sent = Client.Endsend (IAR);

#ndregion

}

///

/// Provide a client class with TCP network connection services // // ///////////////////////////>: /// Principle: /// 1 . Use asynchronous socket communication and server in accordance with certain communication format, please note that the server's pass ///xfa format must be consistent, otherwise the server program can crash, the whole problem is not overcome, how to judge from byte [] // Its encoding format /// 2. Supports identification of data packet format with tag to complete the transfer of big data packets and adapt to bad networks /////////// Note: / // public class tcpcli {#Region field

///

/// Client and server session /////////////////////// /// Client Has been connected to Server /// Private bool _isconnected = false;

///

/// Receive data buffer size 64K /// public const Int defaultBuffersize = 64 * 1024;

///

/// packet parser /// private damramresolver_resolver;

///

/// Communication format codec /// private coder _coder;

///

/// Receive data buffer /// private bote [] _recvdatabase = new byte [defaultbuffersize];

#ndregion

#REGON event definition

// Need to subscribe to the event to receive the notification of the event, if the subscriber exits, you must cancel the subscription ///

/// has been connected to server event /// public event NetEvent ConnectedServer;

///

/// receives data packets /// public evenet NetEvent receiveddatagram;

///

/// Connection Disconnect Event /// Public Event NetEvent DisconnectedServer; #ENDREGON

#region attribute

///

/// Returns the session object between the client and the server //// public session clientsession {get {return_Session;}}

///

/// Returns the connection status between the client and the server /// public bool isconnected {get {returnnected;}}

///

/// Data Packet Analyzer /// Public DataGramresolver resovlver {get {return_resolver;} set {_resolver = value;}}

///

/// encoding decoder /// public coder servercoder {get {return_coder;}}

#endregion #Region public method

///

/// Default constructor, using the default encoding format /// public tcli () {_coder = new coder (CODER.EncodingmothOrd.default);}

///

/// Constructor, use a specific encoder to initialize /// /// Packet Encoder public TCPCLI (CODER CODER) {_CODER = CODER;} /// /// connection server /// /// server IP address /// server port public virtual void connection (isconnected) {i (isconnected) {// Reconnect Debug.Assert (_SESSION! = null);

CLOSE ();

Socket news = new socket (addressfamily.internetwork, sockettype.stream, protocoltype.tcp);

IpendPoint IEP = New IpendPoint (iPaddress.Parse (IP), Port); Newsock.BegInConnect (IEP, New AsyncCallback (Connected), Newsock

}

///

/// Send data message /// /// public virtual void send (string data) {if (datagram.length = = 0) {return;}

If (! _isconnected) {throw ("No connection server, no data"));

// Get the coded byte by the message byte [] data = _coder.getencodingBytes (DataGram);

_Session.ClientSocket.begInsend (Data, 0, Data.Length, SocketFlags.none, New AsyncCallback (SenddataEnd), _Session.ClientSocket;

///

/// Close connection /// public virtual void close () {if (! _ isconnected) {return;}

_Session.Close ();

_Session = NULL;

_isconnected = false;

#ndregion

#Region protected method

///

/// data send completion processing function /// /// protected version {socket remote = (socket) ) IAR.ASYNCSTATE; INT SENT = Remote.endsend (IAR); debug.assert (Sent! = 0);

///

/// Establish TCP connection post-processing process /// /// Asynchronous Socket protected virtual void connection (ivket socket) {socket socket = (Socket) IAR.ASYNCSTATE;

Socket.endConnect (IAR);

// Create a new session _Session = new session (socket); _ISCONNECTED = true;

// Trigger the connection to establish an event if (Connected Server! = Null) {ConnectedServer (this, new neteventargs;});

// Establish a connection to receive data immediately_Session.ClientSocket.BeginReceive (_RecvdataBuffer, 0, DefaultBufferSize, SocketFlags.none, New AsyncCallback (Recvdata), Socket;}

///

/// data reception processing function /// /// asynchronous socket protected virtual void recvdata (IasyncResult IAR) {socket remote = IAR.ASYNCSTATE;

Try {int RECV = Remote.EndReceive (IAR);

// Normal exit IF (Recv == 0) {_Session.TypeOfExit = session.exittype.NormaleXit;

IF (disconnectedserver! = null) {disconnectedserver (this, new neteventargs);}

Return;}

String receiveddata = _coder.GetencodingString (_RecvdataBuffer, RECV); // The message IF received by the event release (ReceiveDataGram! = null) {// If the message is analyzed by the packet parser, if the message is defined Mark, you need to handle multiple cases of information IF (_Resolver! = Null) {if (_Session.DataGram! = Null && _ssion.DataGram.length! = 0) {// Plus the last message of the message ReceiveData = _Session.DataGram receiveddata;} String [] recvdatagram = _Resolver.Resolve (Rec ReceiveData);

Foreach (String NewDataGram in Recvdatagram) {// NEED Deep Copy. Because you need to guarantee multiple different packets independently there are iCloneAble CopySession = (iCloneable);

Session ClientSession = (session) CopySession.Clone ();

Clientsession.DataGram = newdatagram;

// Release a message ReceiveDataGram (this, New NetEventArgs (ClientSession);

// The remaining code snippet is used when receiving _Session.Datagram = receiveddata;} // does not define the tail mark of the message, directly give the message subscriber to use else {iCloneable CopySession = (iCloneable) _Session;

Session ClientSession = (session) CopySession.Clone ();

ClientSession.DataGram = ReceiveData;

ReceivedDataGram (this, New NetEventArgs (ClientSession);

}

} // end of if (ReceiveDataGram! = null)

// continue to receive data _session.ClientSocket.BeginReceive (_recvDataBuffer, 0, DefaultBufferSize, SocketFlags.None, new AsyncCallback (RecvData), _session.ClientSocket);} catch (SocketException ex) {// the client exits if (10054 == ex {// server forced shutdown connection, force exit _Session.TypeOfexit = session.exittype.exceptionexit;

IF (disconnectedserver! = null) {disconnectedserver (this, new neteventArgs);}}} else {throw (ex);}} catch (objectdisposedException ex) {// The implementation here is not elegant // When calling CloseSession () At the time of the data reception, int RECV = Client.EndReceive (IAR) will be called in data reception //; // to access the CloseSession () The object I have been disposed // I think this is also hurting. IF (ex! = null) {EX = null; // Donothing;}}} #ENDREGON

}

///

/// Communication coding format provider provides encoding and decoding services for communication services /// You can customize your own encoding method in inherited classes such as data encryption transmission, etc. /// Public class coder {/// /// encoding mode /// private encodingmothord _EncodingMothORD;

PROTECTED CODER ()} public coder (EncodingmothOrd EncodingMothOrd) {_EncodingMothord = EncodingMothOrd;

Public Enum EncodingMothORD {Default = 0, Unicode, UTF8, ASCII,}

///

/// News Data Decoding /// /// Data required Decoded data /// Post-encoded data public virtual string GetEncodingString (byte [] dataBytes, int size) {switch (_encodingMothord) {case EncodingMothord.Default: {return Encoding.Default.GetString (dataBytes, 0, size);} case EncodingMothord.Unicode: {return Encoding .Unicode.GetString (dataBytes, 0, size);} case EncodingMothord.UTF8: {return Encoding.UTF8.GetString (dataBytes, 0, size);} case EncodingMothord.ASCII: {return Encoding.ASCII.GetString (dataBytes, 0 , Size); DEFAULT: {throw (New Exception ");}}

}

///

/// data encoding /// /// Required packet /// Post-encoded data public virtual byte [] GetEncodingBytes (string datagram) {switch (_encodingMothord) {case EncodingMothord.Default: {return Encoding.Default.GetBytes (datagram);} case EncodingMothord.Unicode: {return Encoding.Unicode.GetBytes (datagram) ;} case EncodingMothord.UTF8: {return Encoding.UTF8.GetBytes (datagram);} case EncodingMothord.ASCII: {return Encoding.ASCII.GetBytes (datagram);} default: {throw (new Exception ( "undefined code format "));}}}}

///

/// Data Packet Analyzer, by analyzing the received raw data, get the complete data packet. /// Inherit this class can realize its own packet parsing method. /// usually The packet recognition method includes: a method of fixed length, length tag, marker, and the like // / Reality of this class is a method of marking, you can implement other methods //////////// Public Class DataGramResolver {/// /// packet end tag /// private string endtag;

///

/// return end tag /// string endtag {get {return endtag;}}

///

/// Protected default constructor, is provided to inheritance class /// protected DataGramResolver () {

}

///

/// Constructor /// /// packet end tag public datagramRamResolver (String endtag) {if (endtag == NULL ) {Throw ("End Marker cannot be NULL");

IF (endtag == ") {throw (" "end tag symbol can not be empty string"));

THIS.Endtag = endtag;

///

/// parsing message /// /// Raw data, returning unused packet pieces, /// The clip will be saved in Session In the /// packet array of DataGram objects, the original data may contain multiple packets public virtual string [] resolve (ref string rawdatagram = new arraylist (); // Tail mark position index int tagIndex = -1;

While (True) {tagIndex = Rawdatagram.indexof (endtag, tagIndex 1); if (tagIndex == -1) {Break;} else {// Follow the end tag to divide the string into two parts String newDatagram = Rawdatagram . Substring (0, tagindex endtag.length);

DataGrams.Add (NewDataGram); if (tagIndex endtag.length> = rawDatagram.length) {rawDatagram = "

Break;

Rawdatagram = rawdatagram.substring (tagIndex endtag.length - newdatagram.length);

// Start from the start position to find tagIndex = 0;}} String [] results = new string [datagrams.count];

DataGrams.copyto (Results);

Return Results;

}

///

/// Client and server session /// // ////////////////> Description: /// Session class contains remote communication The state of the end, these status includes the type of socket, packet content, /// client exits (normal shutdown, forced exiting two types) /// public class session: iCloneable {#Region field

///

/// session ID /// private sessionID;

///

/// Client Send to the server /// Note: In some cases, the message may just be a piece of message instead of //// private string _Datagram; // / /// client socket /// private socket _clisock;

///

/// client's exit type /// private exittype _exittype;

///

/// Exit type enumeration /// public enum exittype {normalexit, ExceptionExit};

# endregion # region properties

///

/// Returns the id /// public sessionid id {get {return_id;}}

///

/// Access session message /// public string database {get {return _datagram;} set {_datagram = value;}} /// /// Socket objects associated with client sessions /// public socket clientsocket {get {return_clisock;

///

/// Access client exit /// public exittype typeofexit {get {return _exittype;}

Set {_exittype = value;}}

#ndregion

#Region method

///

/// uses the Handle value of the socket object as Hashcode, which has a good linear feature. /// /// public override int getHashcode () {Return (int) _clisock.handle;

///

/// Returns whether two sessions represent the same client /// /// //// Public override Bool Equals (Object Obj) {session rightobj = (session) Obj; return (int) _clisock.handle == (int) Rightobj.clientSocket.handle;

}

///

/// Overloads toString () method, returns the feature of the session object /// /// public override string toString () {string result = string. Format ("Session: {0}, IP: {1}", _ID, _clisock.remoteEndPoint.toString ());

//Result.c retturn result;}

///

/// Constructor /// /// Socket connection public session (Socket Clisock) (CLISOCK) (CLISOCK) (CLISOCK) ! = NULL);

_clisock = clisock;

_id = new sessionId ((int) clisock.handle;}

///

/// Close Session /// public void close () {debug.assert (_clisock! = null); // Turns the acceptance and sending of data _clisock.shutdown (socketshutdown.both) ;

// Clean up resources _clisock.close ();

#ndregion

#Region icloneable member

Object system.icloneable.clone () {session new assion = new session (_clisock); newsession.DataGram = _datagram; newsession.typeofexit = _exittype;

Return new assion;

#ndregion}

///

/// Unique logo A session, auxiliary session object Completes specific features in the Hash table /// public class sessionid {/// // / Socket The object's Handle value must be used to initialize it /// private int _id;

///

/// Return ID value /// public int id {get {return_id;}}

///

/// Constructor /// /// socket Handle Value public sessionId (int id) {_id = id;}

///

/// Overload. In order to meet the HashTable key value /// /// /// Public override bool equals (object obj) {if (obj! = null) {sessionid right = (sessionid) OBJ;

Return_ID == Right._ID;} else if (this == null) {return true;} else {return false;}}

///

/// overload. In order to comply with HashTable key value /// /// public override int getHashcode () {return_id;}

///

/// Overload, in order to facilitate display output /// public override string toString () {return_id.tostring ();

}

///

/// server program event parameters contains session objects that excited the event ///////mmary> public class NetEventArgs: Eventargs {#Region field

///

/// Client and server session /// private session _client;

#ndregion

#Region constructor ///

/// Constructor /// /// client session public neteventargs (session client) {if (null == Client) {throw (new argumentnullexception ());

_client = client;} #ENDREGION

#REGION attribute ///

/// Get a session object that excited the event /// public session client {get {return_client;}}

#ndregion}}}

转载请注明原文地址:https://www.9cbs.com/read-45203.html

New Post(0)