Write your own Socket framework (1). socket framework

Source: Internet
Author: User

Write your own Socket framework (1). socket framework

This series only introduces the C # asynchronous Socket framework that can be used in the production environment. If you see similar code elsewhere, don't be surprised. It may be that when I refer to the open source code, directly "plagiarize.

 

1. Think about the entire socket link processing process in your mind, so you will have it.

2. Start listening. The Code is as follows:

Public override bool Start () {this. _ socket = new System. net. sockets. socket (AddressFamily. interNetwork, SocketType. stream, ProtocolType. tcp); // set KeeyAlive. If the client does not actively send messages, Tcp itself sends a heartbeat packet to notify the server. This is a link for communication. // Avoid waiting for the next communication to know that the link is disconnected. This. _ socket. setSocketOption (SocketOptionLevel. socket, SocketOptionName. keepAlive, true); this. _ socket. setSocketOption (SocketOptionLevel. socket, SocketOptionName. dontLinger, true); try {this. _ socket. bind (base. socketConfig. point); this. _ socket. listen (base. socketConfig. backlog); this. _ socket_args = new SocketAsyncEventArgs (); this. _ socket_args.Completed + = new EventHandler <SocketAsyncEventArgs> (Acc EptSocketCompleted); // when the link is over, if IO is not suspended, AcceptAsync is False, indicating that the synchronization is completed. If (! This. _ socket. acceptAsync (this. _ socket_args) {AcceptSocketCompleted (this. _ socket, this. _ socket_args);} return true;} catch (Exception ex) {return false;} void AcceptSocketCompleted (object sender, SocketAsyncEventArgs e) {System. net. sockets. socket socket = null; if (e. socketError! = SocketError. success) {return;} else {socket = e. acceptSocket;} e. acceptSocket = null; bool willRaiseEvent = false; try {// continue listening to this port. Data Transmission of other links is not affected when processing logic. WillRaiseEvent = this. _ socket. AcceptAsync (e);} catch (Exception ex) {willRaiseEvent = true;} if (socket! = Null) OnNewClientAccepted (socket, null); if (! WillRaiseEvent) AcceptSocketCompleted (null, e );}View Code

3. When the link is over at this time, it is necessary to begin to enter the queue. If there is no such requirement, this step can be ignored. The Code is as follows:

Public class SocketProxy {public System. net. sockets. socket Client; public DateTime Timeout = DateTime. now;} public class SocketConnectionQueue: IDisposable {private Queue <SocketProxy> _ queue; private readonly object _ syncObject = new object (); private bool _ isStop = false; private Thread _ thread; public Action <SocketProxy> Connected; public SocketConnectionQueue () {if (_ queue = null) {_ queue = New Queue <SocketProxy> () ;}if (_ thread = null) {_ thread = new Thread (Thread_Work) {IsBackground = true, Priority = ThreadPriority. highest}; _ thread. start () ;}} public void Push (SocketProxy connect) {lock (_ syncObject) {if (_ queue! = Null) {_ queue. Enqueue (connect) ;}} public void Thread_Work () {while (! _ IsStop) {SocketProxy [] socketConnect = null; lock (_ syncObject) {if (_ queue. count> 0) {socketConnect = new SocketProxy [_ queue. count]; _ queue. copyTo (socketConnect, 0); _ queue. clear () ;}} if (socketConnect! = Null & socketConnect. Length> 0) {foreach (var client in socketConnect) {if (Connected! = Null) {Connected. Invoke (client) ;}} Thread. Sleep (10) ;}} public void Dispose () {_ isStop = true; if (_ thread! = Null) {_ thread. Join ();}}}View Code

4. After Entering the queue, you must allocate resources from the link pool. You can also instantiate a link when each request comes, and then add the link to the pool, my approach is to allocate resources when the program is initialized. The Code is as follows:

Public class SocketConnectionPool: IDisposable {private ServerConfig _ serverConfig; public IAppServer AppServer; private ConcurrentStack <SocketConnection> _ connectPool; private long connect_id = 0; private byte [] _ buffer; private readonly object _ syncObject = new object (); private SocketConnectionQueue _ queue; public Action <System. net. sockets. socket, SocketConnection> Connected; public long Gener AteId () {if (connect_id = long. maxValue) {connect_id = 0;} connect_id ++; return connect_id;} public SocketConnectionPool (IAppServer server) {this. appServer = server; this. _ serverConfig = server. appConfig;} public void Init () {var connects = new List <SocketConnection> (this. _ serverConfig. maxConnectionNumber); _ buffer = new byte [this. _ serverConfig. bufferSize]; SocketAsyncEventArgs arg; for (v Ar I = 0; I <this. _ serverConfig. maxConnectionNumber; I ++) {arg = new SocketAsyncEventArgs (); arg. setBuffer (_ buffer, 0, _ buffer. length); connects. add (new SocketConnection (arg, this);} _ connectPool = new ConcurrentStack <SocketConnection> (connects); if (_ queue = null) {_ queue = new SocketConnectionQueue ();} _ queue. connected = OnConnected;} public void Push (System. net. sockets. socket socket ){ SocketProxy proxy = new SocketProxy () {Client = socket}; _ queue. push (proxy);} public void OnConnected (SocketProxy proxy) {// if the link in the queue is not allocated to resources within the Timeout time, the link is closed and discarded. Int timeout = (int) (DateTime. now-proxy. timeout ). totalSeconds; if (timeout> = this. _ serverConfig. timeout) {proxy. client. close (); return;} else {// not allocated to the resource re-entry column. SocketConnection connect = this. GetConnectionFromPool (); if (connect = null) {_ queue. Push (proxy);} else {if (this. Connected! = Null) {this. connected (proxy. client, connect) ;}}}/// <summary> /// retrieve the link from the link pool (LIFO) /// </summary> /// <returns> </returns> public SocketConnection GetConnectionFromPool () {// _ queue. push (); SocketConnection connect; if (! _ ConnectPool. tryPop (out connect) {return null;} lock (_ syncObject) {long connect_id = this. generateId (); connect. connectId = connect_id;} return connect;} // <summary> // release the link, and put back the connection pool // </summary> // <param name = "connect"> </param> public void ReleaseConnection (SocketConnection connect) {_ connectPool. push (connect); LogHelper. debug (connect. connectId + "pool");} public void Dispose () {_ queue. dispose ();}}View Code

Many socketconnections are initialized in Init (). This is the class we use to manage a specific single link. The Code is as follows:

Public class SocketConnection {public SocketFlag Flag {get; private set;} public SocketConnectionPool Pool {get {return _ pool;} private set {}} private SocketConnectionPool _ pool; public SocketAsyncEventArgs RecevieEventArgs {get; set;} public long ConnectId {get; set;} public SocketConnection () {this. flag = SocketFlag. error;} public SocketConnection (SocketAsyncEventArgs args, SocketConnectionPool pool) {RecevieEventArgs = args; RecevieEventArgs. completed + = new EventHandler <SocketAsyncEventArgs> (SocketEventArgs_Completed); this. flag = SocketFlag. busy; this. _ pool = pool;} void SocketEventArgs_Completed (object sender, SocketAsyncEventArgs e) {var socketSession = e. userToken as SocketSession; if (socketSession = null) {this. flag = SocketFlag. error; this. close (); return;} switch (e. lastOperation) {case SocketAsyncOperation. receive: socketSession. receiveData (e); break; default: break;} public void Initialise (SocketSession session) {this. recevieEventArgs. userToken = session; this. flag = SocketFlag. busy; session. closed + = () => {this. close () ;};} public void Reset () {// ConnectId = 0; this. recevieEventArgs. userToken = null; this. flag = SocketFlag. idle;} private void Close () {this. reset (); LogHelper. debug (ConnectId + "reset"); this. _ pool. releaseConnection (this );}}View Code

 


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

This ..... Source code?
 
Socket Problems

First, the second CLOSE call is called only after the communication is complete. The first one is closed when an error occurs.
Second, fork returns the BOOL value.
Programs Written by SOCKET can be used across operating systems. WINSOCK is a network programming interface implemented by WINDOWS. The program can only be used on WINDOWS.
The SOCKET in C # has restrictions on the. net Framework Structure, which makes programming easier. You can solve the problem of multithreading.
In addition, it is very difficult to use VC ++ to write network programming at the initial stage. We recommend that you have 2 years of VC development experience before doing underlying network programming.

If you sent me a Baidu message from Sichuan Province, I have some experience in C # And VC program development and what I did. I can give it to you.

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.