Solving Sharepoint ClientContext Socket Exception in C#
How to prevent SocketException 'Address Already in Use' when using Sharepoint CSOM
So, you’ve been writing a Sharepoint client application and it’s running just fine.
After several weeks or months, you noticed some errors were showing up.
If you see a lot of SocketException
error messages like following snippet, then this article is for you.
In my previous article about Sharepoint CSOM Socket Exception, I wrote about on how to solve this issue by editing some registry values. I did it and worked beautifully, but only for several days.
So, I did some digging the server to see why on earth this exception still happening.
To do that, you can open Command Prompt and use netstat
command.
Open the generated netstat.txt
and take a look at it.
In my case I’ve seen a lot of ports being used or in TIME_WAIT
state.
They are the Sharepoint client application itself, dns.exe
, and mostly WindowsAzureGuestAgent.exe
.
Now I don’t want to start an argument what cause this and which process start this. I tried to investigate that, but I didn’t find satisfying answer.
But then I got an idea.
I found out about how Sharepoint PnP extends its ClientContext
class with ExcuteQueryRetry
.
This is being used to prevent Sharepoint Online throttling.
But with the same idea, it can be used to prevent SocketException
as well.
Simplified Scenario
Now before we make the solution, let’s make a simple scenario. You received data from somewhere, for example external REST API, and store it in memory. This series of data length is unknown, so you decided to cache it 100 data at a time and save it to Sharepoint list. Because you don’t know how the series of data will end, this will happened in multiple batches.
To make it simple, let’s create a function to create 100 items in multiple batches. You need to make a new Console project first. Here is an example on how to create 100 new list items in one execution.
Normally, we’re using a ClientContext
object to send it to Sharepoint Server and dispose it when it’s done.
Now let’s create a simulation for sending multiple data to Sharepoint Server in our Main
function.
We’re going to use 256 loop for starter.
If you don’t received an Exception using this loop, try double it or more.
Now let’s try execute it.
You probably will get SocketException
quickly if you run it in the same machine with your Sharepoint Server.
Solution
What we’re looking to solve this matter is when we received SocketException
with SocketError.AddressAlreadyInUse
value.
We can do that by seeing the InnerException
of WebException
object.
Here is the raw picture of the code. Normally, when this happened, we need to retry the process again.
As I mentioned earlier, I got inspiration from Sharepoint PnP on how they prevent throttling by retrying the execution of ExecuteQuery
.
So I make a helper class that will retry the process (not just ExecuteQuery
, but the whole block after CLientContext
object created) when we received AddressAlreadyInUse
.
You can see following code.
What this code do is to retry the whole block of Sharepoint server-related process when a SocketException
happened.
By default it’ll retry 10 times at max.
Before every retry, it’ll wait for 500 ms for the first retry, and double it on second retry, and so on.
Obviously, you can change its value just like ExecuteQueryRetry
.
Let’s Test It
Let’s make a new function based on ExecuteNormally
and change it using our helper class SafeSocketProcess.Execute
.
This is how to use it.
Change your Main
function and use ExecuteSafely
instead.
Now let’s try running this.
You probably won’t receive this SocketException
anymore.
In my case, I only see 7 retries happened at max.
If you still see the Exception
, you can try increase the value of retryCount
and delay
like following example.
Summary
That’s the simplest method to solve this problem. Hopefully after you implement it, you won’t see any problems anymore.
I know that this method is not highly optimized, you can extend it yourself, for example by adding async
and await
.
Thanks for reading. You can fork or download the demo project.
References
- Windows Sockets Error Codes | Microsoft Docs
- PnP-Sites-Core/ClientContextExtensions.cs at master · SharePoint/PnP-Sites-Core · GitHub