Write your own socket framework (2). socket framework

Source: Internet
Author: User
Tags android games

Write your own socket framework (2). socket framework

1. After the normal listening starts, it is necessary to accept the data. The overall flowchart is as follows:

 

2. We can see in the previous section that many socketconnections are initialized during program initialization to manage client connections. How can the application layer operate and when can we accept data? So we have SocketSession, which is used to manage the entire session process for the application layer. The Code is as follows:

Public class SocketSession: IDisposable {public string SessionId {get; private set;} private System. net. sockets. socket _ connectSocket; private IProtocol _ protocol; private SocketConnection _ connect; public SocketConnection Connection {get {return _ connect ;}} private MemoryStream _ memStream; private delegate void ReceiveDataHandler (SocketAsyncEventArgs e ); private ReceiveDataHandler ReceiveH Andler; private delegate void ReceiveReadPackageHandler (byte [] B, int offset, SocketAsyncEventArgs e); private ReceiveReadPackageHandler ReadPackageHandler; public System. net. sockets. socket ConnectSocket {get {return _ connectSocket;} private set {} public SocketSession (string sessionId) {this. sessionId = sessionId;} public SocketSession (System. net. sockets. socket client, SocketConnection co Nnect): this (Guid. newGuid (). toString () {this. _ connectSocket = client; this. _ connect = connect; this. _ protocol = connect. pool. appServer. appProtocol; _ memStream = new MemoryStream (); ReceiveHandler = ReceiveData; ReadPackageHandler = this. readPackage;} internal void ReceiveData (SocketAsyncEventArgs e) {if (e. socketError! = SocketError. success) {this. close (); return;} if (e. bytesTransferred <= 0) {this. close (); return;} try {if (this. connection. flag = SocketFlag. busy) {byte [] buffer = new byte [e. bytesTransferred]; Array. copy (e. buffer, 0, buffer, 0, e. bytesTransferred); ReadPackage (buffer, 0, e); buffer = null ;}} catch (Exception ex) {this. close (); return ;}} internal void ReceiveAsync (SocketAsyncEventArgs E) {if (e = null) {return;} bool isCompleted = true; try {isCompleted = this. _ connectSocket. receiveAsync (e);} catch (Exception ex) {LogHelper. debug (this. sessionId + ex. toString (); this. close () ;}if (! IsCompleted) {this. receiveHandler. beginInvoke (e, ReceiveHandlerCallBack, ReceiveHandler) ;}} void ReceiveHandlerCallBack (IAsyncResult result) {try {(result. asyncState as ReceiveDataHandler ). endInvoke (result);} catch (Exception e) {LogHelper. debug (e. message) ;}} internal void OnDataRecevied (SessionEventArgs arg) {if (DataRecevied! = Null) {this. _ memStream. setLength (0); DataRecevied. invoke (this, arg) ;}} internal void Close () {try {this. _ connectSocket. close ();} catch (Exception ex) {LogHelper. debug ("Disable socket exception" + ex. toString ();} if (this. closed! = Null) {this. Closed () ;}} internal Action Closed; internal Action <SocketSession, SessionEventArgs> DataRecevied; public void Dispose () {if (_ memStream! = Null) {_ memStream. close (); _ memStream. dispose (); _ memStream = null;} public void Send (byte [] data) {try {if (this. connection. flag = SocketFlag. busy) {this. _ connectSocket. send (data) ;}} catch (Exception ex) {this. close () ;}} private void ReadPackage (byte [] data, int offset, SocketAsyncEventArgs e) {if (data = null | data. length = 0) {return;} if (offset> = data. length) {return;} if (offset = 0) {if (_ memStream. length> 0) {_ memStream. write (data, 0, data. length); data = _ memStream. toArray () ;}}// handle OnReceivedCallBack (data, offset, e); data = null;} private void OnReceivedCallBack (byte [] buffer, int offset, SocketAsyncEventArgs e) {byte [] data = this. _ protocol. onDataReceivedCallBack (buffer, ref offset); if (offset =-1) {this. close (); return;} if (data = null | data. length = 0) {this. _ memStream. write (buffer, offset, buffer. length-offset); this. receiveAsync (e); return;} SessionEventArgs session_args = new SessionEventArgs (); session_args.Data = data; this. onDataRecevied (session_args); if (offset <buffer. length) {this. readPackageHandler. beginInvoke (buffer, offset, e, ReadPackageCallBack, ReadPackageHandler);} else {this. receiveAsync (e);} data = null;} void ReadPackageCallBack (IAsyncResult result) {try {(result. asyncState as ReceiveReadPackageHandler ). endInvoke (result);} catch (Exception ex) {LogHelper. debug (ex. message );}}}View Code

 

When the ReceiveAsync method receives data, we call an asynchronous delegate ReceiveHandler. BeginInvoke.

When parsing an independent package and there are extra packages in the buffer data, we also call an asynchronous delegate ReadPackageHandler. BeginInvoke.

If the buffer is large, for example, if I am 8 KB and a single package is small, the client sends messages more frequently. It will lead to a short recursion when parsing the package. Recursion will not stop the heap, and resources will not be released.

After running for a period of time, it may cause OutOfMemoryException. If the data is received synchronously, a recursion may also be formed in the Receive place. Therefore, asynchronous calling is adopted.

 

3. Because the socket is borderless, every Send at the code layer is not directly sent to the server in the real sense, but only to the buffer zone, the system determines when to send messages. If the client sends packets frequently, the packets that the server obtains from the buffer may be composed of multiple packets. The package obtained from the buffer cannot be an Independent Application Layer package. The package must be parsed according to the established protocol.

Let's assume that a simple protocol, the first four bytes of a package, indicates the length of the Package content. The Code is as follows:

Public class DefaultProtocol: IProtocol {public byte [] OnDataReceivedCallBack (byte [] data, ref int offset) {int length = BitConverter. toInt32 (data, offset); int package_head = 4; int package_length = length + package_head; byte [] buffer = null; if (length> 0) {if (offset + package_length <= data. length) {buffer = new byte [length]; Array. copy (data, offset + package_head, buffer, 0, length); offset + = package_length ;}} else {offset =-1 ;}return buffer ;}}View Code

If the Protocol cannot be properly parsed, offset =-1 and close the link. If there is still a remaining package after parsing a package, the parsing will continue after it is thrown to the application layer. If a single package is large and the buffer cannot be placed at a time, we temporarily write the data into the memory stream, and then parse the data received next time.

4. After receiving data, associate SocketConnection with SocketSession. The Code is as follows:

Public class AppServer: IAppServer {public delegate void Merge (SocketSession o, SessionEventArgs e); public delegate void NewConnectionHandler (SocketSession o, EventArgs e); public delegate void OnErrorHandler (Exception e ); public event DataRecevieHandler DataRecevied; public event NewConnectionHandler NewConnected; public event OnErrorHandler OnError; private ISocketListener _ listen Er; private SocketConnectionPool _ connectPool; public AppServer (ServerConfig serverConfig) {this. appConfig = serverConfig; if (this. appProtocol = null) {this. appProtocol = new DefaultProtocol ();} _ connectPool = new SocketConnectionPool (this); _ connectPool. connected = OnConnected; _ listener = new SocketListener (this. appConfig); _ listener. newClientAccepted + = new NewClientAcceptHandler (listener _ NewClientAccepted); _ listener. Error + = new ErrorHandler (_ listener_Error);} void OnDataRecevied (SocketSession session, SessionEventArgs e) {if (this. DataRecevied! = Null) {DataRecevied. beginInvoke (session, e, DataReceviedCallBack, DataRecevied) ;}} public bool Start () {_ connectPool. init (); return _ listener. start ();} public void Stop () {_ listener. stop ();} void _ listener_Error (ISocketListener listener, Exception e) {if (this. onError! = Null) {this. onError. invoke (e) ;}} void listener_NewClientAccepted (ISocketListener listener, System. net. sockets. socket client, object state) {_ connectPool. push (client);} public void OnConnected (System. net. sockets. socket client, SocketConnection connect) {var session = new SocketSession (client, connect); session. dataRecevied = OnDataRecevied; connect. initialise (session); if (NewConnected! = Null) {NewConnected. BeginInvoke (session, EventArgs. Empty, NewConnectedCallBack, NewConnected);} if (connect. RecevieEventArgs! = Null) {session. receiveAsync (connect. recevieEventArgs) ;}} void DataReceviedCallBack (IAsyncResult result) {try {(result. asyncState as DataRecevieHandler ). endInvoke (result);} catch (Exception e) {LogHelper. debug (e. message) ;}} void NewConnectedCallBack (IAsyncResult result) {try {(result. asyncState as NewConnectionHandler ). endInvoke (result);} catch (Exception e) {LogHelper. debug (e. message) ;}} public ServerConfig AppConfig {get; set;} public IProtocol AppProtocol {get; set ;}}View Code


At this point, the entire process of receiving packets is over. However, we find that the packet is being sent synchronously. If you have special requirements, you can consider writing it as an Asynchronous Method, but I personally prefer to leave this part for Application Layer processing, write a sending queue at the application layer, and then have an independent thread to manage this sending queue.

 


How can I develop Android games to build servers and transmit data between clients and servers?

1. First, you must have a common mysql oracle mssql database.
2. There must be a server.
What communication protocols do you use?
HTTP web servers include tomcat, apache, and weblogic.
If the socket protocol is used, you can write a server by yourself or use a ready-made framework. apache mina2.0 is very useful.
3. The android mobile client program needs to write a program to connect to the server for data transmission.
If HTTP is used, the api supports HttpClient.
For Socket, the api also supports writing apache mina.

Use socket to write a connection-oriented network programming framework for me

This ..... Source code?
 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.