Start receiving again Socket Error - c#

I've been stuck on a problem for some time now, when sending a request from client to server, the server responds with data pulled from sql database and client receives it, everything going fine. The problem is when the client again asks for data from server, which gives me following error: Objectreference not set to an instance of object. Thing is, when adding data to my database, the server can receive multiple requests. According to my try catches, the error occurs when my SendCallback calls my method to start receive data.
private static void BeginAccept()
{
listener.Listen(5);
Thread t = new Thread(() =>
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener));
t.Start();
}
private static void AcceptCallback(IAsyncResult ar)
{
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
handler.BeginReceive(recBuf, 0, bufsize, 0, new AsyncCallback(ReceiveCallback), handler);
Console.WriteLine("client connected" );
}
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
Console.WriteLine("Waiting for data...");
string content = string.Empty;
string[] pieces = null;
string[] delimiters = { "|" };
/*StateObject state = (StateObject)ar.AsyncState; */// Calling the socket from AcceptCallback.
Socket handler = (Socket)ar.AsyncState;
sb.Clear();
int dataReceived = handler.EndReceive(ar);
if (dataReceived > 0)
{
sb.Append(Encoding.ASCII.GetString(recBuf, 0,dataReceived));
if (content.IndexOf("<!ReqDB>") > -1)
{
try
{
Console.WriteLine("Following data received: " + content);
pieces = null;
pieces = content.Split(delimiters, StringSplitOptions.None);
sb = null;
Console.WriteLine("ReqDB received!!");
Int64 ID = Int64.Parse(pieces[0]);
RetrieveDataFromDB(handler, ID);
//Some other irrelevant code....
RetrieveDataFromDB pulls data out of the database, converts it and calls Send(handler, data);
private static void Send(Socket handler, string data)
{
byte[] byteData = Encoding.ASCII.GetBytes(data);
handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
Socket handler = (Socket)ar.AsyncState;
byte[] buffer = new byte[1024];
int bytesSend = handler.EndSend(ar);
handler.BeginReceive(recBuf, 0, bufsize, 0, new AsyncCallback(ReceiveCallback), handler);
}
catch (Exception e)
{
Console.WriteLine("Line 197: "+e.ToString());
}
}
Somewhere, probably when SendCallback executes handler.beginReceive and the method is called, the error occurs, and I do not know where the error is, or what is causing the error. I assume it is the handler, though I do not understand why it's causing it.

Related

How to send two images from server to client with socket programming (TCP)?

I want to send some images from server to client. I want when user connect to server and request for images, i sent some images to that. I searched but all of answers about send one image from client to server not server to client!
I wrote below code for send one image from server to client, but i get below error in runtime, because i shutdown socket and then called 'SendCallback' method. Where i shutdown and close socket?
public class ImageSocketServer
{
public class StateObject
{
// Client socket.
public Socket WorkSocket = null;
// Size of receive buffer.
public const int BufferSize = 256;
// Receive buffer.
public byte[] Buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public ManualResetEvent AllDone = new ManualResetEvent(false);
private static ManualResetEvent sendDone = new ManualResetEvent(false);
private Socket handler;
public void StartListening(string ip, int port)
{
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(ip), port);
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(serverEndPoint);
listener.Listen(port);
while (true)
{
AllDone.Reset();
listener.BeginAccept(AcceptCallback, listener);
AllDone.WaitOne();
}
}
private void AcceptCallback(IAsyncResult asyncResult)
{
AllDone.Set();
Socket listener = (Socket)asyncResult.AsyncState;
Socket handler = listener.EndAccept(asyncResult);
StateObject state = new StateObject { WorkSocket = handler };
handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0,
ReadCallback, state);
}
private void ReadCallback(IAsyncResult asyncResult)
{
string content = string.Empty;
StateObject state = (StateObject)asyncResult.AsyncState;
handler = state.WorkSocket;
int bytesRead = handler.EndReceive(asyncResult);
if (bytesRead > 0)
{
state.sb.Append(Encoding.UTF8.GetString(state.Buffer, 0, bytesRead));
content = state.sb.ToString();
if (content.IndexOf(Cache.EndOfMessage, StringComparison.Ordinal) > -1)
{
//Send(handler, #"C:\Users\f.hashemian\Pictures\Camera Roll\test.jpg");
SendImage(handler, #"C:\Users\f.hashemian\Pictures\Camera Roll\test.jpg");
//
}
else
{
handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, ReadCallback, state);
}
}
}
private void SendImage(Socket client, string imagePath)
{
byte[] imgBuff = File.ReadAllBytes(imagePath);
var length = imgBuff.Length;
Send(client, BitConverter.GetBytes(length));
sendDone.WaitOne();
Send(client, imgBuff);
sendDone.WaitOne();
//Here close connection and i have error in SendCallback
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
private void Send(Socket client, byte[] byteData)
{
// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), client);
}
private void SendCallback(IAsyncResult asyncResult)
{
try
{
Socket handler = (Socket)asyncResult.AsyncState;
int byteSent = handler.EndSend(asyncResult);
sendDone.Set();
//
}
catch (Exception ex)
{
throw ex;
}
}
}
This is about send one image with send size of image and then send image to client. If you have any tutorial about some images, please send link here
According to MSDN documentation https://learn.microsoft.com/en-us/dotnet/api/system.threading.manualresetevent.set?view=netframework-1.1#System_Threading_ManualResetEvent_Set, you should call Reset() method after calling WaitOne() on ManualResetEvent to set it in nonsignaled state.
private void SendImage(Socket client, string imagePath)
{
byte[] imgBuff = File.ReadAllBytes(imagePath);
var length = imgBuff.Length;
Send(client, BitConverter.GetBytes(length));
sendDone.WaitOne();
sendDone.Reset();
Send(client, imgBuff);
sendDone.WaitOne();
sendDone.Reset();
//Here close connection and i have error in SendCallback
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
Otherwise, the second WaitOne() will be skipped (since the event is in signaled state) and the Shutdown() method will be called. As a result, you will receive an exception in SendCallback, because the connection is already closed. In your case, it is better to use AutoResetEvent https://learn.microsoft.com/en-us/dotnet/api/system.threading.autoresetevent?view=netframework-4.8 which resets automatically after releasing a single waiting thread.

HTTP GET (with Header 'Connection: keep alive') over TCP

I want to do the following with a raw C# socket. I understand that usually the most appropriate way is via HTTP, with a HTTP client. The browser understands that this connection must be kept open in some way.
http://server.domain.com/protocol/do_something.txt
I am trying the following in C#, but have had no luck. What am I doing wrong? Is there a header missing? Should I be encoding what I'm sending to the server in some way? For the ReceiverSocket client, I'm using the following code, but it's just a very standard asynchronous socket client: https://stackoverflow.com/a/10390066/971580
ReceiverSocket socket = new ReceiverSocket("server.domain.com", 80);
socket.Connect();
System.Threading.Thread.Sleep(1000);
String message = "GET /protocol/do_something.txt HTTP/1.1";
message += "\r\n";
message += "\r\n";
socket.Send(message);
The socket can connect successfully, but I don't get any response when I send anything to the server. This is how I am connecting, sending and receiving.t (Apologies: I tried to do this in snippets, rather than including all the methods, but it looked horrid. . .)
public ReceiverSocket(String address, int port) : base(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
{
messageQueue = new Queue<MessageBase>();
IPHostEntry ipHostInfo = Dns.GetHostEntry(address);
IPAddress ipAddress = ipHostInfo.AddressList[0];
remoteEP = new IPEndPoint(ipAddress, port);
}
public void Connect()
{
this.BeginConnect(remoteEP, ConnectCallback, this);
}
private void ConnectCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
if (client.Connected)
{
client.EndConnect(ar);
Console.WriteLine("Connect Callback - Connected");
StateObject state = new StateObject();
state.workSocket = client;
state.BufferSize = 8192;
if (SocketConnected != null)
SocketConnected(client);
client.BeginReceive(state.Buffer, state.readOffset, state.BufferSize - state.readOffset, 0, ReceiveCallback, state);
}
else
{
Thread.Sleep(5000);
Connect();
}
}
catch (Exception ex)
{
Reconnect();
}
}
private void ReceiveCallback(IAsyncResult ar)
{
Console.WriteLine("Never gets here. . . ");
try
{
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
if (client.Connected)
{
int bytesRead = client.EndReceive(ar);
foreach (MessageBase msg in MessageBase.Receive(client, bytesRead, state))
{
// Add objects to the message queue
lock (this.messageQueue)
this.messageQueue.Enqueue(msg);
}
if (DataRecieved != null)
DataRecieved(client, null);
client.BeginReceive(state.Buffer, state.readOffset, state.BufferSize - state.readOffset, 0, ReceiveCallback, state);
}
else
{
Reconnect();
}
}
catch (SocketException)
{
Reconnect();
}
}
public void Send(String msg)
{
try
{
byte[] bytes = GetBytes(msg);
if (this.Connected)
{
Console.WriteLine("Sending: " + msg);
this.BeginSend(bytes, 0, bytes.Length, 0, SendCallback, this);
}
else
{
Reconnect();
}
}
catch (SocketException sox)
{
Reconnect();
}
catch (Exception ex)
{
int i = 0;
}
}
static byte[] GetBytes(string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
}
public class StateObject
{
public Socket workSocket = null;
public int readOffset = 0;
public StringBuilder sb = new StringBuilder();
private int bufferSize = 0;
public int BufferSize
{
set
{
this.bufferSize = value;
buffer = new byte[this.bufferSize];
}
get { return this.bufferSize; }
}
private byte[] buffer = null;
public byte[] Buffer
{
get { return this.buffer; }
}
}
Shouldn't the fact that I haven't included the message += "Connection: close" header mean that the socket should just start sending whatever data it has asynchronously? Just to note also: I can connect successfuly using Telnet and send the data, just not with a socket yet!
Any pointers at all would be appreciated.
Thanks.
Do NOT call Send() until ConnectCallback() is called first, otherwise you risk sending your data prematurely. Using Sleep() to wait for the connection is wrong.
Do NOT call BeginReceive() until after Send() has finished sending the data.
Because you are using HTTP 1.1, then yes, the connection is kept alive by default if you are connecting to an HTTP 1.1 server. The server's Connection response header will indicate whether the server is actually keeping the connection open or not.
Also, as stated by someone else, HTTP 1.1 requests MUST have a Host header or else the request is malformed and can be rejected/ignored by the server. HTTP 1.1 has a notion of virtual hosts running on the same IP, so the Host header tells the server which host the client wants to talk to.

TCP Server : "Only one usage of each socket address (protocol/network address/port) is normally permitted."

I have a TCP server (implemented as a windows service) for listening to GPS devices in a vehicle tracking application, after random period of time from its operation I got the following error : "Only one usage of each socket address (protocol/network address/port) is normally permitted." While I am sure that I am closing every socket after using it. so can anyone tell me what is the problem here I have the MaxUserPort value in windows server 2008 registry with (65534) and the TCPTimeWaitDelay value with (30 seconds) ?
Here is the code:
1) The Main Thread :
private void MainThread() {
byte[] bytes = new Byte[1024];
IPEndPoint localEndPoint = new IPEndPoint(0, this.port);
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp );
// Addedd on [20/03/2012] by Sherif Mosaad for handling socket exceptions ...
//listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, (int)1);
try {
listener.Bind(localEndPoint);
listener.Listen(100);
while (active) {
mainDone.Reset();
listener.BeginAccept(new AsyncCallback(AcceptCallback),listener);
while (active)
if (mainDone.WaitOne(100, true))
break;
}
listener.Shutdown(SocketShutdown.Both);
listener.Close();
Thread.Sleep(2000);
} catch (Exception e) {
if (OnError != null)
OnError(this, e.ToString());
LogManager.LogError(e, "TCPSimpleServer MainThread");
}
}
2) The AcceptCallback handler:
private void AcceptCallback(IAsyncResult ar) {
mainDone.Set();
Socket listener = (Socket)ar.AsyncState;
Socket handler = null;
try
{
handler = listener.EndAccept(ar);
}
catch
{
try
{
listener.Shutdown(SocketShutdown.Both);
listener.Close();
Thread.Sleep(2000);
}
catch { return; }
}
if (OnConnect != null)
OnConnect(this, handler);
StateObject state = new StateObject();
state.workSocket = handler;
state.endPoint = (IPEndPoint)handler.RemoteEndPoint;
stateObjectDictionary.Add(state, state.workSocket);
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
3) The ReadCallback Handler:
private void ReadCallback(IAsyncResult ar) {
String content = String.Empty;
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
int bytesRead = 0;
try
{
bytesRead = handler.EndReceive(ar);
}
catch (Exception e)
{
// Connection closed by client
if (OnDisconnect != null)
OnDisconnect(this, state.endPoint);
return;
}
if (bytesRead > 0)
{
string data = Encoding.ASCII.GetString(state.buffer, 0, bytesRead);
if (OnDataAvailable != null)
OnDataAvailable(this, handler, data);
try
{
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
catch (Exception e)
{
// Connection closed by client
if (OnDisconnect != null)
OnDisconnect(this, state.endPoint);
return;
}
}
else
{
// Connection closed by peer
if (OnDisconnect != null)
OnDisconnect(this, state.endPoint);
}
}
Finally the state object :
public class StateObject
{
public Socket workSocket = null;
public const int BufferSize = 1024;
public byte[] buffer = new byte[BufferSize];
public StringBuilder sb = new StringBuilder();
public IPEndPoint endPoint;
}
Any help please?
There's a race condition. You call mainDone.Set which allows another thread to proceed to BeginAccept while the current thread moves towards EndAccept. Which will get there first? If you start accepting before finishing the previous accept, I suspect this error might pop up.
Fix? You need to set mainDone event after you call EndAccept
Even better, follow a simpler pattern without synchronization primitives. I outline one here.

C# Async Server/Client Architecture

first post ever on stack overflow!
Anyway...I'm trying to teach myself networking programming in my spare time and I've reached a snag I just cant wrap my head around. After playing with synchronous networking methodology over a few days I decided to make a client/server program that could:
Handle multiple concurrent connections
Handle multiple streams of communication
Have true two way communication
On a more general level I want to make a chat program. Multiple client connections to a server that can send and receive data individually with no problems...but also have the server send data from each client to the others.
Now I haven't gotten as far as I'd like to yet so I'm here for a little guidance. I can't seem to get my loops working properly and I'm sure it has to do with the asynchronous nature of the code...for whatever reason I just can't seem to figure out whats wrong. Here's the the blocks of code:
Server.cs
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
// State object for reading client data asynchronously
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public class AsynchronousSocketListener
{
// Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false);
public AsynchronousSocketListener()
{
}
public static void StartListening()
{
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
// Establish the local endpoint for the socket.
// The DNS name of the computer
// running the listener is "host.contoso.com".
//IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
//IPAddress ipAddress = ipHostInfo.AddressList[0];
IPAddress ipAddress = System.Net.IPAddress.Loopback;
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 3000);
// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(100);
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
public static void AcceptCallback(IAsyncResult ar)
{
// Signal the main thread to continue.
allDone.Set();
// Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
public static void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(
state.buffer, 0, bytesRead));
// Check for end-of-file tag. If it is not there, read
// more data.
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -1)
{
// All the data has been read from the
// client. Display it on the console.
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
content.Length, content);
// Echo the data back to the client.
Send(handler, content);
}
else
{
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}
private static void Send(Socket handler, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket handler = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public static int Main(String[] args)
{
StartListening();
return 0;
}
}
Client.cs
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 256;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public class Program
{
public static ManualResetEvent connectDone = new ManualResetEvent(false);
public static ManualResetEvent sendDone = new ManualResetEvent(false);
public static ManualResetEvent receiveDone = new ManualResetEvent(false);
public static void Connect(EndPoint remoteEP, Socket client)
{
client.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
}
private static void ConnectCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
Console.WriteLine("Socket connected to {0}",
client.RemoteEndPoint.ToString());
// Signal that the connection has been made.
connectDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Send(Socket client, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, SocketFlags.None,
new AsyncCallback(SendCallback), client);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", bytesSent);
// Signal that all bytes have been sent.
sendDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Receive(Socket client)
{
try
{
// Create the state object.
StateObject state = new StateObject();
state.workSocket = client;
// Begin receiving the data from the remote device.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
// Read data from the remote device.
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
// Get the rest of the data.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
else
{
// All the data has arrived; put it in response.
if (state.sb.Length > 1)
{
string response = state.sb.ToString();
Console.WriteLine(response);
}
// Signal that all bytes have been received.
receiveDone.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
static void Main(string[] args)
{
IPAddress ipAddress = System.Net.IPAddress.Loopback;
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 3000);
Socket sock = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
Connect(localEndPoint, sock);
string packet;
while (true)
{
packet = Console.ReadLine();
packet += "<EOF>";
Send(sock, packet);
Receive(sock);
connectDone.WaitOne();
}
}
}
You don't need any loops or waithandles when you go asynchronous. Just fire away another beginAccept inside AcceptCallback and you server will start listening again after accepting a client.
If your problem is that the server responses only once and then shuts down, then, well, that is what you say it to do in a SendCallback - it sends stuff and then shuts down. Call handler.beginReceive instead of handler.shutdown (you'll have to carry your StateObject all the way down to this callback, not just handler).

Async socket crashes when I close the socket

The code shown below appears to almost work. If I create an instance of it and call "Connect" all works fine. When I call "Disconnect", sometimes everything is fine (mainly if I add a breakpoint and step through the function slowly). If I don't use a breakpoint the class(being hosted as a win forms app) seems to disappear (the form does) but visual studio still thinks it's running. In visual studio's output window I get "A first chance exception of type 'System.ObjectDisposedException' occurred in System.dll". Can anyone spot what I'm doing wrong?
// State object for reading client data asynchronously
public class StateObject
{
private Guid ID = Guid.NewGuid();
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
}
public class NetworkComms : IBasePanel
{
private static ILog _log = LogManager.GetCurrentClassLogger();
// ManualResetEvent instances signal completion.
private static ManualResetEvent connectDone = new ManualResetEvent(false);
private static ManualResetEvent sendDone = new ManualResetEvent(false);
private static ManualResetEvent receiveDone = new ManualResetEvent(false);
private static Socket _client = null;
private static IPEndPoint _endpoint = null;
public event ReceiveMessageEventHandler OnReceiveMessage;
public NetworkComms(string address, int port)
{
_endpoint = new IPEndPoint(GetIPAddress(address), port);
}
private IPAddress GetIPAddress(string address)
{
IPAddress ipAddress = null;
if (IPAddress.TryParse(address, out ipAddress))
{
return ipAddress;
}
else
{
IPHostEntry ipHostInfo = Dns.GetHostEntry(address);
return ipHostInfo.AddressList[ipHostInfo.AddressList.Count() - 1];
}
}
private void ConnectCallback(IAsyncResult ar)
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
_log.DebugFormat("Socket connected to {0}", client.RemoteEndPoint.ToString());
// Signal that the connection has been made.
connectDone.Set();
}
private void Receive()
{
// Create the state object.
StateObject state = new StateObject();
state.workSocket = _client;
// Begin receiving the data from the remote device.
_client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}
private void ReceiveCallback(IAsyncResult ar)
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
// Read data from the remote device.
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
ReceivedNewMessage(Encoding.Default.GetString(state.buffer, 0, bytesRead));
// Get the rest of the data.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}
else
{
// Signal that all bytes have been received.
receiveDone.Set();
}
}
private static void SendCallback(IAsyncResult ar)
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
_log.DebugFormat("Sent {0} bytes to server.", bytesSent);
// Signal that all bytes have been sent.
sendDone.Set();
}
public void SendMessage(byte[] message)
{
_client.BeginSend(message, 0, message.Length, 0, new AsyncCallback(SendCallback), _client);
sendDone.WaitOne();
}
public void Connect()
{
_client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_client.BeginConnect(_endpoint, new AsyncCallback(ConnectCallback), _client);
connectDone.WaitOne();
Receive();
}
public void Disconnect()
{
try
{
_client.Shutdown(SocketShutdown.Both);
_client.Close();
}
finally
{
_client = null;
connectDone.Reset();
sendDone.Reset();
receiveDone.Reset();
}
}
private void ReceivedNewMessage(string message)
{
if (this.OnReceiveMessage != null)
{
this.OnReceiveMessage(message);
}
}
public bool IsConnected
{
get
{
if (_client == null) return false;
return _client.Connected;
}
}
}
All of your callbacks need to handle exceptions, which are relativly common in network programming.
In this case what is probably happening is that client.EndReceive(ar); is throwing an ObjectDisposedException because the socket is already closed when its called.

Categories

Resources