C # asynchronous Socket (BeginXXXX) server code,

Source: Internet
Author: User
Tags sendmsg

C # asynchronous Socket (BeginXXXX) server code,

Preface:

1. A recent maintenance company's old project is Socket communication, which is mainly used to receive captured images sent by IPC (client). During this period, communication should be maintained, data packets should be monitored and processed. However, I personally think the code I wrote was not very suitable for myself, so I wrote it again. However, the project is temporarily abandoned, so that it can be conveniently used in the future, it is also convenient for more people like me to record some experiences as slag programmers. I still believe in that sentence, so that sharing can make progress faster.

 

2. In fact, I did not know much about this thing before I did it. After all, with my understanding, C # is used to develop websites in China, so I also read a lot of code posted by my predecessors on the Internet. I tried to copy and paste the Code directly. I found that many of them didn't use the code I wrote until I found it was the same thing. Therefore, I would like to advise you not to extend your hand to the party, but to turn others' knowledge into your own capital through your own understanding.

 

Start:

1. Socket communication is divided into two modes: Synchronous mode and asynchronous mode. The client usually uses synchronous mode and asynchronous mode is mostly used by the server. As for the differences between the two, many of my predecessors have already posted a blog post here to help you understand: http://www.cnblogs.com/bloodmaster/archive/2010/07/02/1769774.html. In case this link fails, I believe you will find other resources.

 

2. For this Socket communication, I think the key point is [Data Processing] instead of establishing a link. However, many people who do not know about it may encounter various difficulties, such as closing the Socket link and packet loss, stick the package. The general practice is

2.1: Use a buffer zone to store all received byte arrays, analyze the data, and obtain the valid part.

2.2: The server and client must specify the Message format. Generally, at least [data header id], [data entity length], and [data tail ID] must be provided ], in this way, you can better process the data. Otherwise, it is difficult to determine which data segment is what you want.

2.3: data analysis must be separated by less strings or characters, because the length obtained is likely to be incorrect (there are many empty bytes in it, or the encoding and decoding issues lead to inconsistent string lengths), so be sure to use byte Arrays for processing, through the agreed encoding and decoding format, find the location of the identifier for data splitting. [For example, to connect a client to a server, you must check the identity information. Therefore, you must encrypt a string and then encode it, after the server receives the data, if it first compiles the data into a string and then obtains the password and converts it to byte [], the length may be different from that recorded previously ]. However, it is more convenient to retrieve the packet header information through string splitting.

3. The problem that occurs when a connection is established is that the socket is released because client messages are not received cyclically, or the socket is stopped after only a few messages are received on the client, I have also encountered this problem, so the key to establishing a connection is the recursive loop call of the BeginAccept and BeginReceive methods.

4. The next step is to paste the code. Here there is only the server, and I will post the client after completing the code. The entry function is public and the main method is all here, auxiliary functions (such as obtaining IP addresses, checking whether ports are occupied, and obtaining and sending messages can be searched by yourself. After all, many of these functions are already open-source)

4.1: I am just a wild programmer. If you have any different opinions, please come up with them. Communication is also a good way to make progress.

4.2

public void Create_Server_Socket()        {            Thread th_server = null;            string result = string.Empty;            try            {                socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);                IPAddress ip = Pubilc.Helper.Computer.GetIPv4();                IPEndPoint point = new IPEndPoint(ip, this._port);                socketServer.Bind(point);                socketServer.Listen(this._listen);                th_server = new Thread(() =>                {                    if (this._isRunning)                        socketServer.BeginAccept(AcceptCallBack, socketServer);                    else                        Close_Server_Socket();                });                th_server.IsBackground = true;                th_server.Start();            }            catch (Exception ex)            {                if (th_server.IsAlive)                    th_server.Abort();                ShowLog(ex.Message);            };        }        public void Close_Server_Socket()        {            if (socketServer != null)            {                socketServer.Close();            }        }        void AcceptCallBack(IAsyncResult ar)        {            Socket socketServer = (Socket)ar.AsyncState;            try            {                Socket socketAccept = socketServer.EndAccept(ar);                DynamicBuffer state = new DynamicBuffer();                state.workSocket = socketAccept;                socketAccept.BeginReceive(state.Buffers, 0, state.Buffers.Length, SocketFlags.None, ReceiveCallBack, state);            }            catch(Exception ex)            {                LogHelper.WriteLog(typeof(SocketHelper_Server), ex);                ShowLog("AcceptCallBack" + ex.Message);            }            finally            {                if (this._isRunning)                    socketServer.BeginAccept(AcceptCallBack, socketServer);            }        }        void ReceiveCallBack(IAsyncResult ar)        {            string sendMsg = string.Empty;            DynamicBuffer state = (DynamicBuffer)ar.AsyncState;            Socket socketAccept = state.workSocket;            try            {                int len = socketAccept.EndReceive(ar);                if (len > 0)                {                    state.WritBuffer();                }                else                {                    sendMsg=doMsg.CheckConnection(socketAccept.RemoteEndPoint.ToString());                    if (!string.IsNullOrEmpty(sendMsg))                    {                        byte[] buffer = Encoding.Default.GetBytes(sendMsg);                        state.sb.AddRange(buffer);                    }                    else                    {                        socketAccept.Shutdown(SocketShutdown.Both);                        socketAccept.Close();                    }                }            }            catch (Exception ex)            {                LogHelper.WriteLog(typeof(SocketHelper_Server), ex);                ShowLog("ReceiveCallBack" + ex.Message);            }            finally            {                if (this._isRunning)                {                    try                    {                        Thread th_send = null;                        th_send = new Thread(() =>                        {                            Send(ref state);                            th_send.Abort();                        });                        th_send.IsBackground = true;                        th_send.Start();                        socketAccept.BeginReceive(state.Buffers, 0, state.Buffers.Length, SocketFlags.None, ReceiveCallBack, state);                    }                    catch (Exception ex)                    {                        showLog(ex.Message);                        LogHelper.WriteLog(typeof(IpcServerDo), ex);                    }                }            }        }        void Send(ref DynamicBuffer state)        {            byte[] buffer = null;            string sendMsg = string.Empty;            Socket socketAccept = state.workSocket;            Dictionary<string, byte[]> data;            state.GetAllData(out data);            if (data.Count > 0)            {                sendMsg = doMsg.AcceptFromIpc(socketAccept.RemoteEndPoint.ToString(), ref data);                if (!string.IsNullOrEmpty(sendMsg))                {                    buffer = Encoding.Default.GetBytes(sendMsg.ToCharArray());                    socketAccept.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, SendCallBack, socketAccept);                }                Send(ref state);            }        }        void SendCallBack(IAsyncResult ar)        {            Socket socketAccept = (Socket)ar.AsyncState;            try            {                int sendBytes = socketAccept.EndSend(ar);            }            catch(Exception ex)            {                LogHelper.WriteLog(typeof(SocketHelper_Server), ex);            }        }

4. The following is the State object class. In fact, this is equivalent to a buffer. Put things here to save, including socket objects. What is useful is the declaration part and constructor above, as for the following Writing Method and data disassembly, I think the buffer cleaning method needs to be improved, this is unacceptable because it takes 10 seconds for me to receive a kb image (the time for the entire logical process to complete and send data, so let's look at the following data processing methods. You can find your desired method based on your needs. Here we just provide ideas.

/// <Summary> /// cyclic queue /// </summary> /// <typeparam name = "T"> </typeparam> public class DynamicBuffer {/// <summary> // buffer size /// </summary> public int bufferSize {get; set ;}//< summary> /// communication object /// </summary> public Socket workSocket {get; set ;} /// <summary> /// buffer /// </summary> public byte [] Buffers {get; set ;} /// <summary> /// storage area /// </summary> public List <byte> sb; public Dynami CBuffer () {this. bufferSize = 1024*64; this. sb = new List <byte> (); this. buffers = new byte [bufferSize];} // <summary> // put the buffer data in the storage zone // </summary> public void WritBuffer () {int endPosition = 0; byte [] buffer; int len = 0; for (endPosition = this. buffers. length-1; endPosition> = 0; endPosition --) {// as many empty bytes \ 0 are found in the data, if (this. buffers [endPosition]! = (Byte) '\ 0') break;} len = endPosition + 1; // because it is the length rather than the position, + 1 buffer = new byte [len] here; array. copy (this. buffers, 0, buffer, 0, len); this. sb. addRange (buffer); this. buffers = new byte [bufferSize];} // returns the specified length of byet [] data, and clears the corresponding storage area public void GetAllData (out Dictionary <string, byte []> data) {int DataLength = 0; DataLength = GetAllAcceptMsg (out data); if (DataLength> 0) {ClearList (DataLength );}} // clear the sent content and empty package data in the storage area, so that the private void ClearList (int DataLength) {this. sb. removeRange (0, DataLength) ;}/// <summary> /// determines whether the storage area accepts the complete package and stores the complete package, disassembling /// </summary> /// <returns> length of valid data at a time </returns> private int GetAllAcceptMsg (out Dictionary <string, byte []> data) {int DataLength = 0; int contentLength = 0; int newlinePosition = 0; string title = string. empty; string arr_msg = string. empty; byte [] buffer = this. sb. toArray (); data = new Dictionary <string, byte []> (); try {newlinePosition = StaticHelp. search (buffer, Encoding. default. getBytes ("\ r \ n"), false); // find the position of the line feed if (newlinePosition> 0) {arr_msg = Encoding. UTF8.GetString (buffer); contentLength = Convert. toInt32 (CommonHelper. getStrByRegex (arr_msg, "Content-Length:", "\ r \ n"); int dataLen = buffer. length-newlinePosition; if (dataLen> = contentLength) {title = arr_msg.Split (new string [] {"\ r \ n"}, StringSplitOptions. none) [0] + "\ r \ n"; byte [] postData = new byte [contentLength]; if (contentLength> 0) Buffer. blockCopy (buffer, newlinePosition, postData, 0, contentLength); data. add (title, postData); DataLength = newlinePosition + contentLength ;}} else {DataLength = 0 ;}} catch (Exception ex) {LogHelper. writeLog (typeof (IpcServerDo), ex) ;}return DataLength ;}}

 

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.