How do I test my socket exception handling code? - c#

I have the following code:
try
{
mainSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, serverPort);
mainSocket.Bind(ipEndPoint);
mainSocket.Listen(MAX_CONNECTIONS);
mainSocket.BeginAccept(new AsyncCallback(serverEndAccept), mainSocket);
OnNetworkEvents eventArgs =
new OnNetworkEvents(true, "Listening for Connection");
OnUpdateNetworkStatusMessage(this, eventArgs);
}
catch (SocketException e)
{
// add code here
}
catch (ObjectDisposedException e)
{
// add code here
}
How do I test the code's SocketException given the server is listening successfully all of the time?

Do not test against the live network. Mock the socket and test against a mock that throws a SocketException.

you could add something like this for testing:
#if (UNITTEST)
throw new SocketException();
#endif
Then in your unit test compile just define that variable.
Otherwise do something to force an exception. Like have an invalid config setting that won't let it connect for use with your unit test code.

Unplug your network cable or shut off your wireless (assuming you're testing against a remote server).

Manually throw a SocketException from inside your try block.
Like
throw new SocketException("Testing");

Related

error opening socket in program on network location

I develop software from a network location. Until recently this works without problems. But after the last Windows 10 update (may 2018) something changed. Programs still run from this location but when I try to open a socket I get the error 'invalid argument (10022)'. The code is so basic:
Socket s;
s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Running it from a local disk doesn't produce the error.
A sample program with with a single button will generate this error condition.
private void button1_Click(object sender, EventArgs e)
{
Socket s;
try
{
s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
catch (Exception error)
{
MessageBox.Show("Error : " + error.Message);
return;
}
MessageBox.Show("Oke");
}
Any thoughts how to proceed?

Socket reuse not working

I have got the following two functions to start and stop a 'local server' (Socket listener).
public String startServer(Int32 port, Int32 maximumPendingConnections, ref String errorMsg) {
try {
// Creates one SocketPermission object for access restrictions
permission = new SocketPermission(
NetworkAccess.Accept, // Allowed to accept connections
TransportType.Tcp, // Defines transport types
"", // The IP addresses of local host
SocketPermission.AllPorts // Specifies all ports
);
// Listening Socket object
sListener = null;
// Ensures the code to have permission to access a Socket
permission.Demand();
// Resolves a host name to an IPHostEntry instance
IPHostEntry ipHost = Dns.GetHostEntry("");
// Gets first IP address associated with a localhost
ipAddr = ipHost.AddressList[0];
// Creates a network endpoint
ipEndPoint = new IPEndPoint(ipAddr, port);
// Create one Socket object to listen the incoming connection
sListener = new Socket(
ipAddr.AddressFamily,
SocketType.Stream,
ProtocolType.Tcp
);
// Associates a Socket with a local endpoint
sListener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); //newly added as an answer
sListener.Bind(ipEndPoint);
sListener.Listen(maximumPendingConnections);
// Begins an asynchronous operation to accept an attempt
AsyncCallback aCallback = new AsyncCallback(AcceptCallback);
sListener.BeginAccept(aCallback, sListener);
} catch (Exception e) {
//ErrorHandling
}
return ipAddr.ToString();
}
Stop Connection:
public void stopServer(ref String errorMsg) {
try {
sListener.Shutdown(SocketShutdown.Both);
sListener.Disconnect(true);
sListener.Close();
sListener.Dispose();
} catch (Exception e) {
//Errorhandling
}
}
I have found on SO that you cannot reuse a socket, however if you set sListener.Disconnect(true); it should be able to reuse it. Besides I'm creating a new socket every time on starting. What am I missing here?
It gives the error back that every socket can only be used once. It gives an error on sListener.Bind(ipEndPoint);
#Edit 14:41 - 16-12-2015
I have found that if I add the following line of code before the sListener.Bind(ipEndPoint); It works;
sListener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
If you want to actually to reuse the socket, don't do Shutdown, Close and Dispose, since these calls return the resources used by the socket to the OS. Basically, your socket handler becomes invalid and the work done by Disconnect(true) is futile then.
(You also don't need to do Shutdown and Close at the same time. Just Close will do the trick.)
The Connected property will always return false because socket is in listening state, not connected. Unfortunately, is not possible to "unlisten" the socket so you have to close it and create new socket.
Another issue is: the sequence Shutdown, Disconnect, Close and Dispose looks like kicking the dead body.

Catch an AsyncCallback

As you can see in the code below I'm calling connect with an IP and port.
s.EndConnect(ar) is throwing ObjectDisposedException if the server is not running. Now if this happens I want to wait 5 seconds and retry. The problem is catching it in the ConnectCallback and calling itself doesn't work since the object IAsyncResult ar is disposed? I'm not storing the IP and port globally.
Now obviously I can store them globally and fix it that way, but I'm wondering if there's something else to fix this. Since I don't need the IP and port anywhere else storing them globally seems unnecessary.
Socket s;
public ClientSettings()
{
s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
public void Connect(string IP, int port)
{
/* Simple connection method */
try
{
IPEndPoint ep = new IPEndPoint(IPAddress.Parse(IP), port);
s.BeginConnect(ep, new AsyncCallback(ConnectCallback), s);
}
catch { }
}
void ConnectCallback(IAsyncResult ar)
{
s.EndConnect(ar);
connected = true;
byte[] buffer = new byte[8192];
s.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReadCallback), buffer);
}
You're using outdated APIs. Use await with Socket and the problem goes away at much better code quality.
Or, use synchronous IO. This is appropriate if there will only be a few dozen connections at a time. This results in even easier code.
Alternatively, make IP and port instance variables. No need for globals.

Socket.Connect Throws and Error I can't catch

I apologize if this has been answered on SO. I looked but didn't find it. My situation is my customer can connect to their TCP server either by being on the local network, or coming in remotely via a Verizon modem. (I am using .NET 3.5 - C#)
When I connect from either of those, things are fine. But what if I am accidentally on the "wrong" network (ex: I am at Starbucks and logged onto their wireless network. I forget, thinking I am on the Verizon card, so, now I try to log in) The server refuses the connection. Fine. But my Try/Catch is not catching anything... it simply exits the routine (if I am calling it through threadpool) or it hangs if I call it directly.
Here is the code (it fails on: m_clientSocket.Connect(ipEnd) ):
tcpConnectionObject passedTCPObject = (tcpConnectionObject) obj;
if (checkNetStat(passedTCPObject) == false)
{
updateStatus(false);
return;
}
try
{
m_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = IPAddress.Parse(passedTCPObject.ipString);
int iPortNo = System.Convert.ToInt16(passedTCPObject.portString);
IPEndPoint ipEnd = new IPEndPoint(ip, iPortNo);
m_clientSocket.Connect(ipEnd);
if (m_clientSocket.Connected)
{
updateStatus(true);
//Wait for data asynchronously
WaitForData();
}
}
catch (SocketException e)
{
updateStatus(false);
return;
}
catch (Exception e)
{
updateStatus(false);
return;
}
updateStatus(true);
return ;
I call this from a Winform using the threadpool:
tcpConnectionObject passObject = new tcpConnectionObject(serverIP, serverPORT);
ThreadPool.QueueUserWorkItem(new WaitCallback(SRVR_CONNECT.connectToTCP), passObject);
This is called in the form's SHOW() method. When I do it like this, my form shows, but the status is never changed (which it should be by any result) If I put a debugger on it, and start stepping through the execution, I get to the Socket.Connect() and the debugger simply exits the mthod, and my form shows. I never hit any of my catches.
I have tried every error that Socket can generate, but it never catches anything. When I run my debugger, as soon as I hit that line, it exits my method, but there is no error that is catch-able.
If you really are waiting asynchronously (as you state in your comment), then you may be exiting the try/catch block before you actually get the exception.
It exits your method because you have a return statement inside of your catch block. You are telling it to return explicitly.
OK, I think Peter was on the right track. it seems like the debugger was simply skipping over my Connect line and moving on to the next line while waiting for the Socket.Connect() to finish (if that makes sense?)
Here's a change in the code that works... I move the packet creation, and the callback definition out of "WaitForData" and use the beginConnect method instead. Then I can set a timeout, which lets me know it fails -- so the code is changed to this:
try
{
m_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Cet the remote IP address
IPAddress ip = IPAddress.Parse(passedTCPObject.ipString);
int iPortNo = System.Convert.ToInt16(passedTCPObject.portString);
// Create the end point
ipEnd = new IPEndPoint(ip, iPortNo);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
SocketPacket theSocPkt = new SocketPacket();
if (m_pfnCallBack == null)
{
m_pfnCallBack = new AsyncCallback(OnDataReceived);
}
// Give It 5 Seconds to connect
IAsyncResult result = socket.BeginConnect(ipEnd, m_pfnCallBack, theSocPkt);
bool success = result.AsyncWaitHandle.WaitOne(5000, true);
if (!success)
{
socket.Close();
throw new ApplicationException("Server Refused Connection");
}
// Success
updateStatus(true);
}
catch (SocketException e)
{
updateStatus(false);
return;
}
catch (Exception e)
{
updateStatus(false);
return;
}

Trying to start a listener socket

I have tried to follow the exmaple on the MSDN to create an async server. But nothing seems to be able to connect to it.
http://msdn.microsoft.com/en-us/library/5w7b7x5f.aspx
Here's what I have...
Also notice the AddressList[2], this is not a mistake ;)
private static Socket mListenerSocket;
IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
IPEndPoint localEP = new IPEndPoint(ipHostInfo.AddressList[2], port);
// This line outputs 192.168.0.6:6809 (which is correct)
Console.WriteLine("{0}", localEP.ToString());
mListenerSocket = new Socket(
ipHostInfo.AddressList[2].AddressFamily,
SocketType.Stream,
ProtocolType.Tcp);
mListenerSocket.Bind(localEP);
mListenerSocket.Listen(10);
mListenerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mListenerSocket);
My callback mathod is defined as:
private static void AcceptCallback(IAsyncResult ar)
{
// It does not even get here
mListenerSocket.EndAccept(ar);
}
I would expect when I telnet using 'telnet 192.168.0.6 6809' it should jump to the AcceptCallback method, but it doesn't, so a connection isnt established.
So any ideas why it doesnt work? The are no errors to help me :(
I have tried using a TcpListener instead, but again to still no avail :(
mListenerSocket = new TcpListener(IPAddress.Any, port);
mListenerSocket.Start();
mListenerSocket.BeginAcceptSocket(new AsyncCallback(AcceptCallback), mListenerSocket);
My firewall was preventing connections to the client. Even though I disabled it, I had to restart Visual Studio to capture it.

Categories