Use a GHI Cobra WiFi and NETMF 4.3, we are trying to bind a new Socket to a local endpoint. The 10022 error code indicates an invalid argument. From the docs:
The argument that we are passing is 192.168.1.202:12000.
[ul]Is our argument invalid? If so, how can we make it valid?
If not, is the state of our socket invalid? If so, how can we make it valid?[/ul]
Here is our source code.
const int internalPort = 12000;
const string internalIPAddress = "192.168.1.202";
var localEndPoint = new IPEndPoint(IPAddress.Parse(internalIPAddress), internalPort);
var serverSocket = new Socket(
AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
serverSocket.Bind(localEndPoint);
The code is running on a single board computer with a wireless network adapter. The adapter has already acquired the internalIPAddress that we’re using in the code.
[title]What we have tried[/title]
We have used IPAddress.Any when creating the local endpoint. This Binds successfully but throws at serverSocket.Accept() with ErrorCode = 10050, which indicates that the network is down.
We have tried delaying the bind for three seconds and retrying. This does not help. It still throws.
for (var i = 0; i < maxFailedBindAttempts; ++i)
{
try
{
// Sleep before calling Bind() to prevent
// SocketException ErrorCode = 10022
Thread.Sleep(millisecondSocketBindDelay);
serverSocket.Bind(localEndPoint);
// If we're hear the Bind succeeded. Stop looping.
break;
}
catch (Exception ex)
{
_logger.Write(ex.ToString());
if (i == maxFailedBindAttempts)
{
// rethrow the exception
throw;
}
}
}
We have also looked on the GHI Forum for other posts containing ErrorCode 10022.
From a quick read-through I didn’t spot anything obviously wrong. Can you provide a complete minimal program.cs that demonstrates the failure so that we can see how you are creating the network? Then we can try it on our hardware too.
@ mcalsyn - It is working! Thank you for encouraging the minimal program. The problem was that we were calling Bind() on the Socket before the WiFi was available.
The fix was to put the socket connection here:
NetworkChange.NetworkAvailabilityChanged += (sender, args) =>
{
("NetworkAvailabilityChanged. IsAvailable is now " + args.IsAvailable).Dump();
if (!args.IsAvailable) return;
// bind here.
};
Here is the hardware stack:
[ul]G120 Fez Cobra II WiFi
Loader version 4.3.4.0
Firmware version 4.3.6.0[/ul]
Here is the full source code.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using GHI.Networking;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using Microsoft.SPOT.Net.NetworkInformation;
namespace G120.SocketServer
{
public class Program
{
private const int Port = 12000;
private const string IpAddress = "192.168.1.115";
private const string SubnetMask = "255.255.255.0";
private const string GatewayAddress = "192.168.1.1";
private const string Bigfont = "BigFont";
private const string Nutbutter3 = "NutButter3";
public static void Main()
{
var wiFiRs9110 = new WiFiRS9110(
SPI.SPI_module.SPI2,
GHI.Pins.G120.P1_10,
GHI.Pins.G120.P2_11,
GHI.Pins.G120.P1_9, 4000);
wiFiRs9110.Open(); // what does this do?
wiFiRs9110.EnableStaticIP(IpAddress, SubnetMask, GatewayAddress);
ConnectWiFi(wiFiRs9110, Bigfont, Nutbutter3);
NetworkChange.NetworkAvailabilityChanged += (sender, args) =>
{
("NetworkAvailabilityChanged. IsAvailable is now " + args.IsAvailable).Dump();
if (!args.IsAvailable) return;
var threadStart = new ThreadStart(() => ConnectSocket(IpAddress, Port));
var thread = new Thread(threadStart);
thread.Start();
};
try
{
var threadStart = new ThreadStart(() => ConnectSocket(IpAddress, Port));
var thread = new Thread(threadStart);
thread.Start();
}
catch (Exception)
{
("We expect this to throw because the WiFi is not yet connected.").Dump();
}
// wait
var i = 0;
while (true)
{
Thread.Sleep(5000);
("Waiting count " + i++).Dump();
wiFiRs9110.Dump();
}
}
private static void ConnectWiFi(WiFiRS9110 wifiRs9110, string ssid, string password)
{
const int millisecondsTimeout = 1000;
var targetGateway = new WiFiRS9110.NetworkParameters[0];
while (targetGateway.Length == 0)
{
targetGateway = wifiRs9110.Scan(ssid);
Thread.Sleep(millisecondsTimeout);
}
wifiRs9110.Join(ssid, password);
}
private static void ConnectSocket(string ipAddress, int port)
{
const int socketBacklog = 25;
var localEndPoint = new IPEndPoint(IPAddress.Parse(ipAddress), port);
var serverSocket = new Socket(
AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
serverSocket.Bind(localEndPoint);
serverSocket.Listen(socketBacklog);
("#####").Dump();
("#####").Dump();
("#####").Dump();
("Socket connection succeeded!").Dump();
("Navigate to " + ipAddress + ":" + port + " in your web browser.").Dump();
("#####").Dump();
("#####").Dump();
("#####").Dump();
while (true)
{
// Wait for an incoming connection; queue it when it arrives.
// Accept blocks until a connection arrives.
// See also bit.ly/1S54gul
using (var clientSocket = serverSocket.Accept())
{
clientSocket.Okay("It works.");
}
}
}
}
public static class Extensions
{
public static void Dump(this NetworkInterface networkInterface)
{
var builder = new StringBuilder();
builder.AppendLine("NetworkInterface");
foreach (var dns in networkInterface.DnsAddresses)
{
builder.AppendLine("DnsAddress: " + dns);
}
builder.AppendLine("GatewayAddress:" + networkInterface.GatewayAddress);
builder.AppendLine("IPAddress:" + networkInterface.IPAddress);
builder.AppendLine("IsDhcpEnabled:" + networkInterface.IsDhcpEnabled);
builder.AppendLine("IsDynamicDnsEnabled:" + networkInterface.IsDynamicDnsEnabled);
builder.AppendLine("NetworkInterfaceType:" + networkInterface.NetworkInterfaceType);
builder.AppendLine("PhysicalAddress:" + ByteArrayToHex(networkInterface.PhysicalAddress, ":"));
builder.AppendLine("SubnetMask:" + networkInterface.SubnetMask);
builder.ToString().Dump();
}
public static void Dump(this WiFiRS9110 wiFiRs9110)
{
var builder = new StringBuilder();
builder.AppendLine("WiFiRS9110");
wiFiRs9110.NetworkInterface.Dump();
builder.AppendLine("LinkConnected:" + wiFiRs9110.LinkConnected);
builder.AppendLine("ActiveNetwork:" + wiFiRs9110.ActiveNetwork);
builder.AppendLine("NetworkIsAvailable:" + wiFiRs9110.NetworkIsAvailable);
builder.AppendLine("Opened:" + wiFiRs9110.Opened);
builder.ToString().Dump();
}
public static void Dump(this string output)
{
Debug.Print(output);
}
public static string ByteArrayToHex(this byte[] byteArray, string separator)
{
// even though it is in the NETMF System namespace,
// BitConverter.ToString(byteArray) does NOT work on Cobra boards.
var macBuilder = new StringBuilder(byteArray.Length * 2);
for (var i = 0; i < byteArray.Length; ++i)
{
var hex = byteArray[i].ToString("X2");
if (i != 0)
{
macBuilder.Append(separator);
}
macBuilder.Append(hex);
}
return macBuilder.ToString();
}
public static void Okay(this Socket clientSocket, string message)
{
const string crlf = "\r\n";
var builder = new StringBuilder();
builder.Append("HTTP/1.1 200 OK");
builder.Append(crlf);
builder.Append("Connection: close");
builder.Append(crlf);
builder.Append(crlf);
builder.Append(message);
builder.Append(crlf);
builder.Append(crlf);
var bytes = Encoding.UTF8.GetBytes(builder.ToString());
clientSocket.Send(bytes);
}
}
}
I will try to run this code in the next 12-24 hours, but first thing I notice (and should have noticed before) is that you are binding to a specific IP address. Try IPAddress.Any instead of the specific address. Let me know if that works for you. I’ll dig out a matching hardware setup unless I hear back from you that you’ve had success.
On most Berkeley-style socket stacks (Unix, Linux, Windows), using a specific address for bind() will cause your socket to bind ONLY on the interface that hosts that IP address. This is important if you machine has multiple IP-capable interfaces (for example, wireless, ethernet and maybe bluetooth all at the same time, or multiple ethernet cards). Most non-trivial OSs have multiple interfaces, so specifying an address means that you only listen on one of them.
Now on netmf (an lwip-based stack) a lot of that fancy code is left out. My theory is that it just can’t handle address-specific bindings. It will take you far less code to try out than it took me to type this Give it a shot - I think it may fix your issue, and it saves you some double-bookeeping in your code.
@ mcalsyn - Yo. Thank you for the detailed explanation. I appreciate that. Fact is, the code sample that I posted was working already and it also works with IPAddress.Any as you suggested. Sorry that it wasn’t clear that the code I posted worked. Thank you again for your help.