C# implementation of asynchronous, synchronous, one to many, webapi and other network frameworks based on hslcommunication

Today, let's talk about how to use hslcommunication to implement a convenient network framework. Although I have written relevant articles before, they are scattered and there is no comprehensive comparison. Today's article will explain it in combination with some actual situations.

Before starting, let's introduce the official website of hslcommunication: http://www.hslcommunication.cn/

 

You can download and install in NuGet manager in Visual Studio, or directly enter the following instructions in NuGet console to install:

 

1 Install-Package HslCommunication

 

If you need Nuget installation tutorial: http://www.cnblogs.com/dathlin/p/7705014.html

 

For complete information and API introduction of components, please refer to: http://www.cnblogs.com/dathlin/p/7703805.html The usage restrictions of components and update logs are all in this page.

demo source code address of this library: https://github.com/dathlin/HslCommunication

 

Scenario 1:

I have a data server. The server will update the data regularly, and then all clients who need the data can obtain the data information at the same time and update the relevant interface. We call this mechanism publish subscribe mechanism. The client subscribes the data it needs to the server. When the server updates the data, it publishes the latest data to all subscribed clients.

This mode is especially suitable for the display of real-time data of some client interfaces. For example, I have a client interface to display the real-time data of the device. Only the server is qualified or conditional to access the device. Then it is particularly suitable to use publish and subscribe.

The most typical publish subscribe mode is MQTT protocol, and HSL supports version 3.1.1 of MQTT protocol. Let's develop a program now.

 

First create a server console program and a client winform program. The next step is to install the nuget component hslcommunication. Open nuget

 

Let's click to install the core network communication component.

 

We search this component, then check the installed item and click to install the component.

Then we write some code on the server side. Now we want to push from 0, 1, 2, 3, 4, 5 and 6. Let's define the name of A topic casually, "A", and then push it once A second. The program is very short

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HslCommunication;
using HslCommunication.MQTT;

namespace Server
{
	class Program
	{
		static void Main( string[] args )
		{
			MqttServer server = new MqttServer( );
			server.ServerStart( 1883 );
			int i = 0;
			while(true)
			{
				System.Threading.Thread.Sleep( 1000 );
				server.PublishTopicPayload( "A", Encoding.UTF8.GetBytes( i.ToString( ) ) );
				i++;
			}
		}
	}
}

We then put a label on the client interface to display the received data information.

 

We then start the network in the form startup method.

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using HslCommunication;
using HslCommunication.MQTT;

namespace WindowsFormsApp1
{
	public partial class Form1 : Form
	{
		public Form1( )
		{
			InitializeComponent( );
		}

		private void Form1_Load( object sender, EventArgs e )
		{
			client = new MqttClient( new MqttConnectionOptions( )
			{
				IpAddress = "127.0.0.1",
				Port = 1883,
			} );
			// Trigger when data is received
			client.OnMqttMessageReceived += Client_OnMqttMessageReceived;
			// The topic of the subscriber, which will be subscribed after the connection is successful
			client.OnClientConnected += m =>
			{
				m.SubscribeMessage( "A" );
			};
			client.ConnectServer( );


		}

		private void Client_OnMqttMessageReceived( string topic, byte[] payload )
		{
			// Switch back to the main thread to display text
			Invoke( new Action( ( ) =>
			 {
				 label1.Text = Encoding.UTF8.GetString( payload );
			 } ) );
		}

		private MqttClient client;
	}
}

  

Then start the server first. When we start the client, we can see that a number is updating.

 

Of course, this may not matter. If you open multiple clients at this time, for example, open eight clients.

 

You will find that all data is updated at the same time. There are more clients. At this time, a friend may ask, you only passed one data, ah, I have a lot of data in one interface, maybe dozens or hundreds. How

The core of this problem is how to compress all the data you need to transfer into a byte [] and then parse it into the data you need when it is displayed. This process is serialization and deserialization.

In fact, there is no standard answer. I give two ideas below.

The first idea is to use json technology to program the required data into a string, and then convert it to byte []. We assume that there are three label data to be displayed.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HslCommunication;
using HslCommunication.MQTT;
using Newtonsoft.Json.Linq;

namespace Server
{
	class Program
	{
		static void Main( string[] args )
		{
			MqttServer server = new MqttServer( );
			server.ServerStart( 1883 );
			int i = 0;
			while(true)
			{
				System.Threading.Thread.Sleep( 1000 );

				JObject json = new JObject( );
				json.Add( "Temperature 1", new JValue( i ) );
				json.Add( "Temperature 2", new JValue( i + 1 ) );
				json.Add( "Temperature 3", new JValue( i + 2 ) );

				server.PublishTopicPayload( "A", Encoding.UTF8.GetBytes( json.ToString( ) ) );
				i++;
			}
		}
	}
}  

We use the technology of json component, and we can start using it as long as using. Then we need to modify it on the client.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using HslCommunication;
using HslCommunication.MQTT;
using Newtonsoft.Json.Linq;

namespace WindowsFormsApp1
{
	public partial class Form1 : Form
	{
		public Form1( )
		{
			InitializeComponent( );
		}

		private void Form1_Load( object sender, EventArgs e )
		{
			client = new MqttClient( new MqttConnectionOptions( )
			{
				IpAddress = "127.0.0.1",
				Port = 1883,
			} );
			// Trigger when data is received
			client.OnMqttMessageReceived += Client_OnMqttMessageReceived;
			// The topic of the subscriber, which will be subscribed after the connection is successful
			client.OnClientConnected += m =>
			{
				m.SubscribeMessage( "A" );
			};
			client.ConnectServer( );


		}

		private void Client_OnMqttMessageReceived( string topic, byte[] payload )
		{
			// Switch back to the main thread to display text
			Invoke( new Action( ( ) =>
			 {
				 JObject json = JObject.Parse( Encoding.UTF8.GetString( payload ) );

				 label1.Text = json.Value<int>( "Temperature 1" ).ToString( );
				 label2.Text = json.Value<int>( "Temperature 2" ).ToString( );
				 label3.Text = json.Value<int>( "Temperature 3" ).ToString( );
			 } ) );
		}

		private MqttClient client;
	}
}  

You can compare it. The main thing is to modify the content of the display part,

 

 

Well, now you can send multiple data at the same time. Of course, if it's an array, it's OK. It's nothing more than json serialization and deserialization. The deeper you understand json components, you can realize more advanced functions.

Let's take another look at another xml technology. In fact, it is essentially the same as json. It encapsulates and parses data. Here I will post a key code, and the implementation depends on you.

Server side:

 

Client code:

 

We found that compression and parsing are just different, the ideas are the same, and there is almost no difference in performance. The above example shows the transmission of complex data. Let's take a look at another classic situation and how to deal with it.

 

In addition to form1, we also have a sub form form2, which also needs to display the information of a topic.

 

When we click the button on form1, form2 will be displayed. OK, now we have two topics, "A" and "B". Let's modify the content of the server

		static void Main( string[] args )
		{
			MqttServer server = new MqttServer( );
			server.ServerStart( 1883 );
			int i = 0;
			while(true)
			{
				System.Threading.Thread.Sleep( 1000 );

				XElement element = new XElement( "Data" );
				element.SetAttributeValue( "Temperature 1", i );
				element.SetAttributeValue( "Temperature 2", i + 1 );
				element.SetAttributeValue( "Temperature 3", i + 2 );

				server.PublishTopicPayload( "A", Encoding.UTF8.GetBytes( element.ToString( ) ) );

				server.PublishTopicPayload( "B", Encoding.UTF8.GetBytes( i.ToString( ) ) );
				i++;
			}
		}  

It mainly adds the data information of sending subject B.

The event of the button displaying form2 on the form1 form is as follows:

		private void button1_Click( object sender, EventArgs e )
		{
			using(Form2 form = new Form2( ))
			{
				form.ShowDialog( );
			}
		}

 

How should we write a subscription in form2.

  

using HslCommunication.MQTT;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
	public partial class Form2 : Form
	{
		public Form2( )
		{
			InitializeComponent( );
		}

		private void Form2_Load( object sender, EventArgs e )
		{
			client = new MqttClient( new MqttConnectionOptions( )
			{
				IpAddress = "127.0.0.1",
				Port = 1883,
			} );
			// Trigger when data is received
			client.OnMqttMessageReceived += Client_OnMqttMessageReceived;
			// The topic of the subscriber, which will be subscribed after the connection is successful
			client.OnClientConnected += m =>
			{
				m.SubscribeMessage( "B" );
			};
			client.ConnectServer( );

		}

		private void Client_OnMqttMessageReceived( string topic, byte[] payload )
		{
			// Switch back to the main thread to display text
			Invoke( new Action( ( ) =>
			{
				label1.Text = Encoding.UTF8.GetString( payload );
			} ) );
		}

		private MqttClient client;

		private void Form2_FormClosing( object sender, FormClosingEventArgs e )
		{
			client.ConnectClose( );
		}
	}
}  

In terms of writing, it is the same as form1, but there is a small detail to note. When the form2 form is closed, it needs to close the connection with the server, otherwise the network still connected in the background will lead to the destruction of the interface when refreshing the interface, and then send it to crash.

Generally speaking, it is necessary to instantiate another MqttClient object, and then someone will ask if I can use one MqttClient object for all interfaces, otherwise if I have more interfaces, I will instantiate a lot.

It's really not easy to solve this problem. It involves a concept, event binding and unbound operation. OK, let's take a look at how to realize this requirement. Let's modify the code of form1 first

		private void Client_OnMqttMessageReceived( string topic, byte[] payload )
		{
			// Switch back to the main thread to display text
			Invoke( new Action( ( ) =>
			 {
				 // My form1 only subscribes to A, so it should only respond to A.
				 if (topic == "A")
				 {
					 XElement element = XElement.Parse( Encoding.UTF8.GetString( payload ) );

					 label1.Text = element.Attribute( "Temperature 1" ).Value;
					 label2.Text = element.Attribute( "Temperature 2" ).Value;
					 label3.Text = element.Attribute( "Temperature 3" ).Value;
				 }
			 } ) );
		}  

There is A modification here. Before displaying the data, judge the topic. If it is A, display it again, regardless of others. Because we only use one MqttClient, when instantiating form2, we need to pass the client of form1 to form2.

Then, when form2 form initializes, you need to subscribe to B. when the form closes, you need to unsubscribe from B, and then unbind the bound events. Of course, when displaying the data of Topic B, we also need to judge topic B. The code is as follows:

using HslCommunication.MQTT;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
	public partial class Form2 : Form
	{
		public Form2( MqttClient client )
		{
			InitializeComponent( );
			this.client = client;
		}

		private void Form2_Load( object sender, EventArgs e )
		{
			// Trigger when data is received
			client.OnMqttMessageReceived += Client_OnMqttMessageReceived;
			// The topic of the subscriber, which will be subscribed after the connection is successful
			client.SubscribeMessage( "B" );

		}

		private void Client_OnMqttMessageReceived( string topic, byte[] payload )
		{
			// Switch back to the main thread to display text
			Invoke( new Action( ( ) =>
			{
				if (topic == "B")
				{
					label1.Text = Encoding.UTF8.GetString( payload );
				}
			} ) );
		}

		private MqttClient client;

		private void Form2_FormClosing( object sender, FormClosingEventArgs e )
		{
			client.UnSubscribeMessage( "B" );
			client.OnMqttMessageReceived -= Client_OnMqttMessageReceived;
		}
	}
}

  

For more advanced functions of MQTT server, such as adding ID filtering, user name and password verification, and other contents, you can also post the following posts:

https://www.cnblogs.com/dathlin/p/12312952.html

You can realize some very advanced functions by yourself. There will be no more details here.

The client can also enter id, user name and password to realize an advanced operation and the contents of the log. For detailed description of the client, please refer to the following:

https://www.cnblogs.com/dathlin/p/11631894.html

 

 

 

 

Scenario 2:

 

I have a server program that provides services to other clients. The client sends data to the server, the server processes it, and then returns the results to the client. The emphasis is on a question and answer mechanism, the client asks and the server answers.

In this case, at the same time, the client can also be used to upload and download data. Of course, when the client connects to the server, it is best to mark the id information of a client and enter the user name and password for verification.

 

All this hslcommunication has been supported. And it has been integrated into the MQTT server. Let me take the above project as an example. I have a requirement now. I have two buttons in the client to control the real-time data released by the MQTT of the server.

At this time, someone may ask, mqtt client releases a data, mqtt server intercepts it and judges it. Yes, it is. However, both the server and the client have a lot of trouble in programming, and the client needs to feed back the results. Is the operation successful,

 

Let's talk about the convenient implementation. MQTT server can receive the request to synchronize the network. You need to judge the protocol type of the next session.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HslCommunication;
using HslCommunication.MQTT;
using Newtonsoft.Json.Linq;
using System.Xml.Linq;

namespace Server
{
	class Program
	{
		static void Main( string[] args )
		{
			MqttServer server = new MqttServer( );
			server.ServerStart( 1883 );
			bool isPublish = true;               // Flag whether to publish data.

			server.OnClientApplicationMessageReceive += ( MqttSession session, MqttClientApplicationMessage message ) =>
			{
				if(session.Protocol == "HUSL")
				{
					// Process the synchronization network
					if(message.Topic == "STOP")
					{
						isPublish = false;      // Stop publishing data
						server.PublishTopicPayload( session, "SUCCESS", null );   // Returns the description of the successful operation
					}
					else if(message.Topic == "CONTINUE")
					{
						isPublish = true;       // Continue publishing data
						server.PublishTopicPayload( session, "SUCCESS", null );   // Returns the description of the successful operation
					}
					else
					{
						server.PublishTopicPayload( session, message.Topic, message.Payload );   // Other commands are not processed and the original data is returned
					}
				}
			};

			int i = 0;
			while(true)
			{
				System.Threading.Thread.Sleep( 1000 );

				if (isPublish)
				{
					XElement element = new XElement( "Data" );
					element.SetAttributeValue( "Temperature 1", i );
					element.SetAttributeValue( "Temperature 2", i + 1 );
					element.SetAttributeValue( "Temperature 3", i + 2 );

					server.PublishTopicPayload( "A", Encoding.UTF8.GetBytes( element.ToString( ) ) );

					server.PublishTopicPayload( "B", Encoding.UTF8.GetBytes( i.ToString( ) ) );
					i++;
				}
			}
		}

	}
}

  

We use isPublish to control the publication of data. The attribute of bool is determined by the button on the client. How to write the two buttons on the client

 

We use these two buttons to control the bool variable of the server. The code is relatively simple.

		private void button2_Click( object sender, EventArgs e )
		{
			// Stop publishing
			MqttSyncClient syncClient = new MqttSyncClient( "127.0.0.1", 1883 );
			OperateResult<string, string> read = syncClient.ReadString( "STOP", null );
			if (read.IsSuccess)
			{
				if(read.Content1 == "SUCCESS")
				{
					MessageBox.Show( "Notification closed successfully!" );
				}
				else
				{
					MessageBox.Show( "Notification shutdown failed:" + read.Content1 );
				}
			}
			else
			{
				MessageBox.Show( "Notification shutdown failed:" + read.Message );
			}
		}

		private void button3_Click( object sender, EventArgs e )
		{
			// Continue publishing
			MqttSyncClient syncClient = new MqttSyncClient( "127.0.0.1", 1883 );
			OperateResult<string, string> read = syncClient.ReadString( "CONTINUE", null );
			if (read.IsSuccess)
			{
				if (read.Content1 == "SUCCESS")
				{
					MessageBox.Show( "Notification closed successfully!" );
				}
				else
				{
					MessageBox.Show( "Notification shutdown failed:" + read.Content1 );
				}
			}
			else
			{
				MessageBox.Show( "Notification shutdown failed:" + read.Message );
			}
		}  

The code here performs some verification. When the received string is SUCCESS, it represents true SUCCESS! Let's verify the effect.

 

After clicking stop publishing, the server will stop publishing immediately. Click continue publishing, and the server will continue publishing. Very satisfied with the demonstration effect.

 

Some of the partners here may have questions. Why should the client judge whether the server returns a SUCCESS string? As long as the server returns normally, isn't it all this string?

Generally speaking, yes, but there is a more advanced usage here. Let's assume that in this scenario, the permission level of these two buttons is very high. Only the specified account can operate, and other accounts cannot operate. For example, an account named "hsl"

We can modify the server code:

 

At this point, let's start the client again to see the effect.

 

We not only return the failure result, but also return the failure reason, which is convenient for the client to view. Here, Lao tie may say that if the account of my client software is not hsl, the button will be disabled. This is also an idea. However, in most cases, the client is considered unsafe, and the server needs security checks.

Now modify our client program and set a user name and password.

 

At this time, you have permission to operate. If you need to verify the user name and password on the server, modify the authentication connection of the server. For details, please refer to the blog post on the server.

https://www.cnblogs.com/dathlin/p/12312952.html

 

 

At this time, some partners may have questions. I don't seem to see the connection operation of your synchronous access client. After instantiation, I can read and write directly.

The above code mechanism is indeed like this. The principle is short connection. When you read, connect the data. When you finish reading, disconnect the connection. If I want to make a long connection, this client object will be used in many different forms. I can only instantiate one. So that's how you write the code.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
using HslCommunication;
using HslCommunication.MQTT;
using Newtonsoft.Json.Linq;

namespace WindowsFormsApp1
{
	public partial class Form1 : Form
	{
		public Form1( )
		{
			InitializeComponent( );
		}

		private void Form1_Load( object sender, EventArgs e )
		{
			client = new MqttClient( new MqttConnectionOptions( )
			{
				IpAddress = "127.0.0.1",
				Port = 1883,
			} );
			// Trigger when data is received
			client.OnMqttMessageReceived += Client_OnMqttMessageReceived;
			// The topic of the subscriber, which will be subscribed after the connection is successful
			client.OnClientConnected += m =>
			{
				m.SubscribeMessage( "A" );
			};
			client.ConnectServer( );

			// Instantiation of synchronous network
			syncClient = new MqttSyncClient( new MqttConnectionOptions( )
			{
				IpAddress = "127.0.0.1",
				Port = 1883,
				Credentials = new MqttCredential( "hsl", "123456" )
			} );
			syncClient.SetPersistentConnection( ); // Set as long connection
		}

		private void Client_OnMqttMessageReceived( string topic, byte[] payload )
		{
			// Switch back to the main thread to display text
			Invoke( new Action( ( ) =>
			 {
				 // My form1 only subscribes to A, so it should only respond to A.
				 if (topic == "A")
				 {
					 XElement element = XElement.Parse( Encoding.UTF8.GetString( payload ) );

					 label1.Text = element.Attribute( "Temperature 1" ).Value;
					 label2.Text = element.Attribute( "Temperature 2" ).Value;
					 label3.Text = element.Attribute( "Temperature 3" ).Value;
				 }
			 } ) );
		}

		private MqttClient client;

		private void button1_Click( object sender, EventArgs e )
		{
			using(Form2 form = new Form2( client ))
			{
				form.ShowDialog( );
			}
		}

		private MqttSyncClient syncClient;

		private void button2_Click( object sender, EventArgs e )
		{
			// Stop publishing
			OperateResult<string, string> read = syncClient.ReadString( "STOP", null );
			if (read.IsSuccess)
			{
				if(read.Content1 == "SUCCESS")
				{
					MessageBox.Show( "Notification closed successfully!" );
				}
				else
				{
					MessageBox.Show( "Notification shutdown failed:" + read.Content1 );
				}
			}
			else
			{
				MessageBox.Show( "Notification shutdown failed:" + read.Message );
			}
		}

		private void button3_Click( object sender, EventArgs e )
		{
			// Continue publishing
			OperateResult<string, string> read = syncClient.ReadString( "CONTINUE", null );
			if (read.IsSuccess)
			{
				if (read.Content1 == "SUCCESS")
				{
					MessageBox.Show( "Notification closed successfully!" );
				}
				else
				{
					MessageBox.Show( "Notification shutdown failed:" + read.Content1 );
				}
			}
			else
			{
				MessageBox.Show( "Notification shutdown failed:" + read.Message );
			}
		}
	}
}  

After instantiating the syncClient, we can only see one long connection. If multiple forms also need to use the syncClient object, just pass the object syncClient to other forms. The usage is the same as the code of form1.

using HslCommunication;
using HslCommunication.MQTT;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
	public partial class Form2 : Form
	{
		public Form2( MqttClient client , MqttSyncClient syncClient )
		{
			InitializeComponent( );
			this.client = client;
			this.syncClient = syncClient;
		}

		private void Form2_Load( object sender, EventArgs e )
		{
			// Trigger when data is received
			client.OnMqttMessageReceived += Client_OnMqttMessageReceived;
			// The topic of the subscriber, which will be subscribed after the connection is successful
			client.SubscribeMessage( "B" );

		}

		private void Client_OnMqttMessageReceived( string topic, byte[] payload )
		{
			// Switch back to the main thread to display text
			Invoke( new Action( ( ) =>
			{
				if (topic == "B")
				{
					label1.Text = Encoding.UTF8.GetString( payload );
				}
			} ) );
		}

		private MqttClient client;
		private MqttSyncClient syncClient;


		private void Form2_FormClosing( object sender, FormClosingEventArgs e )
		{
			client.UnSubscribeMessage( "B" );
			client.OnMqttMessageReceived -= Client_OnMqttMessageReceived;
		}

		private void button2_Click( object sender, EventArgs e )
		{
			// Stop publishing
			OperateResult<string, string> read = syncClient.ReadString( "STOP", null );
			if (read.IsSuccess)
			{
				if (read.Content1 == "SUCCESS")
				{
					MessageBox.Show( "Notification closed successfully!" );
				}
				else
				{
					MessageBox.Show( "Notification shutdown failed:" + read.Content1 );
				}
			}
			else
			{
				MessageBox.Show( "Notification shutdown failed:" + read.Message );
			}
		}

		private void button3_Click( object sender, EventArgs e )
		{
			// Continue publishing
			OperateResult<string, string> read = syncClient.ReadString( "CONTINUE", null );
			if (read.IsSuccess)
			{
				if (read.Content1 == "SUCCESS")
				{
					MessageBox.Show( "Notification closed successfully!" );
				}
				else
				{
					MessageBox.Show( "Notification shutdown failed:" + read.Content1 );
				}
			}
			else
			{
				MessageBox.Show( "Notification shutdown failed:" + read.Message );
			}
		}
	}
}  

After the code is written in this way, our form2 also has the function of notifying off. In form1, we only need to pass the client object to form2.

 

 

 

 

By summarizing the above code, let's take a closer look at the core of the server code,

 

The function of this topic is similar to a command code. The server processes different data and realizes different functions according to the information of the topic. Some netizens may ask, I can interact with the above commands. Now I want to upload and download files through this. Can I do it?

The answer is also OK. For example, I implement the file download function. This function is relatively common. My client may need to request the server to download a file. For example, download a word document.

 

Here I put a word document in the current DEBUG directory of the server.

 

 

I'll write the code on the server side first. At this time, I need to continue adding a topic. Judge whether we set the command to download the file. Is it "DownloadFile"

 

This part of the code is to send the word document in the current debug directory to the other party. Of course, you can also specify the absolute path. Here, for flexibility, because the server program may not be deployed on my computer, but also on other computers.

 

At the client, we add a button to download the file, which is also saved to the current directory of the client, and then notify word software to open it.

 

The code of clicking the button is as follows:

 

Here is the current directory saved in the client. Let's run it;

 

It is found that the file is directly opened. Let's see what changes have taken place in the directory of the client?

 

 

Did download a file. Let's think again. When the server reads the file again, what if the file is occupied? What if the reading fails? What if the file doesn't exist? Is the server crashing? Of course not. We can still enter the returned Topic for processing.

If we return a string with whether the operation is successful or not, we can use the class provided by hsl. Look at the code demonstration.

 

Here we choose to return the wrong interface to the client in case of reading failure. The code of the client parsing part also needs to be changed slightly

 

Then we run the server and client and find that there is no problem. We can download the file and open it.

At this time, let's try the unexpected situation. We delete the files in the debug directory of the server to see how the abnormal situation will be displayed.

 

Well, we have deleted it. Let's see what happens when the client clicks download again.

 

 

At this time, the client can friendly remind the wrong content, whether the file does not exist or is occupied, and so on. There is another problem to consider here. If the file I download reaches 10M, and my server is deployed on another computer in the LAN, it will take 10 seconds for my client to download the file. The above code will cause the interface to freeze for 10 minutes. In order not to block the UI interface, we need to use the background thread to download. Here is an example of async Await technology is a real background download.

 

You only need to change two places to realize the asynchronous download in the background. If your client is net35, you can only use the thread class to implement the background thread.

At this time, a small partner may have said that I need to download a file for 10 seconds, maybe 1 minute, maybe longer. I also want to know the download progress now, otherwise users don't know how long to wait, and the experience is not good.

It's okay, meet you. We can realize the download progress by modifying the code of the client.

 

We add a progress bar control to display the progress of downloading files. We update the progress when downloading files.

 

In the download method, we can pass in a download progress delegate. Similarly, the upload progress is the same. You can take a closer look

 syncClient. The meaning of the parameters of the readasync method and their related uses.

 

The last detail of this part is that the data received by the client is received in the byte [] array, which is actually memory. If your file is large, a G or even larger, it takes up a lot of memory for the client, and it is not easy to manage multiple files on the server. If you need to manage files, you can refer to another blog:

hsl has a special file server to handle the upload and download of high concurrency and large files. It also supports some information management of files.

https://www.cnblogs.com/dathlin/p/7746113.html

 

Among them, the java version and python version are supported through the request of the network, that is, both java and python can request data from the server of C#.

 

 

 

 

 

 

Scenario 3:

I have a server program that provides services for other web pages, languages, or front-end interfaces. Or my system needs to provide external services.

So using webapi is a common way, but how do you usually create a webapi? Create a new ASP Net MVC? Or grpc?

If it is a complex webapi, there is no problem to create it with a framework, but I just want to create a simple webapi and provide several interfaces. It is best to integrate it directly into my winform, wpf or console program. There is no need to open more software, which is more troublesome.

 

This can also be achieved.

 

 

This allows you to start a server. We use postman to test

 

Similarly, GETB is the same. I won't repeat it here. For detailed blog, please refer to the following address:

 

https://www.cnblogs.com/dathlin/p/12335933.html

 

 

 

Scenario 4, I want to push the data to the web page for real-time update.

 

Refer to the blog below.

 

https://www.cnblogs.com/dathlin/p/12303098.html

 

Posted by maxx99 on Wed, 25 May 2022 23:42:24 +0300