C# Implementation of Asynchronous Socket Communication Programming (2)

In the first article, a console application with asynchronous communication has been implemented. The server can connect to multiple clients and send messages.

In this article, two functions will be implemented:
1. Realize the client side of the GUI, which can communicate with the server in two directions
2. Realize the length verification of socket communication

GUI implementation of the client

In the console program, the client can not easily send messages to the server, use C# to write the user interface, realize communication and print messages.
write picture description here
In GUI socket programming, asynchronous programming or multi-threaded programming must be used, otherwise the main thread cannot refresh the interface when communicating.

Sending a message
Clicking the send button will send the content of the text box, which is not continuous, and does not require asynchronous programming.

      public bool sendMsg(string message)
       {
           try
           {
               msg = message;
               sendBuffer = Encoding.Unicode.GetBytes(message);
               cSocket.Send(sendBuffer, sendBuffer.Length, 0);
           }
           catch (Exception e)
           {
               msg = "send exception: " + e.Message;
           }            
           return true;
       }

achieve effect
write picture description here

On the left is the server, on the right is the client. Click the button to connect to the server and start receiving the information sent by the server regularly. Enter information in the text box and click the button to send it to the server.

length check

When the TCP/IP protocol sends data, it is not strictly according to the programming written one by one. In order to improve the efficiency, the following changes will be made:
1. When the data length is short, the data will be accumulated to a certain length. For sending, several pieces of data may be received at one time;
2. When the length of the data is too long, the data will be split into several pieces for transmission.

But the TCP/IP protocol guarantees that these data arrive in order and will not be lost, which is reliable.

Solution
Therefore, in order to correctly parse the received information, we must perform certain packaging operations on the data to correctly assemble the received information.
1. Add a length in front of each data and mark it with a special symbol. Here , use [and Guaranteed not to appear the characters we marked, such as base64 encoding.]

coding

        public string createStr()
        {
            string s = "";
            if (sr.Peek()>=0)       // 判断结尾
            {
                s = sr.ReadLine();
                // 进行base64编码
                byte[] b = Encoding.Unicode.GetBytes(s);
                s = Convert.ToBase64String(b);
                s = "[" + s.Length + "]" + s;
            }                        
            return s;
        }

length check

Length verification uses the tag field to verify
1. If the previous one has been parsed, search []to obtain the length, and then perform assembly
2. If the previous one has not been parsed, perform assembly search according to the missing length

The writing here is not very perfect, and some situations will cause problems:
1. For example, when the identification field is divided into two parts, the following code cannot be parsed

        private bool complete;  // 之前解析是否完成
        private int strLength;  // 字符串长度
        private string unStr;   // 记录已经累计的长度
        public bool writeToFile(string s)
        {
            sw_o.WriteLine(s);
            sw_o.Flush();
            int idx1, idx2;
            try
            {               
                if(complete)    // 上一轮已经查找完毕
                {
                    idx1 = s.IndexOf('[');
                    idx2 = s.IndexOf(']');
                    while(idx1!=-1)  //能够找到一个标识符
                    {
                        // 获取长度
                        strLength = int.Parse(s.Substring(idx1 + 1, idx2 - idx1 - 1));
                        Console.WriteLine(strLength);
                        if (s.Length - idx2 - 1 < strLength)     // 这一个段已经不够使用
                        {
                            unStr = s.Substring(idx2 + 1, s.Length - idx2 - 1);
                            strLength -= (s.Length - idx2 - 1);
                            complete = false;
                            break;
                        }
                        else if (s.Length - idx2 - 1 == strLength)  // 刚好够用
                        {
                            unStr = s.Substring(idx2 + 1, strLength);
                            string str = decoderBase64(unStr);
                            writeStr(str);
                            Console.WriteLine("finished1: " + str);
                            complete = true;
                            break;
                        }
                        else
                        {
                            string str = s.Substring(idx2 + 1, strLength); // 写入一个完整字符串
                            str = decoderBase64(str);
                            writeStr(str);
                            Console.WriteLine("finished2: " + str);
                            // 截取新的字符串进行重复操作
                            s = s.Substring(idx2 + strLength + 1, s.Length - idx2 - strLength - 1);
                            idx1 = s.IndexOf('[');
                            idx2 = s.IndexOf(']');
                        }                                           
                    }
                }
                else
                {
                    if(s.Length<strLength)      // 不够使用
                    {
                        strLength -= s.Length;
                        unStr += s;
                        complete = false;
                    }
                    else if(s.Length == strLength)      // 刚好完全
                    {
                        complete = true;
                        unStr += s;
                        string str = decoderBase64(unStr);
                        writeStr(str);
                        Console.WriteLine("finished3: "+str);
                    }
                    else
                    {
                        idx1 = s.IndexOf('[');
                        unStr += s.Substring(0, idx1);      // 上次遗留的进行完全
                        string str = decoderBase64(unStr);
                        writeStr(str);
                        idx2 = s.IndexOf(']');
                        while(idx1 !=-1)
                        {
                            // 获取长度
                            strLength = int.Parse(s.Substring(idx1 + 1, idx2 - idx1 - 1));
                            Console.WriteLine(strLength);
                            if (s.Length - idx2 - 1 < strLength)     // 这一个段已经不够使用
                            {
                                unStr = s.Substring(idx2 + 1, s.Length - idx2 - 1);
                                strLength -= (s.Length - idx2 - 1);
                                complete = false;
                                break;
                            }
                            else if (s.Length - idx2 - 1 == strLength)  // 刚好够用
                            {
                                unStr = s.Substring(idx2 + 1, strLength);
                                str = decoderBase64(unStr);
                                writeStr(str);
                                Console.WriteLine("finished4: " + str);
                                complete = true;
                                break;
                            }
                            else
                            {
                                str = s.Substring(idx2 + 1, strLength); // 写入一个完整字符串
                                str = decoderBase64(str);
                                writeStr(str);
                                Console.WriteLine("finished5: " + str);
                                // 截取新的字符串进行重复操作
                                s = s.Substring(idx2 + strLength + 1, s.Length - idx2 - strLength - 1);
                                idx1 = s.IndexOf('[');
                                idx2 = s.IndexOf(']');
                            }                               
                        }
                    }
                }                       
            }
            catch(Exception e)
            {
                Console.WriteLine("writefile Exception: "+e.Message);
            }
            return true;

        }

achieve effect

write picture description here
The left side is the assembled text, and the right side is the actual received base64encoded data, which is automatically split and merged by the TCP/IP protocol, and the actual sent data. Correct assembly can be performed for this case.

Welcome to add more perfect verification~

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325766619&siteId=291194637